diff --git a/.fern/metadata.json b/.fern/metadata.json new file mode 100644 index 0000000..26ba3d9 --- /dev/null +++ b/.fern/metadata.json @@ -0,0 +1,10 @@ +{ + "cliVersion": "1.0.4", + "generatorName": "fernapi/fern-typescript-node-sdk", + "generatorVersion": "3.29.2", + "generatorConfig": { + "includeApiReference": true, + "namespaceExport": "Pipedream", + "noSerdeLayer": false + } +} diff --git a/.npmignore b/.npmignore deleted file mode 100644 index c0c40ac..0000000 --- a/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -node_modules -src -tests -.gitignore -.github -.fernignore -.prettierrc.yml -biome.json -tsconfig.json -yarn.lock -pnpm-lock.yaml \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fe5bc2f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,133 @@ +# Contributing + +Thanks for your interest in contributing to this SDK! This document provides guidelines for contributing to the project. + +## Getting Started + +### Prerequisites + +- Node.js 20 or higher +- pnpm package manager + +### Installation + +Install the project dependencies: + +```bash +pnpm install +``` + +### Building + +Build the project: + +```bash +pnpm build +``` + +### Testing + +Run the test suite: + +```bash +pnpm test +``` + +Run specific test types: +- `pnpm test:unit` - Run unit tests +- `pnpm test:wire` - Run wire/integration tests + +### Linting and Formatting + +Check code style: + +```bash +pnpm run lint +pnpm run format:check +``` + +Fix code style issues: + +```bash +pnpm run lint:fix +pnpm run format:fix +``` + +Or use the combined check command: + +```bash +pnpm run check:fix +``` + +## About Generated Code + +**Important**: Most files in this SDK are automatically generated by [Fern](https://buildwithfern.com) from the API definition. Direct modifications to generated files will be overwritten the next time the SDK is generated. + +### Generated Files + +The following directories contain generated code: +- `src/api/` - API client classes and types +- `src/serialization/` - Serialization/deserialization logic +- Most TypeScript files in `src/` + +### How to Customize + +If you need to customize the SDK, you have two options: + +#### Option 1: Use `.fernignore` + +For custom code that should persist across SDK regenerations: + +1. Create a `.fernignore` file in the project root +2. Add file patterns for files you want to preserve (similar to `.gitignore` syntax) +3. Add your custom code to those files + +Files listed in `.fernignore` will not be overwritten when the SDK is regenerated. + +For more information, see the [Fern documentation on custom code](https://buildwithfern.com/learn/sdks/overview/custom-code). + +#### Option 2: Contribute to the Generator + +If you want to change how code is generated for all users of this SDK: + +1. The TypeScript SDK generator lives in the [Fern repository](https://github.com/fern-api/fern) +2. Generator code is located at `generators/typescript/sdk/` +3. Follow the [Fern contributing guidelines](https://github.com/fern-api/fern/blob/main/CONTRIBUTING.md) +4. Submit a pull request with your changes to the generator + +This approach is best for: +- Bug fixes in generated code +- New features that would benefit all users +- Improvements to code generation patterns + +## Making Changes + +### Workflow + +1. Create a new branch for your changes +2. Make your modifications +3. Run tests to ensure nothing breaks: `pnpm test` +4. Run linting and formatting: `pnpm run check:fix` +5. Build the project: `pnpm build` +6. Commit your changes with a clear commit message +7. Push your branch and create a pull request + +### Commit Messages + +Write clear, descriptive commit messages that explain what changed and why. + +### Code Style + +This project uses automated code formatting and linting. Run `pnpm run check:fix` before committing to ensure your code meets the project's style guidelines. + +## Questions or Issues? + +If you have questions or run into issues: + +1. Check the [Fern documentation](https://buildwithfern.com) +2. Search existing [GitHub issues](https://github.com/fern-api/fern/issues) +3. Open a new issue if your question hasn't been addressed + +## License + +By contributing to this project, you agree that your contributions will be licensed under the same license as the project. diff --git a/README.md b/README.md index 32cdc9d..2b29985 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ import { PipedreamClient } from "@pipedream/sdk"; const client = new PipedreamClient({ clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", projectEnvironment: "YOUR_PROJECT_ENVIRONMENT", projectId: "YOUR_PROJECT_ID" }); await client.actions.run({ + projectId: "project_id", id: "id", externalUserId: "external_user_id" }); @@ -42,7 +43,7 @@ following namespace: ```typescript import { Pipedream } from "@pipedream/sdk"; -const request: Pipedream.AppsListRequest = { +const request: Pipedream.RetrieveAppCategoriesRequest = { ... }; ``` @@ -464,30 +465,19 @@ List endpoints are paginated. The SDK provides an iterator so that you can simpl import { PipedreamClient } from "@pipedream/sdk"; const client = new PipedreamClient({ clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", projectEnvironment: "YOUR_PROJECT_ENVIRONMENT", projectId: "YOUR_PROJECT_ID" }); -const response = await client.apps.list({ - after: "after", - before: "before", - limit: 1, - q: "q", - sortKey: "name", - sortDirection: "asc" -}); -for await (const item of response) { +const pageableResponse = await client.apps.list(); +for await (const item of pageableResponse) { console.log(item); } // Or you can manually iterate page-by-page -let page = await client.apps.list({ - after: "after", - before: "before", - limit: 1, - q: "q", - sortKey: "name", - sortDirection: "asc" -}); +let page = await client.apps.list(); while (page.hasNextPage()) { page = page.getNextPage(); } + +// You can also access the underlying response +const response = page.response; ``` ## Advanced @@ -570,6 +560,69 @@ console.log(data); console.log(rawResponse.headers['X-My-Header']); ``` +### Logging + +The SDK supports logging. You can configure the logger by passing in a `logging` object to the client options. + +```typescript +import { PipedreamClient, logging } from "@pipedream/sdk"; + +const client = new PipedreamClient({ + ... + logging: { + level: logging.LogLevel.Debug, // defaults to logging.LogLevel.Info + logger: new logging.ConsoleLogger(), // defaults to ConsoleLogger + silent: false, // defaults to true, set to false to enable logging + } +}); +``` +The `logging` object can have the following properties: +- `level`: The log level to use. Defaults to `logging.LogLevel.Info`. +- `logger`: The logger to use. Defaults to a `logging.ConsoleLogger`. +- `silent`: Whether to silence the logger. Defaults to `true`. + +The `level` property can be one of the following values: +- `logging.LogLevel.Debug` +- `logging.LogLevel.Info` +- `logging.LogLevel.Warn` +- `logging.LogLevel.Error` + +To provide a custom logger, you can pass in an object that implements the `logging.ILogger` interface. + +
+Custom logger examples + +Here's an example using the popular `winston` logging library. +```ts +import winston from 'winston'; + +const winstonLogger = winston.createLogger({...}); + +const logger: logging.ILogger = { + debug: (msg, ...args) => winstonLogger.debug(msg, ...args), + info: (msg, ...args) => winstonLogger.info(msg, ...args), + warn: (msg, ...args) => winstonLogger.warn(msg, ...args), + error: (msg, ...args) => winstonLogger.error(msg, ...args), +}; +``` + +Here's an example using the popular `pino` logging library. + +```ts +import pino from 'pino'; + +const pinoLogger = pino({...}); + +const logger: logging.ILogger = { + debug: (msg, ...args) => pinoLogger.debug(args, msg), + info: (msg, ...args) => pinoLogger.info(args, msg), + warn: (msg, ...args) => pinoLogger.warn(args, msg), + error: (msg, ...args) => pinoLogger.error(args, msg), +}; +``` +
+ + ### Runtime Compatibility diff --git a/biome.json b/biome.json index b6890df..a777468 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.2.5/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", "root": true, "vcs": { "enabled": false @@ -7,16 +7,21 @@ "files": { "ignoreUnknown": true, "includes": [ - "./**", - "!dist", - "!lib", - "!*.tsbuildinfo", - "!_tmp_*", - "!*.tmp", - "!.tmp/", - "!*.log", - "!.DS_Store", - "!Thumbs.db" + "**", + "!!dist", + "!!**/dist", + "!!lib", + "!!**/lib", + "!!_tmp_*", + "!!**/_tmp_*", + "!!*.tmp", + "!!**/*.tmp", + "!!.tmp/", + "!!**/.tmp/", + "!!*.log", + "!!**/*.log", + "!!**/.DS_Store", + "!!**/Thumbs.db" ] }, "formatter": { diff --git a/package.json b/package.json index de4dd44..af1b497 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/sdk", - "version": "2.2.0", + "version": "2.2.1", "private": false, "repository": "github:PipedreamHQ/pipedream-sdk-typescript", "type": "commonjs", @@ -10,11 +10,6 @@ "exports": { ".": { "types": "./dist/cjs/index.d.ts", - "browser": { - "types": "./dist/esm/browser/index.d.mts", - "import": "./dist/esm/browser/index.mjs", - "default": "./dist/esm/browser/index.mjs" - }, "import": { "types": "./dist/esm/index.d.mts", "default": "./dist/esm/index.mjs" @@ -25,18 +20,6 @@ }, "default": "./dist/cjs/index.js" }, - "./browser": { - "types": "./dist/esm/browser/index.d.mts", - "import": { - "types": "./dist/esm/browser/index.d.mts", - "default": "./dist/esm/browser/index.mjs" - }, - "require": { - "types": "./dist/cjs/browser/index.d.ts", - "default": "./dist/cjs/browser/index.js" - }, - "default": "./dist/esm/browser/index.mjs" - }, "./serialization": { "types": "./dist/cjs/serialization/index.d.ts", "import": { @@ -49,18 +32,6 @@ }, "default": "./dist/cjs/serialization/index.js" }, - "./server": { - "types": "./dist/cjs/index.d.ts", - "import": { - "types": "./dist/esm/index.d.mts", - "default": "./dist/esm/index.mjs" - }, - "require": { - "types": "./dist/cjs/index.d.ts", - "default": "./dist/cjs/index.js" - }, - "default": "./dist/cjs/index.js" - }, "./package.json": "./package.json" }, "files": [ @@ -83,6 +54,7 @@ "test:unit": "vitest --project unit", "test:wire": "vitest --project wire" }, + "dependencies": {}, "devDependencies": { "webpack": "^5.97.1", "ts-loader": "^9.5.1", @@ -90,17 +62,15 @@ "msw": "2.11.2", "@types/node": "^18.19.70", "typescript": "~5.7.2", - "@biomejs/biome": "2.2.5" + "@biomejs/biome": "2.3.1" }, "browser": { - "./dist/cjs/wrapper/utils/getBaseUrl.js": "./dist/cjs/wrapper/utils/getBaseUrl.browser.js", - "./dist/esm/wrapper/utils/getBaseUrl.mjs": "./dist/esm/wrapper/utils/getBaseUrl.browser.mjs", "fs": false, "os": false, "path": false, "stream": false }, - "packageManager": "pnpm@10.14.0", + "packageManager": "pnpm@10.20.0", "engines": { "node": ">=18.0.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6cd1ea..3110e1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: 2.2.5 - version: 2.2.5 + specifier: 2.3.1 + version: 2.3.1 '@types/node': specifier: ^18.19.70 version: 18.19.130 @@ -25,62 +25,62 @@ importers: version: 5.7.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@18.19.130)(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(terser@5.44.0) + version: 3.2.4(@types/node@18.19.130)(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(terser@5.44.1) webpack: specifier: ^5.97.1 version: 5.102.1 packages: - '@biomejs/biome@2.2.5': - resolution: {integrity: sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw==} + '@biomejs/biome@2.3.1': + resolution: {integrity: sha512-A29evf1R72V5bo4o2EPxYMm5mtyGvzp2g+biZvRFx29nWebGyyeOSsDWGx3tuNNMFRepGwxmA9ZQ15mzfabK2w==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.2.5': - resolution: {integrity: sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ==} + '@biomejs/cli-darwin-arm64@2.3.1': + resolution: {integrity: sha512-ombSf3MnTUueiYGN1SeI9tBCsDUhpWzOwS63Dove42osNh0PfE1cUtHFx6eZ1+MYCCLwXzlFlYFdrJ+U7h6LcA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.2.5': - resolution: {integrity: sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg==} + '@biomejs/cli-darwin-x64@2.3.1': + resolution: {integrity: sha512-pcOfwyoQkrkbGvXxRvZNe5qgD797IowpJPovPX5biPk2FwMEV+INZqfCaz4G5bVq9hYnjwhRMamg11U4QsRXrQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.2.5': - resolution: {integrity: sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw==} + '@biomejs/cli-linux-arm64-musl@2.3.1': + resolution: {integrity: sha512-+DZYv8l7FlUtTrWs1Tdt1KcNCAmRO87PyOnxKGunbWm5HKg1oZBSbIIPkjrCtDZaeqSG1DiGx7qF+CPsquQRcg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.2.5': - resolution: {integrity: sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ==} + '@biomejs/cli-linux-arm64@2.3.1': + resolution: {integrity: sha512-td5O8pFIgLs8H1sAZsD6v+5quODihyEw4nv2R8z7swUfIK1FKk+15e4eiYVLcAE4jUqngvh4j3JCNgg0Y4o4IQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.2.5': - resolution: {integrity: sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ==} + '@biomejs/cli-linux-x64-musl@2.3.1': + resolution: {integrity: sha512-Y3Ob4nqgv38Mh+6EGHltuN+Cq8aj/gyMTJYzkFZV2AEj+9XzoXB9VNljz9pjfFNHUxvLEV4b55VWyxozQTBaUQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.2.5': - resolution: {integrity: sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew==} + '@biomejs/cli-linux-x64@2.3.1': + resolution: {integrity: sha512-PYWgEO7up7XYwSAArOpzsVCiqxBCXy53gsReAb1kKYIyXaoAlhBaBMvxR/k2Rm9aTuZ662locXUmPk/Aj+Xu+Q==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.2.5': - resolution: {integrity: sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg==} + '@biomejs/cli-win32-arm64@2.3.1': + resolution: {integrity: sha512-RHIG/zgo+69idUqVvV3n8+j58dKYABRpMyDmfWu2TITC+jwGPiEaT0Q3RKD+kQHiS80mpBrST0iUGeEXT0bU9A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.2.5': - resolution: {integrity: sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw==} + '@biomejs/cli-win32-x64@2.3.1': + resolution: {integrity: sha512-izl30JJ5Dp10mi90Eko47zhxE6pYyWPcnX1NQxKpL/yMhXxf95oLTzfpu4q+MDBh/gemNqyJEwjBpe0MT5iWPA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -91,168 +91,168 @@ packages: '@bundled-es-modules/statuses@1.0.1': resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} - '@esbuild/aix-ppc64@0.25.11': - resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.11': - resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.11': - resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.11': - resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.11': - resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.11': - resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.11': - resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.11': - resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.11': - resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.11': - resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.11': - resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.11': - resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.11': - resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.11': - resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.11': - resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.11': - resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.11': - resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.11': - resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.11': - resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.11': - resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.11': - resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.11': - resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.11': - resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.11': - resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.11': - resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.11': - resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@inquirer/ansi@1.0.1': - resolution: {integrity: sha512-yqq0aJW/5XPhi5xOAL1xRCpe1eh8UFVgYFpFsjEqmIR8rKLyP+HINvFXwUaxYICflJrVlxnp7lLN6As735kVpw==} + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} - '@inquirer/confirm@5.1.19': - resolution: {integrity: sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -260,8 +260,8 @@ packages: '@types/node': optional: true - '@inquirer/core@10.3.0': - resolution: {integrity: sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==} + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -269,12 +269,12 @@ packages: '@types/node': optional: true - '@inquirer/figures@1.0.14': - resolution: {integrity: sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==} + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} - '@inquirer/type@3.0.9': - resolution: {integrity: sha512-QPaNt/nmE2bLGQa9b7wwyRJoLZ7pN6rcyXvzU0YCmivmJyq1BVo94G98tStRWkoD1RgDX5C+dPlhhHzNdu/W/w==} + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -311,113 +311,113 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@rollup/rollup-android-arm-eabi@4.52.5': - resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} + '@rollup/rollup-android-arm-eabi@4.53.2': + resolution: {integrity: sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.52.5': - resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} + '@rollup/rollup-android-arm64@4.53.2': + resolution: {integrity: sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.52.5': - resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} + '@rollup/rollup-darwin-arm64@4.53.2': + resolution: {integrity: sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.52.5': - resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} + '@rollup/rollup-darwin-x64@4.53.2': + resolution: {integrity: sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.52.5': - resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} + '@rollup/rollup-freebsd-arm64@4.53.2': + resolution: {integrity: sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.52.5': - resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} + '@rollup/rollup-freebsd-x64@4.53.2': + resolution: {integrity: sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.52.5': - resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': + resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.52.5': - resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} + '@rollup/rollup-linux-arm-musleabihf@4.53.2': + resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.52.5': - resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} + '@rollup/rollup-linux-arm64-gnu@4.53.2': + resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.52.5': - resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} + '@rollup/rollup-linux-arm64-musl@4.53.2': + resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.52.5': - resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} + '@rollup/rollup-linux-loong64-gnu@4.53.2': + resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.52.5': - resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} + '@rollup/rollup-linux-ppc64-gnu@4.53.2': + resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.52.5': - resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} + '@rollup/rollup-linux-riscv64-gnu@4.53.2': + resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.52.5': - resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} + '@rollup/rollup-linux-riscv64-musl@4.53.2': + resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.52.5': - resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} + '@rollup/rollup-linux-s390x-gnu@4.53.2': + resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.52.5': - resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} + '@rollup/rollup-linux-x64-gnu@4.53.2': + resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.52.5': - resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} + '@rollup/rollup-linux-x64-musl@4.53.2': + resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.52.5': - resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} + '@rollup/rollup-openharmony-arm64@4.53.2': + resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.52.5': - resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} + '@rollup/rollup-win32-arm64-msvc@4.53.2': + resolution: {integrity: sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.52.5': - resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} + '@rollup/rollup-win32-ia32-msvc@4.53.2': + resolution: {integrity: sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.52.5': - resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} + '@rollup/rollup-win32-x64-gnu@4.53.2': + resolution: {integrity: sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.52.5': - resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} + '@rollup/rollup-win32-x64-msvc@4.53.2': + resolution: {integrity: sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==} cpu: [x64] os: [win32] @@ -567,16 +567,16 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - baseline-browser-mapping@2.8.19: - resolution: {integrity: sha512-zoKGUdu6vb2jd3YOq0nnhEDQVbPcHhco3UImJrv5dSkvxTc2pl2WjOPsjZXDwPDSl5eghIMuY3R6J9NDKF3KcQ==} + baseline-browser-mapping@2.8.28: + resolution: {integrity: sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==} hasBin: true braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.27.0: - resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -587,8 +587,8 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - caniuse-lite@1.0.30001751: - resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} + caniuse-lite@1.0.30001754: + resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} @@ -641,8 +641,8 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - electron-to-chromium@1.5.238: - resolution: {integrity: sha512-khBdc+w/Gv+cS8e/Pbnaw/FXcBUeKrRVik9IxfXtgREOWyJhR4tj43n3amkVogJ/yeQUqzkrZcFhtIxIdqmmcQ==} + electron-to-chromium@1.5.250: + resolution: {integrity: sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -654,8 +654,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - esbuild@0.25.11: - resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -724,8 +724,8 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphql@16.11.0: - resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} + graphql@16.12.0: + resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} has-flag@4.0.0: @@ -766,8 +766,8 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -809,8 +809,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - node-releases@2.0.26: - resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} @@ -854,8 +854,8 @@ packages: rettime@0.7.0: resolution: {integrity: sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==} - rollup@4.52.5: - resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} + rollup@4.53.2: + resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -948,8 +948,8 @@ packages: uglify-js: optional: true - terser@5.44.0: - resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==} + terser@5.44.1: + resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} engines: {node: '>=10'} hasBin: true @@ -1020,8 +1020,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@7.1.11: - resolution: {integrity: sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==} + vite@7.2.2: + resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -1137,39 +1137,39 @@ packages: snapshots: - '@biomejs/biome@2.2.5': + '@biomejs/biome@2.3.1': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.2.5 - '@biomejs/cli-darwin-x64': 2.2.5 - '@biomejs/cli-linux-arm64': 2.2.5 - '@biomejs/cli-linux-arm64-musl': 2.2.5 - '@biomejs/cli-linux-x64': 2.2.5 - '@biomejs/cli-linux-x64-musl': 2.2.5 - '@biomejs/cli-win32-arm64': 2.2.5 - '@biomejs/cli-win32-x64': 2.2.5 - - '@biomejs/cli-darwin-arm64@2.2.5': + '@biomejs/cli-darwin-arm64': 2.3.1 + '@biomejs/cli-darwin-x64': 2.3.1 + '@biomejs/cli-linux-arm64': 2.3.1 + '@biomejs/cli-linux-arm64-musl': 2.3.1 + '@biomejs/cli-linux-x64': 2.3.1 + '@biomejs/cli-linux-x64-musl': 2.3.1 + '@biomejs/cli-win32-arm64': 2.3.1 + '@biomejs/cli-win32-x64': 2.3.1 + + '@biomejs/cli-darwin-arm64@2.3.1': optional: true - '@biomejs/cli-darwin-x64@2.2.5': + '@biomejs/cli-darwin-x64@2.3.1': optional: true - '@biomejs/cli-linux-arm64-musl@2.2.5': + '@biomejs/cli-linux-arm64-musl@2.3.1': optional: true - '@biomejs/cli-linux-arm64@2.2.5': + '@biomejs/cli-linux-arm64@2.3.1': optional: true - '@biomejs/cli-linux-x64-musl@2.2.5': + '@biomejs/cli-linux-x64-musl@2.3.1': optional: true - '@biomejs/cli-linux-x64@2.2.5': + '@biomejs/cli-linux-x64@2.3.1': optional: true - '@biomejs/cli-win32-arm64@2.2.5': + '@biomejs/cli-win32-arm64@2.3.1': optional: true - '@biomejs/cli-win32-x64@2.2.5': + '@biomejs/cli-win32-x64@2.3.1': optional: true '@bundled-es-modules/cookie@2.0.1': @@ -1180,98 +1180,98 @@ snapshots: dependencies: statuses: 2.0.2 - '@esbuild/aix-ppc64@0.25.11': + '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.11': + '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.25.11': + '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-x64@0.25.11': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.25.11': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-x64@0.25.11': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.25.11': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.25.11': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/linux-arm64@0.25.11': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm@0.25.11': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-ia32@0.25.11': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-loong64@0.25.11': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.25.11': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ppc64@0.25.11': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.25.11': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-s390x@0.25.11': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-x64@0.25.11': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.25.11': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.25.11': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.11': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.25.11': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.25.11': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/sunos-x64@0.25.11': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-arm64@0.25.11': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-ia32@0.25.11': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-x64@0.25.11': + '@esbuild/win32-x64@0.25.12': optional: true - '@inquirer/ansi@1.0.1': {} + '@inquirer/ansi@1.0.2': {} - '@inquirer/confirm@5.1.19(@types/node@18.19.130)': + '@inquirer/confirm@5.1.21(@types/node@18.19.130)': dependencies: - '@inquirer/core': 10.3.0(@types/node@18.19.130) - '@inquirer/type': 3.0.9(@types/node@18.19.130) + '@inquirer/core': 10.3.2(@types/node@18.19.130) + '@inquirer/type': 3.0.10(@types/node@18.19.130) optionalDependencies: '@types/node': 18.19.130 - '@inquirer/core@10.3.0(@types/node@18.19.130)': + '@inquirer/core@10.3.2(@types/node@18.19.130)': dependencies: - '@inquirer/ansi': 1.0.1 - '@inquirer/figures': 1.0.14 - '@inquirer/type': 3.0.9(@types/node@18.19.130) + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@18.19.130) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 @@ -1280,9 +1280,9 @@ snapshots: optionalDependencies: '@types/node': 18.19.130 - '@inquirer/figures@1.0.14': {} + '@inquirer/figures@1.0.15': {} - '@inquirer/type@3.0.9(@types/node@18.19.130)': + '@inquirer/type@3.0.10(@types/node@18.19.130)': optionalDependencies: '@types/node': 18.19.130 @@ -1323,70 +1323,70 @@ snapshots: '@open-draft/until@2.1.0': {} - '@rollup/rollup-android-arm-eabi@4.52.5': + '@rollup/rollup-android-arm-eabi@4.53.2': optional: true - '@rollup/rollup-android-arm64@4.52.5': + '@rollup/rollup-android-arm64@4.53.2': optional: true - '@rollup/rollup-darwin-arm64@4.52.5': + '@rollup/rollup-darwin-arm64@4.53.2': optional: true - '@rollup/rollup-darwin-x64@4.52.5': + '@rollup/rollup-darwin-x64@4.53.2': optional: true - '@rollup/rollup-freebsd-arm64@4.52.5': + '@rollup/rollup-freebsd-arm64@4.53.2': optional: true - '@rollup/rollup-freebsd-x64@4.52.5': + '@rollup/rollup-freebsd-x64@4.53.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.52.5': + '@rollup/rollup-linux-arm-musleabihf@4.53.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.52.5': + '@rollup/rollup-linux-arm64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.52.5': + '@rollup/rollup-linux-arm64-musl@4.53.2': optional: true - '@rollup/rollup-linux-loong64-gnu@4.52.5': + '@rollup/rollup-linux-loong64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.52.5': + '@rollup/rollup-linux-ppc64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.52.5': + '@rollup/rollup-linux-riscv64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.52.5': + '@rollup/rollup-linux-riscv64-musl@4.53.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.52.5': + '@rollup/rollup-linux-s390x-gnu@4.53.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.52.5': + '@rollup/rollup-linux-x64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-x64-musl@4.52.5': + '@rollup/rollup-linux-x64-musl@4.53.2': optional: true - '@rollup/rollup-openharmony-arm64@4.52.5': + '@rollup/rollup-openharmony-arm64@4.53.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.52.5': + '@rollup/rollup-win32-arm64-msvc@4.53.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.52.5': + '@rollup/rollup-win32-ia32-msvc@4.53.2': optional: true - '@rollup/rollup-win32-x64-gnu@4.52.5': + '@rollup/rollup-win32-x64-gnu@4.53.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.52.5': + '@rollup/rollup-win32-x64-msvc@4.53.2': optional: true '@types/chai@5.2.3': @@ -1426,14 +1426,14 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(vite@7.1.11(@types/node@18.19.130)(terser@5.44.0))': + '@vitest/mocker@3.2.4(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(vite@7.2.2(@types/node@18.19.130)(terser@5.44.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.19 + magic-string: 0.30.21 optionalDependencies: msw: 2.11.2(@types/node@18.19.130)(typescript@5.7.3) - vite: 7.1.11(@types/node@18.19.130)(terser@5.44.0) + vite: 7.2.2(@types/node@18.19.130)(terser@5.44.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -1448,7 +1448,7 @@ snapshots: '@vitest/snapshot@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 - magic-string: 0.30.19 + magic-string: 0.30.21 pathe: 2.0.3 '@vitest/spy@3.2.4': @@ -1571,25 +1571,25 @@ snapshots: assertion-error@2.0.1: {} - baseline-browser-mapping@2.8.19: {} + baseline-browser-mapping@2.8.28: {} braces@3.0.3: dependencies: fill-range: 7.1.1 - browserslist@4.27.0: + browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.8.19 - caniuse-lite: 1.0.30001751 - electron-to-chromium: 1.5.238 - node-releases: 2.0.26 - update-browserslist-db: 1.1.4(browserslist@4.27.0) + baseline-browser-mapping: 2.8.28 + caniuse-lite: 1.0.30001754 + electron-to-chromium: 1.5.250 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.28.0) buffer-from@1.1.2: {} cac@6.7.14: {} - caniuse-lite@1.0.30001751: {} + caniuse-lite@1.0.30001754: {} chai@5.3.3: dependencies: @@ -1632,7 +1632,7 @@ snapshots: deep-eql@5.0.2: {} - electron-to-chromium@1.5.238: {} + electron-to-chromium@1.5.250: {} emoji-regex@8.0.0: {} @@ -1643,34 +1643,34 @@ snapshots: es-module-lexer@1.7.0: {} - esbuild@0.25.11: + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.11 - '@esbuild/android-arm': 0.25.11 - '@esbuild/android-arm64': 0.25.11 - '@esbuild/android-x64': 0.25.11 - '@esbuild/darwin-arm64': 0.25.11 - '@esbuild/darwin-x64': 0.25.11 - '@esbuild/freebsd-arm64': 0.25.11 - '@esbuild/freebsd-x64': 0.25.11 - '@esbuild/linux-arm': 0.25.11 - '@esbuild/linux-arm64': 0.25.11 - '@esbuild/linux-ia32': 0.25.11 - '@esbuild/linux-loong64': 0.25.11 - '@esbuild/linux-mips64el': 0.25.11 - '@esbuild/linux-ppc64': 0.25.11 - '@esbuild/linux-riscv64': 0.25.11 - '@esbuild/linux-s390x': 0.25.11 - '@esbuild/linux-x64': 0.25.11 - '@esbuild/netbsd-arm64': 0.25.11 - '@esbuild/netbsd-x64': 0.25.11 - '@esbuild/openbsd-arm64': 0.25.11 - '@esbuild/openbsd-x64': 0.25.11 - '@esbuild/openharmony-arm64': 0.25.11 - '@esbuild/sunos-x64': 0.25.11 - '@esbuild/win32-arm64': 0.25.11 - '@esbuild/win32-ia32': 0.25.11 - '@esbuild/win32-x64': 0.25.11 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -1716,7 +1716,7 @@ snapshots: graceful-fs@4.2.11: {} - graphql@16.11.0: {} + graphql@16.12.0: {} has-flag@4.0.0: {} @@ -1744,7 +1744,7 @@ snapshots: loupe@3.2.1: {} - magic-string@0.30.19: + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -1767,13 +1767,13 @@ snapshots: dependencies: '@bundled-es-modules/cookie': 2.0.1 '@bundled-es-modules/statuses': 1.0.1 - '@inquirer/confirm': 5.1.19(@types/node@18.19.130) + '@inquirer/confirm': 5.1.21(@types/node@18.19.130) '@mswjs/interceptors': 0.39.8 '@open-draft/deferred-promise': 2.2.0 '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 '@types/statuses': 2.0.6 - graphql: 16.11.0 + graphql: 16.12.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 @@ -1795,7 +1795,7 @@ snapshots: neo-async@2.6.2: {} - node-releases@2.0.26: {} + node-releases@2.0.27: {} outvariant@1.4.3: {} @@ -1827,32 +1827,32 @@ snapshots: rettime@0.7.0: {} - rollup@4.52.5: + rollup@4.53.2: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.5 - '@rollup/rollup-android-arm64': 4.52.5 - '@rollup/rollup-darwin-arm64': 4.52.5 - '@rollup/rollup-darwin-x64': 4.52.5 - '@rollup/rollup-freebsd-arm64': 4.52.5 - '@rollup/rollup-freebsd-x64': 4.52.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 - '@rollup/rollup-linux-arm-musleabihf': 4.52.5 - '@rollup/rollup-linux-arm64-gnu': 4.52.5 - '@rollup/rollup-linux-arm64-musl': 4.52.5 - '@rollup/rollup-linux-loong64-gnu': 4.52.5 - '@rollup/rollup-linux-ppc64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-musl': 4.52.5 - '@rollup/rollup-linux-s390x-gnu': 4.52.5 - '@rollup/rollup-linux-x64-gnu': 4.52.5 - '@rollup/rollup-linux-x64-musl': 4.52.5 - '@rollup/rollup-openharmony-arm64': 4.52.5 - '@rollup/rollup-win32-arm64-msvc': 4.52.5 - '@rollup/rollup-win32-ia32-msvc': 4.52.5 - '@rollup/rollup-win32-x64-gnu': 4.52.5 - '@rollup/rollup-win32-x64-msvc': 4.52.5 + '@rollup/rollup-android-arm-eabi': 4.53.2 + '@rollup/rollup-android-arm64': 4.53.2 + '@rollup/rollup-darwin-arm64': 4.53.2 + '@rollup/rollup-darwin-x64': 4.53.2 + '@rollup/rollup-freebsd-arm64': 4.53.2 + '@rollup/rollup-freebsd-x64': 4.53.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.2 + '@rollup/rollup-linux-arm-musleabihf': 4.53.2 + '@rollup/rollup-linux-arm64-gnu': 4.53.2 + '@rollup/rollup-linux-arm64-musl': 4.53.2 + '@rollup/rollup-linux-loong64-gnu': 4.53.2 + '@rollup/rollup-linux-ppc64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-musl': 4.53.2 + '@rollup/rollup-linux-s390x-gnu': 4.53.2 + '@rollup/rollup-linux-x64-gnu': 4.53.2 + '@rollup/rollup-linux-x64-musl': 4.53.2 + '@rollup/rollup-openharmony-arm64': 4.53.2 + '@rollup/rollup-win32-arm64-msvc': 4.53.2 + '@rollup/rollup-win32-ia32-msvc': 4.53.2 + '@rollup/rollup-win32-x64-gnu': 4.53.2 + '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 safe-buffer@5.2.1: {} @@ -1923,10 +1923,10 @@ snapshots: jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 - terser: 5.44.0 + terser: 5.44.1 webpack: 5.102.1 - terser@5.44.0: + terser@5.44.1: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.15.0 @@ -1978,19 +1978,19 @@ snapshots: undici-types@5.26.5: {} - update-browserslist-db@1.1.4(browserslist@4.27.0): + update-browserslist-db@1.1.4(browserslist@4.28.0): dependencies: - browserslist: 4.27.0 + browserslist: 4.28.0 escalade: 3.2.0 picocolors: 1.1.1 - vite-node@3.2.4(@types/node@18.19.130)(terser@5.44.0): + vite-node@3.2.4(@types/node@18.19.130)(terser@5.44.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.11(@types/node@18.19.130)(terser@5.44.0) + vite: 7.2.2(@types/node@18.19.130)(terser@5.44.1) transitivePeerDependencies: - '@types/node' - jiti @@ -2005,24 +2005,24 @@ snapshots: - tsx - yaml - vite@7.1.11(@types/node@18.19.130)(terser@5.44.0): + vite@7.2.2(@types/node@18.19.130)(terser@5.44.1): dependencies: - esbuild: 0.25.11 + esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.5 + rollup: 4.53.2 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 18.19.130 fsevents: 2.3.3 - terser: 5.44.0 + terser: 5.44.1 - vitest@3.2.4(@types/node@18.19.130)(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(terser@5.44.0): + vitest@3.2.4(@types/node@18.19.130)(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(terser@5.44.1): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(vite@7.1.11(@types/node@18.19.130)(terser@5.44.0)) + '@vitest/mocker': 3.2.4(msw@2.11.2(@types/node@18.19.130)(typescript@5.7.3))(vite@7.2.2(@types/node@18.19.130)(terser@5.44.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -2031,7 +2031,7 @@ snapshots: chai: 5.3.3 debug: 4.4.3 expect-type: 1.2.2 - magic-string: 0.30.19 + magic-string: 0.30.21 pathe: 2.0.3 picomatch: 4.0.3 std-env: 3.10.0 @@ -2040,8 +2040,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.11(@types/node@18.19.130)(terser@5.44.0) - vite-node: 3.2.4(@types/node@18.19.130)(terser@5.44.0) + vite: 7.2.2(@types/node@18.19.130)(terser@5.44.1) + vite-node: 3.2.4(@types/node@18.19.130)(terser@5.44.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.19.130 @@ -2076,7 +2076,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.27.0 + browserslist: 4.28.0 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 diff --git a/src/BaseClient.ts b/src/BaseClient.ts index 8792c37..9b9a77d 100644 --- a/src/BaseClient.ts +++ b/src/BaseClient.ts @@ -17,6 +17,10 @@ export interface BaseClientOptions { timeoutInSeconds?: number; /** The default number of times to retry the request. Defaults to 2. */ maxRetries?: number; + /** Provide a custom fetch implementation. Useful for platforms that don't have a built-in fetch or need a custom implementation. */ + fetch?: typeof fetch; + /** Configure logging for the client. */ + logging?: core.logging.LogConfig | core.logging.Logger; } export interface BaseRequestOptions { diff --git a/src/api/resources/accounts/client/Client.ts b/src/api/resources/accounts/client/Client.ts index 5020985..03767bc 100644 --- a/src/api/resources/accounts/client/Client.ts +++ b/src/api/resources/accounts/client/Client.ts @@ -26,31 +26,26 @@ export class Accounts { /** * Retrieve all connected accounts for the project with optional filtering * - * @param {Pipedream.AccountsListRequest} request + * @param {Pipedream.ListAccountsRequest} request * @param {Accounts.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.accounts.list({ - * externalUserId: "external_user_id", - * oauthAppId: "oauth_app_id", - * after: "after", - * before: "before", - * limit: 1, - * app: "app", - * includeCredentials: true + * projectId: "project_id" * }) */ public async list( - request: Pipedream.AccountsListRequest = {}, + request: Pipedream.ListAccountsRequest, requestOptions?: Accounts.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( async ( - request: Pipedream.AccountsListRequest, + request: Pipedream.ListAccountsRequest, ): Promise> => { - const { externalUserId, oauthAppId, after, before, limit, app, includeCredentials } = request; + const { projectId, externalUserId, oauthAppId, after, before, limit, app, includeCredentials } = + request; const _queryParams: Record = {}; if (externalUserId != null) { _queryParams.external_user_id = externalUserId; @@ -94,6 +89,8 @@ export class Accounts { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -139,7 +136,7 @@ export class Accounts { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -162,8 +159,7 @@ export class Accounts { * * @example * await client.accounts.create({ - * externalUserId: "external_user_id", - * oauthAppId: "oauth_app_id", + * projectId: "project_id", * appSlug: "app_slug", * cfmapJson: "cfmap_json", * connectToken: "connect_token" @@ -180,7 +176,7 @@ export class Accounts { request: Pipedream.CreateAccountOpts, requestOptions?: Accounts.RequestOptions, ): Promise> { - const { externalUserId, oauthAppId, ..._body } = request; + const { projectId, externalUserId, oauthAppId, ..._body } = request; const _queryParams: Record = {}; if (externalUserId != null) { _queryParams.external_user_id = externalUserId; @@ -217,6 +213,8 @@ export class Accounts { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -266,31 +264,29 @@ export class Accounts { /** * Get the details for a specific connected account * - * @param {string} accountId - * @param {Pipedream.AccountsRetrieveRequest} request + * @param {Pipedream.RetrieveAccountsRequest} request * @param {Accounts.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.accounts.retrieve("account_id", { - * includeCredentials: true + * await client.accounts.retrieve({ + * projectId: "project_id", + * accountId: "account_id" * }) */ public retrieve( - accountId: string, - request: Pipedream.AccountsRetrieveRequest = {}, + request: Pipedream.RetrieveAccountsRequest, requestOptions?: Accounts.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(accountId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - accountId: string, - request: Pipedream.AccountsRetrieveRequest = {}, + request: Pipedream.RetrieveAccountsRequest, requestOptions?: Accounts.RequestOptions, ): Promise> { - const { includeCredentials } = request; + const { projectId, accountId, includeCredentials } = request; const _queryParams: Record = {}; if (includeCredentials != null) { _queryParams.include_credentials = includeCredentials.toString(); @@ -317,6 +313,8 @@ export class Accounts { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -366,22 +364,29 @@ export class Accounts { /** * Remove a connected account and its associated credentials * - * @param {string} accountId + * @param {Pipedream.DeleteAccountsRequest} request * @param {Accounts.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.accounts.delete("account_id") + * await client.accounts.delete({ + * projectId: "project_id", + * accountId: "account_id" + * }) */ - public delete(accountId: string, requestOptions?: Accounts.RequestOptions): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__delete(accountId, requestOptions)); + public delete( + request: Pipedream.DeleteAccountsRequest, + requestOptions?: Accounts.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise(this.__delete(request, requestOptions)); } private async __delete( - accountId: string, + request: Pipedream.DeleteAccountsRequest, requestOptions?: Accounts.RequestOptions, ): Promise> { + const { projectId, accountId } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -403,6 +408,8 @@ export class Accounts { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { data: undefined, rawResponse: _response.rawResponse }; @@ -443,22 +450,29 @@ export class Accounts { /** * Remove all connected accounts for a specific app * - * @param {string} appId + * @param {Pipedream.DeleteByAppAccountsRequest} request * @param {Accounts.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.accounts.deleteByApp("app_id") + * await client.accounts.deleteByApp({ + * projectId: "project_id", + * appId: "app_id" + * }) */ - public deleteByApp(appId: string, requestOptions?: Accounts.RequestOptions): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__deleteByApp(appId, requestOptions)); + public deleteByApp( + request: Pipedream.DeleteByAppAccountsRequest, + requestOptions?: Accounts.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise(this.__deleteByApp(request, requestOptions)); } private async __deleteByApp( - appId: string, + request: Pipedream.DeleteByAppAccountsRequest, requestOptions?: Accounts.RequestOptions, ): Promise> { + const { projectId, appId } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -480,6 +494,8 @@ export class Accounts { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { data: undefined, rawResponse: _response.rawResponse }; diff --git a/src/api/resources/accounts/client/requests/AccountsRetrieveRequest.ts b/src/api/resources/accounts/client/requests/AccountsRetrieveRequest.ts deleted file mode 100644 index 617ce73..0000000 --- a/src/api/resources/accounts/client/requests/AccountsRetrieveRequest.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -/** - * @example - * { - * includeCredentials: true - * } - */ -export interface AccountsRetrieveRequest { - /** Whether to retrieve the account's credentials or not */ - includeCredentials?: boolean; -} diff --git a/src/api/resources/accounts/client/requests/CreateAccountOpts.ts b/src/api/resources/accounts/client/requests/CreateAccountOpts.ts index 54cfb43..14c4b1c 100644 --- a/src/api/resources/accounts/client/requests/CreateAccountOpts.ts +++ b/src/api/resources/accounts/client/requests/CreateAccountOpts.ts @@ -3,14 +3,15 @@ /** * @example * { - * externalUserId: "external_user_id", - * oauthAppId: "oauth_app_id", + * projectId: "project_id", * appSlug: "app_slug", * cfmapJson: "cfmap_json", * connectToken: "connect_token" * } */ export interface CreateAccountOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; externalUserId?: string; /** The OAuth app ID to filter by, if applicable */ oauthAppId?: string; diff --git a/src/api/resources/accounts/client/requests/DeleteAccountsRequest.ts b/src/api/resources/accounts/client/requests/DeleteAccountsRequest.ts new file mode 100644 index 0000000..a9b30b3 --- /dev/null +++ b/src/api/resources/accounts/client/requests/DeleteAccountsRequest.ts @@ -0,0 +1,14 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * accountId: "account_id" + * } + */ +export interface DeleteAccountsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + accountId: string; +} diff --git a/src/api/resources/accounts/client/requests/DeleteByAppAccountsRequest.ts b/src/api/resources/accounts/client/requests/DeleteByAppAccountsRequest.ts new file mode 100644 index 0000000..de84352 --- /dev/null +++ b/src/api/resources/accounts/client/requests/DeleteByAppAccountsRequest.ts @@ -0,0 +1,14 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * appId: "app_id" + * } + */ +export interface DeleteByAppAccountsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + appId: string; +} diff --git a/src/api/resources/accounts/client/requests/AccountsListRequest.ts b/src/api/resources/accounts/client/requests/ListAccountsRequest.ts similarity index 69% rename from src/api/resources/accounts/client/requests/AccountsListRequest.ts rename to src/api/resources/accounts/client/requests/ListAccountsRequest.ts index 684cf8a..f23998a 100644 --- a/src/api/resources/accounts/client/requests/AccountsListRequest.ts +++ b/src/api/resources/accounts/client/requests/ListAccountsRequest.ts @@ -3,16 +3,12 @@ /** * @example * { - * externalUserId: "external_user_id", - * oauthAppId: "oauth_app_id", - * after: "after", - * before: "before", - * limit: 1, - * app: "app", - * includeCredentials: true + * projectId: "project_id" * } */ -export interface AccountsListRequest { +export interface ListAccountsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; externalUserId?: string; /** The OAuth app ID to filter by, if applicable */ oauthAppId?: string; diff --git a/src/api/resources/accounts/client/requests/RetrieveAccountsRequest.ts b/src/api/resources/accounts/client/requests/RetrieveAccountsRequest.ts new file mode 100644 index 0000000..2d532f6 --- /dev/null +++ b/src/api/resources/accounts/client/requests/RetrieveAccountsRequest.ts @@ -0,0 +1,16 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * accountId: "account_id" + * } + */ +export interface RetrieveAccountsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + accountId: string; + /** Whether to retrieve the account's credentials or not */ + includeCredentials?: boolean; +} diff --git a/src/api/resources/accounts/client/requests/index.ts b/src/api/resources/accounts/client/requests/index.ts index a4e9526..6044ae1 100644 --- a/src/api/resources/accounts/client/requests/index.ts +++ b/src/api/resources/accounts/client/requests/index.ts @@ -1,3 +1,5 @@ -export type { AccountsListRequest } from "./AccountsListRequest.js"; -export type { AccountsRetrieveRequest } from "./AccountsRetrieveRequest.js"; export type { CreateAccountOpts } from "./CreateAccountOpts.js"; +export type { DeleteAccountsRequest } from "./DeleteAccountsRequest.js"; +export type { DeleteByAppAccountsRequest } from "./DeleteByAppAccountsRequest.js"; +export type { ListAccountsRequest } from "./ListAccountsRequest.js"; +export type { RetrieveAccountsRequest } from "./RetrieveAccountsRequest.js"; diff --git a/src/api/resources/actions/client/Client.ts b/src/api/resources/actions/client/Client.ts index 7eda762..f3eeab2 100644 --- a/src/api/resources/actions/client/Client.ts +++ b/src/api/resources/actions/client/Client.ts @@ -26,29 +26,25 @@ export class Actions { /** * Retrieve available actions with optional search and app filtering * - * @param {Pipedream.ActionsListRequest} request + * @param {Pipedream.ListActionsRequest} request * @param {Actions.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.actions.list({ - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app" + * projectId: "project_id" * }) */ public async list( - request: Pipedream.ActionsListRequest = {}, + request: Pipedream.ListActionsRequest, requestOptions?: Actions.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( async ( - request: Pipedream.ActionsListRequest, + request: Pipedream.ListActionsRequest, ): Promise> => { - const { after, before, limit, q, app } = request; + const { projectId, after, before, limit, q, app } = request; const _queryParams: Record = {}; if (after != null) { _queryParams.after = after; @@ -86,6 +82,8 @@ export class Actions { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -131,7 +129,7 @@ export class Actions { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -147,31 +145,30 @@ export class Actions { /** * Get detailed configuration for a specific action by its key * - * @param {string} componentId - The key that uniquely identifies the component (e.g., 'slack-send-message') - * @param {Pipedream.ActionsRetrieveRequest} request + * @param {Pipedream.RetrieveActionsRequest} request * @param {Actions.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.actions.retrieve("component_id", { + * await client.actions.retrieve({ + * projectId: "project_id", + * componentId: "component_id", * version: "1.2.3" * }) */ public retrieve( - componentId: string, - request: Pipedream.ActionsRetrieveRequest = {}, + request: Pipedream.RetrieveActionsRequest, requestOptions?: Actions.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(componentId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - componentId: string, - request: Pipedream.ActionsRetrieveRequest = {}, + request: Pipedream.RetrieveActionsRequest, requestOptions?: Actions.RequestOptions, ): Promise> { - const { version } = request; + const { projectId, componentId, version } = request; const _queryParams: Record = {}; if (version != null) { _queryParams.version = version; @@ -198,6 +195,8 @@ export class Actions { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -247,29 +246,33 @@ export class Actions { /** * Retrieve remote options for a given prop for a action * - * @param {Pipedream.ConfigurePropOpts} request + * @param {Pipedream.ConfigurePropActionsRequest} request * @param {Actions.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.actions.configureProp({ - * id: "id", - * externalUserId: "external_user_id", - * propName: "prop_name" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } * }) */ public configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropActionsRequest, requestOptions?: Actions.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__configureProp(request, requestOptions)); } private async __configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropActionsRequest, requestOptions?: Actions.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -290,13 +293,15 @@ export class Actions { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ConfigurePropOpts.jsonOrThrow(request, { + body: serializers.ConfigurePropOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -346,28 +351,32 @@ export class Actions { /** * Reload the prop definition based on the currently configured props * - * @param {Pipedream.ReloadPropsOpts} request + * @param {Pipedream.ReloadPropsActionsRequest} request * @param {Actions.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.actions.reloadProps({ - * id: "id", - * externalUserId: "external_user_id" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } * }) */ public reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsActionsRequest, requestOptions?: Actions.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__reloadProps(request, requestOptions)); } private async __reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsActionsRequest, requestOptions?: Actions.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -388,13 +397,15 @@ export class Actions { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ReloadPropsOpts.jsonOrThrow(request, { + body: serializers.ReloadPropsOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -451,6 +462,7 @@ export class Actions { * * @example * await client.actions.run({ + * projectId: "project_id", * id: "id", * externalUserId: "external_user_id" * }) @@ -466,6 +478,7 @@ export class Actions { request: Pipedream.RunActionOpts, requestOptions?: Actions.RequestOptions, ): Promise> { + const { projectId, ..._body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -486,13 +499,15 @@ export class Actions { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.RunActionOpts.jsonOrThrow(request, { + body: serializers.RunActionOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/actions/client/requests/ActionsRetrieveRequest.ts b/src/api/resources/actions/client/requests/ActionsRetrieveRequest.ts deleted file mode 100644 index 092050d..0000000 --- a/src/api/resources/actions/client/requests/ActionsRetrieveRequest.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -/** - * @example - * { - * version: "1.2.3" - * } - */ -export interface ActionsRetrieveRequest { - /** Optional semantic version of the component to retrieve (for example '1.0.0') */ - version?: string; -} diff --git a/src/api/resources/actions/client/requests/ConfigurePropActionsRequest.ts b/src/api/resources/actions/client/requests/ConfigurePropActionsRequest.ts new file mode 100644 index 0000000..0b0f315 --- /dev/null +++ b/src/api/resources/actions/client/requests/ConfigurePropActionsRequest.ts @@ -0,0 +1,20 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } + * } + */ +export interface ConfigurePropActionsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ConfigurePropOpts; +} diff --git a/src/api/resources/actions/client/requests/ActionsListRequest.ts b/src/api/resources/actions/client/requests/ListActionsRequest.ts similarity index 74% rename from src/api/resources/actions/client/requests/ActionsListRequest.ts rename to src/api/resources/actions/client/requests/ListActionsRequest.ts index 5b9b728..ba20ea5 100644 --- a/src/api/resources/actions/client/requests/ActionsListRequest.ts +++ b/src/api/resources/actions/client/requests/ListActionsRequest.ts @@ -3,14 +3,12 @@ /** * @example * { - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app" + * projectId: "project_id" * } */ -export interface ActionsListRequest { +export interface ListActionsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The cursor to start from for pagination */ after?: string; /** The cursor to end before for pagination */ diff --git a/src/api/resources/actions/client/requests/ReloadPropsActionsRequest.ts b/src/api/resources/actions/client/requests/ReloadPropsActionsRequest.ts new file mode 100644 index 0000000..7e9cac9 --- /dev/null +++ b/src/api/resources/actions/client/requests/ReloadPropsActionsRequest.ts @@ -0,0 +1,19 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } + * } + */ +export interface ReloadPropsActionsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ReloadPropsOpts; +} diff --git a/src/api/resources/actions/client/requests/RetrieveActionsRequest.ts b/src/api/resources/actions/client/requests/RetrieveActionsRequest.ts new file mode 100644 index 0000000..e5679e8 --- /dev/null +++ b/src/api/resources/actions/client/requests/RetrieveActionsRequest.ts @@ -0,0 +1,18 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * componentId: "component_id", + * version: "1.2.3" + * } + */ +export interface RetrieveActionsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** The key that uniquely identifies the component (e.g., 'slack-send-message') */ + componentId: string; + /** Optional semantic version of the component to retrieve (for example '1.0.0') */ + version?: string; +} diff --git a/src/api/resources/actions/client/requests/RunActionOpts.ts b/src/api/resources/actions/client/requests/RunActionOpts.ts index e72bd7b..42e7dc0 100644 --- a/src/api/resources/actions/client/requests/RunActionOpts.ts +++ b/src/api/resources/actions/client/requests/RunActionOpts.ts @@ -5,19 +5,22 @@ import type * as Pipedream from "../../../../index.js"; /** * @example * { + * projectId: "project_id", * id: "id", * externalUserId: "external_user_id" * } */ export interface RunActionOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The action component ID */ id: string; /** Optional action component version (in SemVer format, for example '1.0.0'), defaults to latest */ - version?: string; + version?: string | null; /** The external user ID */ externalUserId: string; configuredProps?: Pipedream.ConfiguredProps; /** The ID for dynamic props */ dynamicPropsId?: string; - stashId?: Pipedream.RunActionOptsStashId; + stashId?: Pipedream.RunActionOptsStashId | null; } diff --git a/src/api/resources/actions/client/requests/index.ts b/src/api/resources/actions/client/requests/index.ts index 89e2dfe..878588c 100644 --- a/src/api/resources/actions/client/requests/index.ts +++ b/src/api/resources/actions/client/requests/index.ts @@ -1,3 +1,5 @@ -export type { ActionsListRequest } from "./ActionsListRequest.js"; -export type { ActionsRetrieveRequest } from "./ActionsRetrieveRequest.js"; +export type { ConfigurePropActionsRequest } from "./ConfigurePropActionsRequest.js"; +export type { ListActionsRequest } from "./ListActionsRequest.js"; +export type { ReloadPropsActionsRequest } from "./ReloadPropsActionsRequest.js"; +export type { RetrieveActionsRequest } from "./RetrieveActionsRequest.js"; export type { RunActionOpts } from "./RunActionOpts.js"; diff --git a/src/api/resources/appCategories/client/Client.ts b/src/api/resources/appCategories/client/Client.ts index c7db14c..7e7d7c0 100644 --- a/src/api/resources/appCategories/client/Client.ts +++ b/src/api/resources/appCategories/client/Client.ts @@ -61,6 +61,8 @@ export class AppCategories { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -103,23 +105,26 @@ export class AppCategories { /** * Get details of a specific app category by its ID * - * @param {string} id - The ID of the app category to retrieve + * @param {Pipedream.RetrieveAppCategoriesRequest} request * @param {AppCategories.RequestOptions} requestOptions - Request-specific configuration. * * @example - * await client.appCategories.retrieve("id") + * await client.appCategories.retrieve({ + * id: "id" + * }) */ public retrieve( - id: string, + request: Pipedream.RetrieveAppCategoriesRequest, requestOptions?: AppCategories.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(id, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - id: string, + request: Pipedream.RetrieveAppCategoriesRequest, requestOptions?: AppCategories.RequestOptions, ): Promise> { + const { id } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -141,6 +146,8 @@ export class AppCategories { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/appCategories/client/index.ts b/src/api/resources/appCategories/client/index.ts index cb0ff5c..195f9aa 100644 --- a/src/api/resources/appCategories/client/index.ts +++ b/src/api/resources/appCategories/client/index.ts @@ -1 +1 @@ -export {}; +export * from "./requests/index.js"; diff --git a/src/api/resources/appCategories/client/requests/RetrieveAppCategoriesRequest.ts b/src/api/resources/appCategories/client/requests/RetrieveAppCategoriesRequest.ts new file mode 100644 index 0000000..5be39b8 --- /dev/null +++ b/src/api/resources/appCategories/client/requests/RetrieveAppCategoriesRequest.ts @@ -0,0 +1,12 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * id: "id" + * } + */ +export interface RetrieveAppCategoriesRequest { + /** The ID of the app category to retrieve */ + id: string; +} diff --git a/src/api/resources/appCategories/client/requests/index.ts b/src/api/resources/appCategories/client/requests/index.ts new file mode 100644 index 0000000..29046cf --- /dev/null +++ b/src/api/resources/appCategories/client/requests/index.ts @@ -0,0 +1 @@ +export type { RetrieveAppCategoriesRequest } from "./RetrieveAppCategoriesRequest.js"; diff --git a/src/api/resources/apps/client/Client.ts b/src/api/resources/apps/client/Client.ts index 2598a5f..4439110 100644 --- a/src/api/resources/apps/client/Client.ts +++ b/src/api/resources/apps/client/Client.ts @@ -26,25 +26,18 @@ export class Apps { /** * Retrieve all available apps with optional filtering and sorting * - * @param {Pipedream.AppsListRequest} request + * @param {Pipedream.ListAppsRequest} request * @param {Apps.RequestOptions} requestOptions - Request-specific configuration. * * @example - * await client.apps.list({ - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * sortKey: "name", - * sortDirection: "asc" - * }) + * await client.apps.list() */ public async list( - request: Pipedream.AppsListRequest = {}, + request: Pipedream.ListAppsRequest = {}, requestOptions?: Apps.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( - async (request: Pipedream.AppsListRequest): Promise> => { + async (request: Pipedream.ListAppsRequest): Promise> => { const { after, before, limit, q, sortKey, sortDirection, categoryIds } = request; const _queryParams: Record = {}; if (after != null) { @@ -60,13 +53,13 @@ export class Apps { _queryParams.q = q; } if (sortKey != null) { - _queryParams.sort_key = serializers.AppsListRequestSortKey.jsonOrThrow(sortKey, { + _queryParams.sort_key = serializers.ListAppsRequestSortKey.jsonOrThrow(sortKey, { unrecognizedObjectKeys: "strip", omitUndefined: true, }); } if (sortDirection != null) { - _queryParams.sort_direction = serializers.AppsListRequestSortDirection.jsonOrThrow(sortDirection, { + _queryParams.sort_direction = serializers.ListAppsRequestSortDirection.jsonOrThrow(sortDirection, { unrecognizedObjectKeys: "strip", omitUndefined: true, }); @@ -99,6 +92,8 @@ export class Apps { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -137,7 +132,7 @@ export class Apps { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -153,23 +148,26 @@ export class Apps { /** * Get detailed information about a specific app by ID or name slug * - * @param {string} appId - The name slug or ID of the app (e.g., 'slack', 'github') + * @param {Pipedream.RetrieveAppsRequest} request * @param {Apps.RequestOptions} requestOptions - Request-specific configuration. * * @example - * await client.apps.retrieve("app_id") + * await client.apps.retrieve({ + * appId: "app_id" + * }) */ public retrieve( - appId: string, + request: Pipedream.RetrieveAppsRequest, requestOptions?: Apps.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(appId, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - appId: string, + request: Pipedream.RetrieveAppsRequest, requestOptions?: Apps.RequestOptions, ): Promise> { + const { appId } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -191,6 +189,8 @@ export class Apps { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/apps/client/requests/AppsListRequest.ts b/src/api/resources/apps/client/requests/ListAppsRequest.ts similarity index 64% rename from src/api/resources/apps/client/requests/AppsListRequest.ts rename to src/api/resources/apps/client/requests/ListAppsRequest.ts index 1d04fbf..fcf1ea0 100644 --- a/src/api/resources/apps/client/requests/AppsListRequest.ts +++ b/src/api/resources/apps/client/requests/ListAppsRequest.ts @@ -4,16 +4,9 @@ import type * as Pipedream from "../../../../index.js"; /** * @example - * { - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * sortKey: "name", - * sortDirection: "asc" - * } + * {} */ -export interface AppsListRequest { +export interface ListAppsRequest { /** The cursor to start from for pagination */ after?: string; /** The cursor to end before for pagination */ @@ -23,9 +16,9 @@ export interface AppsListRequest { /** A search query to filter the apps */ q?: string; /** The key to sort the apps by */ - sortKey?: Pipedream.AppsListRequestSortKey; + sortKey?: Pipedream.ListAppsRequestSortKey; /** The direction to sort the apps */ - sortDirection?: Pipedream.AppsListRequestSortDirection; + sortDirection?: Pipedream.ListAppsRequestSortDirection; /** Only return apps in these categories */ categoryIds?: string | string[]; } diff --git a/src/api/resources/apps/client/requests/RetrieveAppsRequest.ts b/src/api/resources/apps/client/requests/RetrieveAppsRequest.ts new file mode 100644 index 0000000..982d532 --- /dev/null +++ b/src/api/resources/apps/client/requests/RetrieveAppsRequest.ts @@ -0,0 +1,12 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * appId: "app_id" + * } + */ +export interface RetrieveAppsRequest { + /** The name slug or ID of the app (e.g., 'slack', 'github') */ + appId: string; +} diff --git a/src/api/resources/apps/client/requests/index.ts b/src/api/resources/apps/client/requests/index.ts index b2fa3e0..843c832 100644 --- a/src/api/resources/apps/client/requests/index.ts +++ b/src/api/resources/apps/client/requests/index.ts @@ -1 +1,2 @@ -export type { AppsListRequest } from "./AppsListRequest.js"; +export type { ListAppsRequest } from "./ListAppsRequest.js"; +export type { RetrieveAppsRequest } from "./RetrieveAppsRequest.js"; diff --git a/src/api/resources/apps/types/AppsListRequestSortDirection.ts b/src/api/resources/apps/types/AppsListRequestSortDirection.ts deleted file mode 100644 index c2d7417..0000000 --- a/src/api/resources/apps/types/AppsListRequestSortDirection.ts +++ /dev/null @@ -1,8 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -export const AppsListRequestSortDirection = { - Asc: "asc", - Desc: "desc", -} as const; -export type AppsListRequestSortDirection = - (typeof AppsListRequestSortDirection)[keyof typeof AppsListRequestSortDirection]; diff --git a/src/api/resources/apps/types/ListAppsRequestSortDirection.ts b/src/api/resources/apps/types/ListAppsRequestSortDirection.ts new file mode 100644 index 0000000..4988664 --- /dev/null +++ b/src/api/resources/apps/types/ListAppsRequestSortDirection.ts @@ -0,0 +1,8 @@ +// This file was auto-generated by Fern from our API Definition. + +export const ListAppsRequestSortDirection = { + Asc: "asc", + Desc: "desc", +} as const; +export type ListAppsRequestSortDirection = + (typeof ListAppsRequestSortDirection)[keyof typeof ListAppsRequestSortDirection]; diff --git a/src/api/resources/apps/types/AppsListRequestSortKey.ts b/src/api/resources/apps/types/ListAppsRequestSortKey.ts similarity index 52% rename from src/api/resources/apps/types/AppsListRequestSortKey.ts rename to src/api/resources/apps/types/ListAppsRequestSortKey.ts index 36842c8..283dd58 100644 --- a/src/api/resources/apps/types/AppsListRequestSortKey.ts +++ b/src/api/resources/apps/types/ListAppsRequestSortKey.ts @@ -1,8 +1,8 @@ // This file was auto-generated by Fern from our API Definition. -export const AppsListRequestSortKey = { +export const ListAppsRequestSortKey = { Name: "name", NameSlug: "name_slug", FeaturedWeight: "featured_weight", } as const; -export type AppsListRequestSortKey = (typeof AppsListRequestSortKey)[keyof typeof AppsListRequestSortKey]; +export type ListAppsRequestSortKey = (typeof ListAppsRequestSortKey)[keyof typeof ListAppsRequestSortKey]; diff --git a/src/api/resources/apps/types/index.ts b/src/api/resources/apps/types/index.ts index 19ea38a..2982c6d 100644 --- a/src/api/resources/apps/types/index.ts +++ b/src/api/resources/apps/types/index.ts @@ -1,2 +1,2 @@ -export * from "./AppsListRequestSortDirection.js"; -export * from "./AppsListRequestSortKey.js"; +export * from "./ListAppsRequestSortDirection.js"; +export * from "./ListAppsRequestSortKey.js"; diff --git a/src/api/resources/components/client/Client.ts b/src/api/resources/components/client/Client.ts index baf723e..748d89b 100644 --- a/src/api/resources/components/client/Client.ts +++ b/src/api/resources/components/client/Client.ts @@ -26,30 +26,25 @@ export class Components { /** * Retrieve available components with optional search and app filtering * - * @param {Pipedream.ComponentsListRequest} request + * @param {Pipedream.ListComponentsRequest} request * @param {Components.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.components.list({ - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app", - * componentType: "trigger" + * projectId: "project_id" * }) */ public async list( - request: Pipedream.ComponentsListRequest = {}, + request: Pipedream.ListComponentsRequest, requestOptions?: Components.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( async ( - request: Pipedream.ComponentsListRequest, + request: Pipedream.ListComponentsRequest, ): Promise> => { - const { after, before, limit, q, app, componentType } = request; + const { projectId, after, before, limit, q, app, componentType } = request; const _queryParams: Record = {}; if (after != null) { _queryParams.after = after; @@ -93,6 +88,8 @@ export class Components { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -138,7 +135,7 @@ export class Components { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -154,31 +151,30 @@ export class Components { /** * Get detailed configuration for a specific component by its key * - * @param {string} componentId - The key that uniquely identifies the component (e.g., 'slack-send-message') - * @param {Pipedream.ComponentsRetrieveRequest} request + * @param {Pipedream.RetrieveComponentsRequest} request * @param {Components.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.components.retrieve("component_id", { + * await client.components.retrieve({ + * projectId: "project_id", + * componentId: "component_id", * version: "1.2.3" * }) */ public retrieve( - componentId: string, - request: Pipedream.ComponentsRetrieveRequest = {}, + request: Pipedream.RetrieveComponentsRequest, requestOptions?: Components.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(componentId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - componentId: string, - request: Pipedream.ComponentsRetrieveRequest = {}, + request: Pipedream.RetrieveComponentsRequest, requestOptions?: Components.RequestOptions, ): Promise> { - const { version } = request; + const { projectId, componentId, version } = request; const _queryParams: Record = {}; if (version != null) { _queryParams.version = version; @@ -205,6 +201,8 @@ export class Components { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -254,29 +252,33 @@ export class Components { /** * Retrieve remote options for a given prop for a component * - * @param {Pipedream.ConfigurePropOpts} request + * @param {Pipedream.ConfigurePropComponentsRequest} request * @param {Components.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.components.configureProp({ - * id: "id", - * externalUserId: "external_user_id", - * propName: "prop_name" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } * }) */ public configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropComponentsRequest, requestOptions?: Components.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__configureProp(request, requestOptions)); } private async __configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropComponentsRequest, requestOptions?: Components.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -297,13 +299,15 @@ export class Components { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ConfigurePropOpts.jsonOrThrow(request, { + body: serializers.ConfigurePropOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -353,28 +357,32 @@ export class Components { /** * Reload the prop definition based on the currently configured props * - * @param {Pipedream.ReloadPropsOpts} request + * @param {Pipedream.ReloadPropsComponentsRequest} request * @param {Components.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.components.reloadProps({ - * id: "id", - * externalUserId: "external_user_id" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } * }) */ public reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsComponentsRequest, requestOptions?: Components.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__reloadProps(request, requestOptions)); } private async __reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsComponentsRequest, requestOptions?: Components.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -395,13 +403,15 @@ export class Components { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ReloadPropsOpts.jsonOrThrow(request, { + body: serializers.ReloadPropsOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/components/client/requests/ComponentsRetrieveRequest.ts b/src/api/resources/components/client/requests/ComponentsRetrieveRequest.ts deleted file mode 100644 index 8fdd3d7..0000000 --- a/src/api/resources/components/client/requests/ComponentsRetrieveRequest.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -/** - * @example - * { - * version: "1.2.3" - * } - */ -export interface ComponentsRetrieveRequest { - /** Optional semantic version of the component to retrieve (for example '1.0.0') */ - version?: string; -} diff --git a/src/api/resources/components/client/requests/ConfigurePropComponentsRequest.ts b/src/api/resources/components/client/requests/ConfigurePropComponentsRequest.ts new file mode 100644 index 0000000..0ddce83 --- /dev/null +++ b/src/api/resources/components/client/requests/ConfigurePropComponentsRequest.ts @@ -0,0 +1,20 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } + * } + */ +export interface ConfigurePropComponentsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ConfigurePropOpts; +} diff --git a/src/api/resources/components/client/requests/ComponentsListRequest.ts b/src/api/resources/components/client/requests/ListComponentsRequest.ts similarity index 76% rename from src/api/resources/components/client/requests/ComponentsListRequest.ts rename to src/api/resources/components/client/requests/ListComponentsRequest.ts index 4da288e..f7148d2 100644 --- a/src/api/resources/components/client/requests/ComponentsListRequest.ts +++ b/src/api/resources/components/client/requests/ListComponentsRequest.ts @@ -5,15 +5,12 @@ import type * as Pipedream from "../../../../index.js"; /** * @example * { - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app", - * componentType: "trigger" + * projectId: "project_id" * } */ -export interface ComponentsListRequest { +export interface ListComponentsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The cursor to start from for pagination */ after?: string; /** The cursor to end before for pagination */ diff --git a/src/api/resources/components/client/requests/ReloadPropsComponentsRequest.ts b/src/api/resources/components/client/requests/ReloadPropsComponentsRequest.ts new file mode 100644 index 0000000..3fbed64 --- /dev/null +++ b/src/api/resources/components/client/requests/ReloadPropsComponentsRequest.ts @@ -0,0 +1,19 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } + * } + */ +export interface ReloadPropsComponentsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ReloadPropsOpts; +} diff --git a/src/api/resources/components/client/requests/RetrieveComponentsRequest.ts b/src/api/resources/components/client/requests/RetrieveComponentsRequest.ts new file mode 100644 index 0000000..00c5a31 --- /dev/null +++ b/src/api/resources/components/client/requests/RetrieveComponentsRequest.ts @@ -0,0 +1,18 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * componentId: "component_id", + * version: "1.2.3" + * } + */ +export interface RetrieveComponentsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** The key that uniquely identifies the component (e.g., 'slack-send-message') */ + componentId: string; + /** Optional semantic version of the component to retrieve (for example '1.0.0') */ + version?: string; +} diff --git a/src/api/resources/components/client/requests/index.ts b/src/api/resources/components/client/requests/index.ts index ce00c15..b0055e0 100644 --- a/src/api/resources/components/client/requests/index.ts +++ b/src/api/resources/components/client/requests/index.ts @@ -1,2 +1,4 @@ -export type { ComponentsListRequest } from "./ComponentsListRequest.js"; -export type { ComponentsRetrieveRequest } from "./ComponentsRetrieveRequest.js"; +export type { ConfigurePropComponentsRequest } from "./ConfigurePropComponentsRequest.js"; +export type { ListComponentsRequest } from "./ListComponentsRequest.js"; +export type { ReloadPropsComponentsRequest } from "./ReloadPropsComponentsRequest.js"; +export type { RetrieveComponentsRequest } from "./RetrieveComponentsRequest.js"; diff --git a/src/api/resources/deployedTriggers/client/Client.ts b/src/api/resources/deployedTriggers/client/Client.ts index dd2e0be..91d736c 100644 --- a/src/api/resources/deployedTriggers/client/Client.ts +++ b/src/api/resources/deployedTriggers/client/Client.ts @@ -26,29 +26,26 @@ export class DeployedTriggers { /** * Retrieve all deployed triggers for a specific external user * - * @param {Pipedream.DeployedTriggersListRequest} request + * @param {Pipedream.ListDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.deployedTriggers.list({ - * after: "after", - * before: "before", - * limit: 1, - * externalUserId: "external_user_id", - * emitterType: "email" + * projectId: "project_id", + * externalUserId: "external_user_id" * }) */ public async list( - request: Pipedream.DeployedTriggersListRequest, + request: Pipedream.ListDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( async ( - request: Pipedream.DeployedTriggersListRequest, + request: Pipedream.ListDeployedTriggersRequest, ): Promise> => { - const { after, before, limit, externalUserId, emitterType } = request; + const { projectId, after, before, limit, externalUserId, emitterType } = request; const _queryParams: Record = {}; if (after != null) { _queryParams.after = after; @@ -87,6 +84,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -132,7 +131,7 @@ export class DeployedTriggers { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -148,31 +147,30 @@ export class DeployedTriggers { /** * Get details of a specific deployed trigger by its ID * - * @param {string} triggerId - * @param {Pipedream.DeployedTriggersRetrieveRequest} request + * @param {Pipedream.RetrieveDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.retrieve("trigger_id", { + * await client.deployedTriggers.retrieve({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * }) */ public retrieve( - triggerId: string, - request: Pipedream.DeployedTriggersRetrieveRequest, + request: Pipedream.RetrieveDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - triggerId: string, - request: Pipedream.DeployedTriggersRetrieveRequest, + request: Pipedream.RetrieveDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId } = request; + const { projectId, triggerId, externalUserId } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -196,6 +194,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -245,31 +245,30 @@ export class DeployedTriggers { /** * Modify the configuration of a deployed trigger, including active status * - * @param {string} triggerId * @param {Pipedream.UpdateTriggerOpts} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.update("trigger_id", { + * await client.deployedTriggers.update({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * }) */ public update( - triggerId: string, request: Pipedream.UpdateTriggerOpts, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__update(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__update(request, requestOptions)); } private async __update( - triggerId: string, request: Pipedream.UpdateTriggerOpts, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId, ..._body } = request; + const { projectId, triggerId, externalUserId, ..._body } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -299,6 +298,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -348,32 +349,30 @@ export class DeployedTriggers { /** * Remove a deployed trigger and stop receiving events * - * @param {string} triggerId - * @param {Pipedream.DeployedTriggersDeleteRequest} request + * @param {Pipedream.DeleteDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.delete("trigger_id", { - * externalUserId: "external_user_id", - * ignoreHookErrors: true + * await client.deployedTriggers.delete({ + * projectId: "project_id", + * triggerId: "trigger_id", + * externalUserId: "external_user_id" * }) */ public delete( - triggerId: string, - request: Pipedream.DeployedTriggersDeleteRequest, + request: Pipedream.DeleteDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__delete(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__delete(request, requestOptions)); } private async __delete( - triggerId: string, - request: Pipedream.DeployedTriggersDeleteRequest, + request: Pipedream.DeleteDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId, ignoreHookErrors } = request; + const { projectId, triggerId, externalUserId, ignoreHookErrors } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; if (ignoreHookErrors != null) { @@ -401,6 +400,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { data: undefined, rawResponse: _response.rawResponse }; @@ -441,32 +442,30 @@ export class DeployedTriggers { /** * Retrieve recent events emitted by a deployed trigger * - * @param {string} triggerId - * @param {Pipedream.DeployedTriggersListEventsRequest} request + * @param {Pipedream.ListEventsDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.listEvents("trigger_id", { - * externalUserId: "external_user_id", - * n: 1 + * await client.deployedTriggers.listEvents({ + * projectId: "project_id", + * triggerId: "trigger_id", + * externalUserId: "external_user_id" * }) */ public listEvents( - triggerId: string, - request: Pipedream.DeployedTriggersListEventsRequest, + request: Pipedream.ListEventsDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__listEvents(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__listEvents(request, requestOptions)); } private async __listEvents( - triggerId: string, - request: Pipedream.DeployedTriggersListEventsRequest, + request: Pipedream.ListEventsDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId, n } = request; + const { projectId, triggerId, externalUserId, n } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; if (n != null) { @@ -494,6 +493,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -543,31 +544,30 @@ export class DeployedTriggers { /** * Get workflows connected to receive events from this trigger * - * @param {string} triggerId - * @param {Pipedream.DeployedTriggersListWorkflowsRequest} request + * @param {Pipedream.ListWorkflowsDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.listWorkflows("trigger_id", { + * await client.deployedTriggers.listWorkflows({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * }) */ public listWorkflows( - triggerId: string, - request: Pipedream.DeployedTriggersListWorkflowsRequest, + request: Pipedream.ListWorkflowsDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__listWorkflows(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__listWorkflows(request, requestOptions)); } private async __listWorkflows( - triggerId: string, - request: Pipedream.DeployedTriggersListWorkflowsRequest, + request: Pipedream.ListWorkflowsDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId } = request; + const { projectId, triggerId, externalUserId } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -591,6 +591,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -640,32 +642,31 @@ export class DeployedTriggers { /** * Connect or disconnect workflows to receive trigger events * - * @param {string} triggerId * @param {Pipedream.UpdateTriggerWorkflowsOpts} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.updateWorkflows("trigger_id", { + * await client.deployedTriggers.updateWorkflows({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id", * workflowIds: ["workflow_ids"] * }) */ public updateWorkflows( - triggerId: string, request: Pipedream.UpdateTriggerWorkflowsOpts, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__updateWorkflows(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__updateWorkflows(request, requestOptions)); } private async __updateWorkflows( - triggerId: string, request: Pipedream.UpdateTriggerWorkflowsOpts, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId, ..._body } = request; + const { projectId, triggerId, externalUserId, ..._body } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -695,6 +696,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -744,31 +747,30 @@ export class DeployedTriggers { /** * Get webhook URLs configured to receive trigger events * - * @param {string} triggerId - * @param {Pipedream.DeployedTriggersListWebhooksRequest} request + * @param {Pipedream.ListWebhooksDeployedTriggersRequest} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.listWebhooks("trigger_id", { + * await client.deployedTriggers.listWebhooks({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * }) */ public listWebhooks( - triggerId: string, - request: Pipedream.DeployedTriggersListWebhooksRequest, + request: Pipedream.ListWebhooksDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__listWebhooks(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__listWebhooks(request, requestOptions)); } private async __listWebhooks( - triggerId: string, - request: Pipedream.DeployedTriggersListWebhooksRequest, + request: Pipedream.ListWebhooksDeployedTriggersRequest, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId } = request; + const { projectId, triggerId, externalUserId } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -792,6 +794,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -841,32 +845,31 @@ export class DeployedTriggers { /** * Configure webhook URLs to receive trigger events * - * @param {string} triggerId * @param {Pipedream.UpdateTriggerWebhooksOpts} request * @param {DeployedTriggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.deployedTriggers.updateWebhooks("trigger_id", { + * await client.deployedTriggers.updateWebhooks({ + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id", * webhookUrls: ["webhook_urls"] * }) */ public updateWebhooks( - triggerId: string, request: Pipedream.UpdateTriggerWebhooksOpts, requestOptions?: DeployedTriggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__updateWebhooks(triggerId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__updateWebhooks(request, requestOptions)); } private async __updateWebhooks( - triggerId: string, request: Pipedream.UpdateTriggerWebhooksOpts, requestOptions?: DeployedTriggers.RequestOptions, ): Promise> { - const { externalUserId, ..._body } = request; + const { projectId, triggerId, externalUserId, ..._body } = request; const _queryParams: Record = {}; _queryParams.external_user_id = externalUserId; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -896,6 +899,8 @@ export class DeployedTriggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersDeleteRequest.ts b/src/api/resources/deployedTriggers/client/requests/DeleteDeployedTriggersRequest.ts similarity index 51% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersDeleteRequest.ts rename to src/api/resources/deployedTriggers/client/requests/DeleteDeployedTriggersRequest.ts index 8642d00..d41e2e4 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersDeleteRequest.ts +++ b/src/api/resources/deployedTriggers/client/requests/DeleteDeployedTriggersRequest.ts @@ -3,11 +3,15 @@ /** * @example * { - * externalUserId: "external_user_id", - * ignoreHookErrors: true + * projectId: "project_id", + * triggerId: "trigger_id", + * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersDeleteRequest { +export interface DeleteDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** The external user ID who owns the trigger */ externalUserId: string; /** Whether to ignore errors during deactivation hook */ diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListRequest.ts b/src/api/resources/deployedTriggers/client/requests/ListDeployedTriggersRequest.ts similarity index 74% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersListRequest.ts rename to src/api/resources/deployedTriggers/client/requests/ListDeployedTriggersRequest.ts index bb190f8..31670bd 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListRequest.ts +++ b/src/api/resources/deployedTriggers/client/requests/ListDeployedTriggersRequest.ts @@ -5,14 +5,13 @@ import type * as Pipedream from "../../../../index.js"; /** * @example * { - * after: "after", - * before: "before", - * limit: 1, - * externalUserId: "external_user_id", - * emitterType: "email" + * projectId: "project_id", + * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersListRequest { +export interface ListDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The cursor to start from for pagination */ after?: string; /** The cursor to end before for pagination */ diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListEventsRequest.ts b/src/api/resources/deployedTriggers/client/requests/ListEventsDeployedTriggersRequest.ts similarity index 51% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersListEventsRequest.ts rename to src/api/resources/deployedTriggers/client/requests/ListEventsDeployedTriggersRequest.ts index 0491619..147ab25 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListEventsRequest.ts +++ b/src/api/resources/deployedTriggers/client/requests/ListEventsDeployedTriggersRequest.ts @@ -3,11 +3,15 @@ /** * @example * { - * externalUserId: "external_user_id", - * n: 1 + * projectId: "project_id", + * triggerId: "trigger_id", + * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersListEventsRequest { +export interface ListEventsDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** Your end user ID, for whom you deployed the trigger */ externalUserId: string; /** The number of events to retrieve (defaults to 20 if not provided) */ diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWorkflowsRequest.ts b/src/api/resources/deployedTriggers/client/requests/ListWebhooksDeployedTriggersRequest.ts similarity index 50% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWorkflowsRequest.ts rename to src/api/resources/deployedTriggers/client/requests/ListWebhooksDeployedTriggersRequest.ts index 19d61aa..efdc1b3 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWorkflowsRequest.ts +++ b/src/api/resources/deployedTriggers/client/requests/ListWebhooksDeployedTriggersRequest.ts @@ -3,10 +3,15 @@ /** * @example * { + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersListWorkflowsRequest { +export interface ListWebhooksDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** The external user ID who owns the trigger */ externalUserId: string; } diff --git a/src/api/resources/deployedTriggers/client/requests/ListWorkflowsDeployedTriggersRequest.ts b/src/api/resources/deployedTriggers/client/requests/ListWorkflowsDeployedTriggersRequest.ts new file mode 100644 index 0000000..0b1db45 --- /dev/null +++ b/src/api/resources/deployedTriggers/client/requests/ListWorkflowsDeployedTriggersRequest.ts @@ -0,0 +1,17 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * triggerId: "trigger_id", + * externalUserId: "external_user_id" + * } + */ +export interface ListWorkflowsDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; + /** The external user ID who owns the trigger */ + externalUserId: string; +} diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersRetrieveRequest.ts b/src/api/resources/deployedTriggers/client/requests/RetrieveDeployedTriggersRequest.ts similarity index 52% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersRetrieveRequest.ts rename to src/api/resources/deployedTriggers/client/requests/RetrieveDeployedTriggersRequest.ts index 20f13ba..f5d88c0 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersRetrieveRequest.ts +++ b/src/api/resources/deployedTriggers/client/requests/RetrieveDeployedTriggersRequest.ts @@ -3,10 +3,15 @@ /** * @example * { + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersRetrieveRequest { +export interface RetrieveDeployedTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** Your end user ID, for whom you deployed the trigger */ externalUserId: string; } diff --git a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts index 500728e..277443e 100644 --- a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts +++ b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts @@ -5,10 +5,15 @@ import type * as Pipedream from "../../../../index.js"; /** * @example * { + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id" * } */ export interface UpdateTriggerOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** The external user ID who owns the trigger */ externalUserId: string; /** Whether the trigger should be active */ diff --git a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts index f64b3f9..7a14fd6 100644 --- a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts +++ b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts @@ -3,11 +3,16 @@ /** * @example * { + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id", * webhookUrls: ["webhook_urls"] * } */ export interface UpdateTriggerWebhooksOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** The external user ID who owns the trigger */ externalUserId: string; /** Array of webhook URLs to set */ diff --git a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts index d2cbe7f..f83d0b7 100644 --- a/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts +++ b/src/api/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts @@ -3,11 +3,16 @@ /** * @example * { + * projectId: "project_id", + * triggerId: "trigger_id", * externalUserId: "external_user_id", * workflowIds: ["workflow_ids"] * } */ export interface UpdateTriggerWorkflowsOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + triggerId: string; /** The external user ID who owns the trigger */ externalUserId: string; /** Array of workflow IDs to set */ diff --git a/src/api/resources/deployedTriggers/client/requests/index.ts b/src/api/resources/deployedTriggers/client/requests/index.ts index 54ff907..a6a3b69 100644 --- a/src/api/resources/deployedTriggers/client/requests/index.ts +++ b/src/api/resources/deployedTriggers/client/requests/index.ts @@ -1,9 +1,9 @@ -export type { DeployedTriggersDeleteRequest } from "./DeployedTriggersDeleteRequest.js"; -export type { DeployedTriggersListEventsRequest } from "./DeployedTriggersListEventsRequest.js"; -export type { DeployedTriggersListRequest } from "./DeployedTriggersListRequest.js"; -export type { DeployedTriggersListWebhooksRequest } from "./DeployedTriggersListWebhooksRequest.js"; -export type { DeployedTriggersListWorkflowsRequest } from "./DeployedTriggersListWorkflowsRequest.js"; -export type { DeployedTriggersRetrieveRequest } from "./DeployedTriggersRetrieveRequest.js"; +export type { DeleteDeployedTriggersRequest } from "./DeleteDeployedTriggersRequest.js"; +export type { ListDeployedTriggersRequest } from "./ListDeployedTriggersRequest.js"; +export type { ListEventsDeployedTriggersRequest } from "./ListEventsDeployedTriggersRequest.js"; +export type { ListWebhooksDeployedTriggersRequest } from "./ListWebhooksDeployedTriggersRequest.js"; +export type { ListWorkflowsDeployedTriggersRequest } from "./ListWorkflowsDeployedTriggersRequest.js"; +export type { RetrieveDeployedTriggersRequest } from "./RetrieveDeployedTriggersRequest.js"; export type { UpdateTriggerOpts } from "./UpdateTriggerOpts.js"; export type { UpdateTriggerWebhooksOpts } from "./UpdateTriggerWebhooksOpts.js"; export type { UpdateTriggerWorkflowsOpts } from "./UpdateTriggerWorkflowsOpts.js"; diff --git a/src/api/resources/fileStash/client/Client.ts b/src/api/resources/fileStash/client/Client.ts index 6031153..98daa17 100644 --- a/src/api/resources/fileStash/client/Client.ts +++ b/src/api/resources/fileStash/client/Client.ts @@ -27,17 +27,17 @@ export class FileStash { * @throws {@link Pipedream.TooManyRequestsError} */ public downloadFile( - request: Pipedream.FileStashDownloadFileRequest, + request: Pipedream.DownloadFileFileStashRequest, requestOptions?: FileStash.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__downloadFile(request, requestOptions)); } private async __downloadFile( - request: Pipedream.FileStashDownloadFileRequest, + request: Pipedream.DownloadFileFileStashRequest, requestOptions?: FileStash.RequestOptions, ): Promise> { - const { s3Key } = request; + const { projectId, s3Key } = request; const _queryParams: Record = {}; _queryParams.s3_key = s3Key; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( @@ -62,6 +62,8 @@ export class FileStash { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { data: _response.body, rawResponse: _response.rawResponse }; diff --git a/src/api/resources/fileStash/client/requests/DownloadFileFileStashRequest.ts b/src/api/resources/fileStash/client/requests/DownloadFileFileStashRequest.ts new file mode 100644 index 0000000..18c9057 --- /dev/null +++ b/src/api/resources/fileStash/client/requests/DownloadFileFileStashRequest.ts @@ -0,0 +1,14 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * s3Key: "s3_key" + * } + */ +export interface DownloadFileFileStashRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + s3Key: string; +} diff --git a/src/api/resources/fileStash/client/requests/FileStashDownloadFileRequest.ts b/src/api/resources/fileStash/client/requests/FileStashDownloadFileRequest.ts deleted file mode 100644 index c066299..0000000 --- a/src/api/resources/fileStash/client/requests/FileStashDownloadFileRequest.ts +++ /dev/null @@ -1,11 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -/** - * @example - * { - * s3Key: "s3_key" - * } - */ -export interface FileStashDownloadFileRequest { - s3Key: string; -} diff --git a/src/api/resources/fileStash/client/requests/index.ts b/src/api/resources/fileStash/client/requests/index.ts index b96258f..a1e7c7c 100644 --- a/src/api/resources/fileStash/client/requests/index.ts +++ b/src/api/resources/fileStash/client/requests/index.ts @@ -1 +1 @@ -export type { FileStashDownloadFileRequest } from "./FileStashDownloadFileRequest.js"; +export type { DownloadFileFileStashRequest } from "./DownloadFileFileStashRequest.js"; diff --git a/src/api/resources/oauthTokens/client/Client.ts b/src/api/resources/oauthTokens/client/Client.ts index 34bfef5..5526839 100644 --- a/src/api/resources/oauthTokens/client/Client.ts +++ b/src/api/resources/oauthTokens/client/Client.ts @@ -76,6 +76,8 @@ export class OauthTokens { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/projects/client/Client.ts b/src/api/resources/projects/client/Client.ts index 0e68abc..ce1f6ed 100644 --- a/src/api/resources/projects/client/Client.ts +++ b/src/api/resources/projects/client/Client.ts @@ -26,22 +26,28 @@ export class Projects { /** * Retrieve project configuration and environment details * + * @param {Pipedream.RetrieveInfoProjectsRequest} request * @param {Projects.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.projects.retrieveInfo() + * await client.projects.retrieveInfo({ + * projectId: "project_id" + * }) */ public retrieveInfo( + request: Pipedream.RetrieveInfoProjectsRequest, requestOptions?: Projects.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieveInfo(requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieveInfo(request, requestOptions)); } private async __retrieveInfo( + request: Pipedream.RetrieveInfoProjectsRequest, requestOptions?: Projects.RequestOptions, ): Promise> { + const { projectId } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -63,6 +69,8 @@ export class Projects { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/projects/client/index.ts b/src/api/resources/projects/client/index.ts index cb0ff5c..195f9aa 100644 --- a/src/api/resources/projects/client/index.ts +++ b/src/api/resources/projects/client/index.ts @@ -1 +1 @@ -export {}; +export * from "./requests/index.js"; diff --git a/src/api/resources/projects/client/requests/RetrieveInfoProjectsRequest.ts b/src/api/resources/projects/client/requests/RetrieveInfoProjectsRequest.ts new file mode 100644 index 0000000..8e138ed --- /dev/null +++ b/src/api/resources/projects/client/requests/RetrieveInfoProjectsRequest.ts @@ -0,0 +1,12 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id" + * } + */ +export interface RetrieveInfoProjectsRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; +} diff --git a/src/api/resources/projects/client/requests/index.ts b/src/api/resources/projects/client/requests/index.ts new file mode 100644 index 0000000..1993d55 --- /dev/null +++ b/src/api/resources/projects/client/requests/index.ts @@ -0,0 +1 @@ +export type { RetrieveInfoProjectsRequest } from "./RetrieveInfoProjectsRequest.js"; diff --git a/src/api/resources/proxy/client/requests/DeleteProxyRequest.ts b/src/api/resources/proxy/client/requests/DeleteProxyRequest.ts new file mode 100644 index 0000000..575d7d8 --- /dev/null +++ b/src/api/resources/proxy/client/requests/DeleteProxyRequest.ts @@ -0,0 +1,21 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * url64: "url_64", + * externalUserId: "external_user_id", + * accountId: "account_id" + * } + */ +export interface DeleteProxyRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** Base64-encoded target URL */ + url64: string; + /** The external user ID for the proxy request */ + externalUserId: string; + /** The account ID to use for authentication */ + accountId: string; +} diff --git a/src/api/resources/proxy/client/requests/GetProxyRequest.ts b/src/api/resources/proxy/client/requests/GetProxyRequest.ts new file mode 100644 index 0000000..dd1e85d --- /dev/null +++ b/src/api/resources/proxy/client/requests/GetProxyRequest.ts @@ -0,0 +1,21 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * url64: "url_64", + * externalUserId: "external_user_id", + * accountId: "account_id" + * } + */ +export interface GetProxyRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** Base64-encoded target URL */ + url64: string; + /** The external user ID for the proxy request */ + externalUserId: string; + /** The account ID to use for authentication */ + accountId: string; +} diff --git a/src/api/resources/proxy/client/requests/PatchProxyRequest.ts b/src/api/resources/proxy/client/requests/PatchProxyRequest.ts new file mode 100644 index 0000000..4faeb88 --- /dev/null +++ b/src/api/resources/proxy/client/requests/PatchProxyRequest.ts @@ -0,0 +1,28 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * url64: "url_64", + * externalUserId: "external_user_id", + * accountId: "account_id", + * body: { + * "string": { + * "key": "value" + * } + * } + * } + */ +export interface PatchProxyRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** Base64-encoded target URL */ + url64: string; + /** The external user ID for the proxy request */ + externalUserId: string; + /** The account ID to use for authentication */ + accountId: string; + /** Request body to forward to the target API */ + body: Record; +} diff --git a/src/api/resources/proxy/client/requests/PostProxyRequest.ts b/src/api/resources/proxy/client/requests/PostProxyRequest.ts new file mode 100644 index 0000000..384b59c --- /dev/null +++ b/src/api/resources/proxy/client/requests/PostProxyRequest.ts @@ -0,0 +1,28 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * url64: "url_64", + * externalUserId: "external_user_id", + * accountId: "account_id", + * body: { + * "string": { + * "key": "value" + * } + * } + * } + */ +export interface PostProxyRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** Base64-encoded target URL */ + url64: string; + /** The external user ID for the proxy request */ + externalUserId: string; + /** The account ID to use for authentication */ + accountId: string; + /** Request body to forward to the target API */ + body: Record; +} diff --git a/src/api/resources/proxy/client/requests/PutProxyRequest.ts b/src/api/resources/proxy/client/requests/PutProxyRequest.ts new file mode 100644 index 0000000..2174b8b --- /dev/null +++ b/src/api/resources/proxy/client/requests/PutProxyRequest.ts @@ -0,0 +1,28 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * url64: "url_64", + * externalUserId: "external_user_id", + * accountId: "account_id", + * body: { + * "string": { + * "key": "value" + * } + * } + * } + */ +export interface PutProxyRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** Base64-encoded target URL */ + url64: string; + /** The external user ID for the proxy request */ + externalUserId: string; + /** The account ID to use for authentication */ + accountId: string; + /** Request body to forward to the target API */ + body: Record; +} diff --git a/src/api/resources/tokens/client/Client.ts b/src/api/resources/tokens/client/Client.ts index 1515718..5e0f84e 100644 --- a/src/api/resources/tokens/client/Client.ts +++ b/src/api/resources/tokens/client/Client.ts @@ -33,6 +33,7 @@ export class Tokens { * * @example * await client.tokens.create({ + * projectId: "project_id", * externalUserId: "external_user_id" * }) */ @@ -47,6 +48,7 @@ export class Tokens { request: Pipedream.CreateTokenOpts, requestOptions?: Tokens.RequestOptions, ): Promise> { + const { projectId, ..._body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -67,13 +69,15 @@ export class Tokens { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.CreateTokenOpts.jsonOrThrow(request, { + body: serializers.CreateTokenOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -123,32 +127,29 @@ export class Tokens { /** * Confirm the validity of a Connect token * - * @param {Pipedream.ConnectToken} ctok - * @param {Pipedream.TokensValidateRequest} request + * @param {Pipedream.ValidateTokensRequest} request * @param {Tokens.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.tokens.validate("ctok", { - * appId: "app_id", - * oauthAppId: "oauth_app_id" + * await client.tokens.validate({ + * ctok: "ctok", + * appId: "app_id" * }) */ public validate( - ctok: Pipedream.ConnectToken, - request: Pipedream.TokensValidateRequest, + request: Pipedream.ValidateTokensRequest, requestOptions?: Tokens.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__validate(ctok, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__validate(request, requestOptions)); } private async __validate( - ctok: Pipedream.ConnectToken, - request: Pipedream.TokensValidateRequest, + request: Pipedream.ValidateTokensRequest, requestOptions?: Tokens.RequestOptions, ): Promise> { - const { appId, oauthAppId } = request; + const { ctok, appId, oauthAppId } = request; const _queryParams: Record = {}; _queryParams.app_id = appId; if (oauthAppId != null) { @@ -176,6 +177,8 @@ export class Tokens { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/tokens/client/requests/CreateTokenOpts.ts b/src/api/resources/tokens/client/requests/CreateTokenOpts.ts index 0639308..65cef32 100644 --- a/src/api/resources/tokens/client/requests/CreateTokenOpts.ts +++ b/src/api/resources/tokens/client/requests/CreateTokenOpts.ts @@ -3,10 +3,13 @@ /** * @example * { + * projectId: "project_id", * externalUserId: "external_user_id" * } */ export interface CreateTokenOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** List of allowed origins for CORS */ allowedOrigins?: string[]; /** URI to redirect to on error */ diff --git a/src/api/resources/tokens/client/requests/TokensValidateRequest.ts b/src/api/resources/tokens/client/requests/ValidateTokensRequest.ts similarity index 59% rename from src/api/resources/tokens/client/requests/TokensValidateRequest.ts rename to src/api/resources/tokens/client/requests/ValidateTokensRequest.ts index 8317f20..71888cf 100644 --- a/src/api/resources/tokens/client/requests/TokensValidateRequest.ts +++ b/src/api/resources/tokens/client/requests/ValidateTokensRequest.ts @@ -1,13 +1,16 @@ // This file was auto-generated by Fern from our API Definition. +import type * as Pipedream from "../../../../index.js"; + /** * @example * { - * appId: "app_id", - * oauthAppId: "oauth_app_id" + * ctok: "ctok", + * appId: "app_id" * } */ -export interface TokensValidateRequest { +export interface ValidateTokensRequest { + ctok: Pipedream.ConnectToken; /** The app ID to validate against */ appId: string; /** The OAuth app ID to validate against (if the token is for an OAuth app) */ diff --git a/src/api/resources/tokens/client/requests/index.ts b/src/api/resources/tokens/client/requests/index.ts index d21749e..2b9a758 100644 --- a/src/api/resources/tokens/client/requests/index.ts +++ b/src/api/resources/tokens/client/requests/index.ts @@ -1,2 +1,2 @@ export type { CreateTokenOpts } from "./CreateTokenOpts.js"; -export type { TokensValidateRequest } from "./TokensValidateRequest.js"; +export type { ValidateTokensRequest } from "./ValidateTokensRequest.js"; diff --git a/src/api/resources/triggers/client/Client.ts b/src/api/resources/triggers/client/Client.ts index 18ea753..6229dd9 100644 --- a/src/api/resources/triggers/client/Client.ts +++ b/src/api/resources/triggers/client/Client.ts @@ -26,29 +26,25 @@ export class Triggers { /** * Retrieve available triggers with optional search and app filtering * - * @param {Pipedream.TriggersListRequest} request + * @param {Pipedream.ListTriggersRequest} request * @param {Triggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.triggers.list({ - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app" + * projectId: "project_id" * }) */ public async list( - request: Pipedream.TriggersListRequest = {}, + request: Pipedream.ListTriggersRequest, requestOptions?: Triggers.RequestOptions, - ): Promise> { + ): Promise> { const list = core.HttpResponsePromise.interceptFunction( async ( - request: Pipedream.TriggersListRequest, + request: Pipedream.ListTriggersRequest, ): Promise> => { - const { after, before, limit, q, app } = request; + const { projectId, after, before, limit, q, app } = request; const _queryParams: Record = {}; if (after != null) { _queryParams.after = after; @@ -86,6 +82,8 @@ export class Triggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -131,7 +129,7 @@ export class Triggers { }, ); const dataWithRawResponse = await list(request).withRawResponse(); - return new core.Pageable({ + return new core.Page({ response: dataWithRawResponse.data, rawResponse: dataWithRawResponse.rawResponse, hasNextPage: (response) => @@ -147,31 +145,30 @@ export class Triggers { /** * Get detailed configuration for a specific trigger by its key * - * @param {string} componentId - The key that uniquely identifies the component (e.g., 'slack-send-message') - * @param {Pipedream.TriggersRetrieveRequest} request + * @param {Pipedream.RetrieveTriggersRequest} request * @param {Triggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.triggers.retrieve("component_id", { + * await client.triggers.retrieve({ + * projectId: "project_id", + * componentId: "component_id", * version: "1.2.3" * }) */ public retrieve( - componentId: string, - request: Pipedream.TriggersRetrieveRequest = {}, + request: Pipedream.RetrieveTriggersRequest, requestOptions?: Triggers.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__retrieve(componentId, request, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions)); } private async __retrieve( - componentId: string, - request: Pipedream.TriggersRetrieveRequest = {}, + request: Pipedream.RetrieveTriggersRequest, requestOptions?: Triggers.RequestOptions, ): Promise> { - const { version } = request; + const { projectId, componentId, version } = request; const _queryParams: Record = {}; if (version != null) { _queryParams.version = version; @@ -198,6 +195,8 @@ export class Triggers { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -247,29 +246,33 @@ export class Triggers { /** * Retrieve remote options for a given prop for a trigger * - * @param {Pipedream.ConfigurePropOpts} request + * @param {Pipedream.ConfigurePropTriggersRequest} request * @param {Triggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.triggers.configureProp({ - * id: "id", - * externalUserId: "external_user_id", - * propName: "prop_name" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } * }) */ public configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropTriggersRequest, requestOptions?: Triggers.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__configureProp(request, requestOptions)); } private async __configureProp( - request: Pipedream.ConfigurePropOpts, + request: Pipedream.ConfigurePropTriggersRequest, requestOptions?: Triggers.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -290,13 +293,15 @@ export class Triggers { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ConfigurePropOpts.jsonOrThrow(request, { + body: serializers.ConfigurePropOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -346,28 +351,32 @@ export class Triggers { /** * Reload the prop definition based on the currently configured props * - * @param {Pipedream.ReloadPropsOpts} request + * @param {Pipedream.ReloadPropsTriggersRequest} request * @param {Triggers.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example * await client.triggers.reloadProps({ - * id: "id", - * externalUserId: "external_user_id" + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } * }) */ public reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsTriggersRequest, requestOptions?: Triggers.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__reloadProps(request, requestOptions)); } private async __reloadProps( - request: Pipedream.ReloadPropsOpts, + request: Pipedream.ReloadPropsTriggersRequest, requestOptions?: Triggers.RequestOptions, ): Promise> { + const { projectId, body: _body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -388,13 +397,15 @@ export class Triggers { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.ReloadPropsOpts.jsonOrThrow(request, { + body: serializers.ReloadPropsOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { @@ -451,6 +462,7 @@ export class Triggers { * * @example * await client.triggers.deploy({ + * projectId: "project_id", * id: "id", * externalUserId: "external_user_id" * }) @@ -466,6 +478,7 @@ export class Triggers { request: Pipedream.DeployTriggerOpts, requestOptions?: Triggers.RequestOptions, ): Promise> { + const { projectId, ..._body } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -486,13 +499,15 @@ export class Triggers { contentType: "application/json", queryParameters: requestOptions?.queryParams, requestType: "json", - body: serializers.DeployTriggerOpts.jsonOrThrow(request, { + body: serializers.DeployTriggerOpts.jsonOrThrow(_body, { unrecognizedObjectKeys: "strip", omitUndefined: true, }), timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { diff --git a/src/api/resources/triggers/client/requests/ConfigurePropTriggersRequest.ts b/src/api/resources/triggers/client/requests/ConfigurePropTriggersRequest.ts new file mode 100644 index 0000000..550f99b --- /dev/null +++ b/src/api/resources/triggers/client/requests/ConfigurePropTriggersRequest.ts @@ -0,0 +1,20 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id", + * propName: "prop_name" + * } + * } + */ +export interface ConfigurePropTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ConfigurePropOpts; +} diff --git a/src/api/resources/triggers/client/requests/DeployTriggerOpts.ts b/src/api/resources/triggers/client/requests/DeployTriggerOpts.ts index 6f864a9..7401fed 100644 --- a/src/api/resources/triggers/client/requests/DeployTriggerOpts.ts +++ b/src/api/resources/triggers/client/requests/DeployTriggerOpts.ts @@ -5,15 +5,18 @@ import type * as Pipedream from "../../../../index.js"; /** * @example * { + * projectId: "project_id", * id: "id", * externalUserId: "external_user_id" * } */ export interface DeployTriggerOpts { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The trigger component ID */ id: string; /** Optional trigger component version (in SemVer format, for example '1.0.0'), defaults to latest */ - version?: string; + version?: string | null; /** The external user ID */ externalUserId: string; configuredProps?: Pipedream.ConfiguredProps; diff --git a/src/api/resources/triggers/client/requests/TriggersListRequest.ts b/src/api/resources/triggers/client/requests/ListTriggersRequest.ts similarity index 74% rename from src/api/resources/triggers/client/requests/TriggersListRequest.ts rename to src/api/resources/triggers/client/requests/ListTriggersRequest.ts index e2add81..deb0e1b 100644 --- a/src/api/resources/triggers/client/requests/TriggersListRequest.ts +++ b/src/api/resources/triggers/client/requests/ListTriggersRequest.ts @@ -3,14 +3,12 @@ /** * @example * { - * after: "after", - * before: "before", - * limit: 1, - * q: "q", - * app: "app" + * projectId: "project_id" * } */ -export interface TriggersListRequest { +export interface ListTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; /** The cursor to start from for pagination */ after?: string; /** The cursor to end before for pagination */ diff --git a/src/api/resources/triggers/client/requests/ReloadPropsTriggersRequest.ts b/src/api/resources/triggers/client/requests/ReloadPropsTriggersRequest.ts new file mode 100644 index 0000000..97b6601 --- /dev/null +++ b/src/api/resources/triggers/client/requests/ReloadPropsTriggersRequest.ts @@ -0,0 +1,19 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../../../index.js"; + +/** + * @example + * { + * projectId: "project_id", + * body: { + * id: "id", + * externalUserId: "external_user_id" + * } + * } + */ +export interface ReloadPropsTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + body: Pipedream.ReloadPropsOpts; +} diff --git a/src/api/resources/triggers/client/requests/RetrieveTriggersRequest.ts b/src/api/resources/triggers/client/requests/RetrieveTriggersRequest.ts new file mode 100644 index 0000000..f9506aa --- /dev/null +++ b/src/api/resources/triggers/client/requests/RetrieveTriggersRequest.ts @@ -0,0 +1,18 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * @example + * { + * projectId: "project_id", + * componentId: "component_id", + * version: "1.2.3" + * } + */ +export interface RetrieveTriggersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; + /** The key that uniquely identifies the component (e.g., 'slack-send-message') */ + componentId: string; + /** Optional semantic version of the component to retrieve (for example '1.0.0') */ + version?: string; +} diff --git a/src/api/resources/triggers/client/requests/TriggersRetrieveRequest.ts b/src/api/resources/triggers/client/requests/TriggersRetrieveRequest.ts deleted file mode 100644 index 0cd0f3e..0000000 --- a/src/api/resources/triggers/client/requests/TriggersRetrieveRequest.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This file was auto-generated by Fern from our API Definition. - -/** - * @example - * { - * version: "1.2.3" - * } - */ -export interface TriggersRetrieveRequest { - /** Optional semantic version of the component to retrieve (for example '1.0.0') */ - version?: string; -} diff --git a/src/api/resources/triggers/client/requests/index.ts b/src/api/resources/triggers/client/requests/index.ts index 8ebeb47..115d1a6 100644 --- a/src/api/resources/triggers/client/requests/index.ts +++ b/src/api/resources/triggers/client/requests/index.ts @@ -1,3 +1,5 @@ +export type { ConfigurePropTriggersRequest } from "./ConfigurePropTriggersRequest.js"; export type { DeployTriggerOpts } from "./DeployTriggerOpts.js"; -export type { TriggersListRequest } from "./TriggersListRequest.js"; -export type { TriggersRetrieveRequest } from "./TriggersRetrieveRequest.js"; +export type { ListTriggersRequest } from "./ListTriggersRequest.js"; +export type { ReloadPropsTriggersRequest } from "./ReloadPropsTriggersRequest.js"; +export type { RetrieveTriggersRequest } from "./RetrieveTriggersRequest.js"; diff --git a/src/api/resources/users/client/Client.ts b/src/api/resources/users/client/Client.ts index c4a16e0..d8166a1 100644 --- a/src/api/resources/users/client/Client.ts +++ b/src/api/resources/users/client/Client.ts @@ -25,25 +25,29 @@ export class Users { /** * Remove an external user and all their associated accounts and resources * - * @param {string} externalUserId + * @param {Pipedream.DeleteExternalUserUsersRequest} request * @param {Users.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Pipedream.TooManyRequestsError} * * @example - * await client.users.deleteExternalUser("external_user_id") + * await client.users.deleteExternalUser({ + * projectId: "project_id", + * externalUserId: "external_user_id" + * }) */ public deleteExternalUser( - externalUserId: string, + request: Pipedream.DeleteExternalUserUsersRequest, requestOptions?: Users.RequestOptions, ): core.HttpResponsePromise { - return core.HttpResponsePromise.fromPromise(this.__deleteExternalUser(externalUserId, requestOptions)); + return core.HttpResponsePromise.fromPromise(this.__deleteExternalUser(request, requestOptions)); } private async __deleteExternalUser( - externalUserId: string, + request: Pipedream.DeleteExternalUserUsersRequest, requestOptions?: Users.RequestOptions, ): Promise> { + const { projectId, externalUserId } = request; const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, mergeOnlyDefinedHeaders({ @@ -65,6 +69,8 @@ export class Users { timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000, maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries, abortSignal: requestOptions?.abortSignal, + fetchFn: this._options?.fetch, + logging: this._options.logging, }); if (_response.ok) { return { data: undefined, rawResponse: _response.rawResponse }; diff --git a/src/api/resources/users/client/index.ts b/src/api/resources/users/client/index.ts index cb0ff5c..195f9aa 100644 --- a/src/api/resources/users/client/index.ts +++ b/src/api/resources/users/client/index.ts @@ -1 +1 @@ -export {}; +export * from "./requests/index.js"; diff --git a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWebhooksRequest.ts b/src/api/resources/users/client/requests/DeleteExternalUserUsersRequest.ts similarity index 52% rename from src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWebhooksRequest.ts rename to src/api/resources/users/client/requests/DeleteExternalUserUsersRequest.ts index 20f90f7..80658ec 100644 --- a/src/api/resources/deployedTriggers/client/requests/DeployedTriggersListWebhooksRequest.ts +++ b/src/api/resources/users/client/requests/DeleteExternalUserUsersRequest.ts @@ -3,10 +3,12 @@ /** * @example * { + * projectId: "project_id", * externalUserId: "external_user_id" * } */ -export interface DeployedTriggersListWebhooksRequest { - /** The external user ID who owns the trigger */ +export interface DeleteExternalUserUsersRequest { + /** The project ID, which starts with 'proj_'. */ + projectId: string; externalUserId: string; } diff --git a/src/api/resources/users/client/requests/index.ts b/src/api/resources/users/client/requests/index.ts new file mode 100644 index 0000000..9012df7 --- /dev/null +++ b/src/api/resources/users/client/requests/index.ts @@ -0,0 +1 @@ +export type { DeleteExternalUserUsersRequest } from "./DeleteExternalUserUsersRequest.js"; diff --git a/src/api/types/Account.ts b/src/api/types/Account.ts index 5165623..353fae2 100644 --- a/src/api/types/Account.ts +++ b/src/api/types/Account.ts @@ -8,26 +8,26 @@ import type * as Pipedream from "../index.js"; export interface Account { id: Pipedream.AccountId; /** The custom name of the account if set. */ - name?: string; + name?: string | null; /** The external ID associated with the account. */ externalId?: string; /** Indicates if the account is healthy. Pipedream will periodically retry token refresh and test requests for unhealthy accounts */ healthy?: boolean; /** Indicates if the account is no longer active */ - dead?: boolean; + dead?: boolean | null; app?: Pipedream.App; /** The date and time the account was created, an ISO 8601 formatted string */ createdAt?: Date; /** The date and time the account was last updated, an ISO 8601 formatted string */ updatedAt?: Date; /** The credentials associated with the account, if the `include_credentials` parameter was set to true in the request */ - credentials?: Record; + credentials?: Record | null; /** The date and time the account's credentials expiration, an ISO 8601 formatted string */ expiresAt?: Date; /** The error message if the account is unhealthy or dead, null otherwise */ - error?: string; + error?: string | null; /** The date and time the account was last refreshed, an ISO 8601 formatted string */ lastRefreshedAt?: Date; /** The date and time the account will next be refreshed, an ISO 8601 formatted string */ - nextRefreshAt?: Date; + nextRefreshAt?: Date | null; } diff --git a/src/api/types/App.ts b/src/api/types/App.ts index e1f07dd..aef674d 100644 --- a/src/api/types/App.ts +++ b/src/api/types/App.ts @@ -7,18 +7,18 @@ import type * as Pipedream from "../index.js"; */ export interface App { /** ID of the app. Only applies for OAuth apps. */ - id?: string; + id?: string | null; /** The name slug of the target app (see https://pipedream.com/docs/connect/quickstart#find-your-apps-name-slug) */ nameSlug: string; /** The human-readable name of the app */ name: string; - authType?: Pipedream.AppAuthType; + authType?: Pipedream.AppAuthType | null; /** A short description of the app */ - description?: string; + description?: string | null; /** The URL to the app's logo */ imgSrc: string; /** A JSON string representing the custom fields for the app */ - customFieldsJson?: string; + customFieldsJson: string | null; /** Categories associated with the app */ categories: string[]; /** A rough directional ordering of app popularity, subject to changes by Pipedream */ diff --git a/src/api/types/AppCategory.ts b/src/api/types/AppCategory.ts index b7da503..4ef0fb9 100644 --- a/src/api/types/AppCategory.ts +++ b/src/api/types/AppCategory.ts @@ -9,5 +9,5 @@ export interface AppCategory { /** The human-readable name of the app category */ name?: string; /** A short description of the app category */ - description?: string; + description?: string | null; } diff --git a/src/api/types/Component.ts b/src/api/types/Component.ts index de1a3d1..297d571 100644 --- a/src/api/types/Component.ts +++ b/src/api/types/Component.ts @@ -11,9 +11,9 @@ export interface Component { version: string; configurableProps: Pipedream.ConfigurableProp[]; /** A description of the component */ - description?: string; + description?: string | null; /** The type of component (trigger or action) */ - componentType?: string; - stash?: Pipedream.ComponentStash; - annotations?: Pipedream.ToolAnnotations; + componentType?: string | null; + stash?: Pipedream.ComponentStash | null; + annotations?: Pipedream.ToolAnnotations | null; } diff --git a/src/api/types/ConfigurableProp.ts b/src/api/types/ConfigurableProp.ts index 390eaa2..c8485ab 100644 --- a/src/api/types/ConfigurableProp.ts +++ b/src/api/types/ConfigurableProp.ts @@ -10,21 +10,21 @@ export interface ConfigurableProp { name: string; type: Pipedream.ConfigurablePropType; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAirtableBaseId.ts b/src/api/types/ConfigurablePropAirtableBaseId.ts index 7755a5a..4608045 100644 --- a/src/api/types/ConfigurablePropAirtableBaseId.ts +++ b/src/api/types/ConfigurablePropAirtableBaseId.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropAirtableBaseId { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAirtableFieldId.ts b/src/api/types/ConfigurablePropAirtableFieldId.ts index 1676649..71e6254 100644 --- a/src/api/types/ConfigurablePropAirtableFieldId.ts +++ b/src/api/types/ConfigurablePropAirtableFieldId.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropAirtableFieldId { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAirtableTableId.ts b/src/api/types/ConfigurablePropAirtableTableId.ts index 4d9109c..d0ffc31 100644 --- a/src/api/types/ConfigurablePropAirtableTableId.ts +++ b/src/api/types/ConfigurablePropAirtableTableId.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropAirtableTableId { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAirtableViewId.ts b/src/api/types/ConfigurablePropAirtableViewId.ts index 155aa84..a5c3944 100644 --- a/src/api/types/ConfigurablePropAirtableViewId.ts +++ b/src/api/types/ConfigurablePropAirtableViewId.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropAirtableViewId { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAlert.ts b/src/api/types/ConfigurablePropAlert.ts index 3f08428..bc25428 100644 --- a/src/api/types/ConfigurablePropAlert.ts +++ b/src/api/types/ConfigurablePropAlert.ts @@ -10,21 +10,21 @@ export interface ConfigurablePropAlert { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAny.ts b/src/api/types/ConfigurablePropAny.ts index 7277cfb..1807ee6 100644 --- a/src/api/types/ConfigurablePropAny.ts +++ b/src/api/types/ConfigurablePropAny.ts @@ -9,21 +9,21 @@ export interface ConfigurablePropAny { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropAnyOptionsItem.ts b/src/api/types/ConfigurablePropAnyOptionsItem.ts index 2576de5..1345002 100644 --- a/src/api/types/ConfigurablePropAnyOptionsItem.ts +++ b/src/api/types/ConfigurablePropAnyOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropAnyOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropApp.ts b/src/api/types/ConfigurablePropApp.ts index 600d82c..098baec 100644 --- a/src/api/types/ConfigurablePropApp.ts +++ b/src/api/types/ConfigurablePropApp.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropApp { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropApphook.ts b/src/api/types/ConfigurablePropApphook.ts index ae1e0bf..b2ee325 100644 --- a/src/api/types/ConfigurablePropApphook.ts +++ b/src/api/types/ConfigurablePropApphook.ts @@ -5,29 +5,29 @@ export interface ConfigurablePropApphook { /** The name of the app prop that this apphook depends on */ appProp: string; /** List of event names to listen for */ - eventNames?: string[]; + eventNames?: string[] | null; /** Whether this apphook is remote */ - remote?: boolean; + remote?: boolean | null; /** Static configuration for the apphook */ - static?: unknown[]; + static?: unknown[] | null; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropBoolean.ts b/src/api/types/ConfigurablePropBoolean.ts index fd6c9cc..8f53107 100644 --- a/src/api/types/ConfigurablePropBoolean.ts +++ b/src/api/types/ConfigurablePropBoolean.ts @@ -9,21 +9,21 @@ export interface ConfigurablePropBoolean { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropBooleanOptionsItem.ts b/src/api/types/ConfigurablePropBooleanOptionsItem.ts index 9c7dc0d..9758419 100644 --- a/src/api/types/ConfigurablePropBooleanOptionsItem.ts +++ b/src/api/types/ConfigurablePropBooleanOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropBooleanOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropDb.ts b/src/api/types/ConfigurablePropDb.ts index 4047086..a10e5ea 100644 --- a/src/api/types/ConfigurablePropDb.ts +++ b/src/api/types/ConfigurablePropDb.ts @@ -5,21 +5,21 @@ export interface ConfigurablePropDb { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropDiscord.ts b/src/api/types/ConfigurablePropDiscord.ts index dc3d7b2..3fa2c0a 100644 --- a/src/api/types/ConfigurablePropDiscord.ts +++ b/src/api/types/ConfigurablePropDiscord.ts @@ -5,21 +5,21 @@ export interface ConfigurablePropDiscord { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropDiscordChannel.ts b/src/api/types/ConfigurablePropDiscordChannel.ts index 302c506..9b49e0e 100644 --- a/src/api/types/ConfigurablePropDiscordChannel.ts +++ b/src/api/types/ConfigurablePropDiscordChannel.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropDiscordChannel { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropDiscordChannelArray.ts b/src/api/types/ConfigurablePropDiscordChannelArray.ts index c6869dd..76aec18 100644 --- a/src/api/types/ConfigurablePropDiscordChannelArray.ts +++ b/src/api/types/ConfigurablePropDiscordChannelArray.ts @@ -7,21 +7,21 @@ export interface ConfigurablePropDiscordChannelArray { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropHttp.ts b/src/api/types/ConfigurablePropHttp.ts index fd1dd12..00ccb90 100644 --- a/src/api/types/ConfigurablePropHttp.ts +++ b/src/api/types/ConfigurablePropHttp.ts @@ -3,25 +3,25 @@ export interface ConfigurablePropHttp { type: "$.interface.http"; /** Whether this HTTP interface allows custom responses */ - customResponse?: boolean; + customResponse?: boolean | null; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropInteger.ts b/src/api/types/ConfigurablePropInteger.ts index 72d5338..b4b7e38 100644 --- a/src/api/types/ConfigurablePropInteger.ts +++ b/src/api/types/ConfigurablePropInteger.ts @@ -5,30 +5,30 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropInteger { type: "integer"; /** The minimum value for this integer prop. */ - min?: number; + min?: number | null; /** The maximum value for this integer prop. */ - max?: number; + max?: number | null; default?: Pipedream.ConfiguredPropValueInteger; /** Available integer options */ - options?: Pipedream.ConfigurablePropIntegerOptionsItem[]; + options?: Pipedream.ConfigurablePropIntegerOptionsItem[] | null; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropIntegerArray.ts b/src/api/types/ConfigurablePropIntegerArray.ts index 9cd3335..5bc0f92 100644 --- a/src/api/types/ConfigurablePropIntegerArray.ts +++ b/src/api/types/ConfigurablePropIntegerArray.ts @@ -5,31 +5,31 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropIntegerArray { type: "integer[]"; /** The minimum value for integers in this array */ - min?: number; + min?: number | null; /** The maximum value for integers in this array */ - max?: number; + max?: number | null; /** Default array of integers */ - default?: Pipedream.ConfiguredPropValueInteger[]; + default?: Pipedream.ConfiguredPropValueInteger[] | null; /** Available options for the integer array */ - options?: Pipedream.ConfigurablePropIntegerArrayOptionsItem[]; + options?: Pipedream.ConfigurablePropIntegerArrayOptionsItem[] | null; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropIntegerArrayOptionsItem.ts b/src/api/types/ConfigurablePropIntegerArrayOptionsItem.ts index 8bf62f0..27c3c10 100644 --- a/src/api/types/ConfigurablePropIntegerArrayOptionsItem.ts +++ b/src/api/types/ConfigurablePropIntegerArrayOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropIntegerArrayOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropIntegerOptionsItem.ts b/src/api/types/ConfigurablePropIntegerOptionsItem.ts index a568fbf..fb3b7da 100644 --- a/src/api/types/ConfigurablePropIntegerOptionsItem.ts +++ b/src/api/types/ConfigurablePropIntegerOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropIntegerOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropObject.ts b/src/api/types/ConfigurablePropObject.ts index f675481..fd242d4 100644 --- a/src/api/types/ConfigurablePropObject.ts +++ b/src/api/types/ConfigurablePropObject.ts @@ -9,21 +9,21 @@ export interface ConfigurablePropObject { /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropObjectOptionsItem.ts b/src/api/types/ConfigurablePropObjectOptionsItem.ts index 6b092b2..67a8f69 100644 --- a/src/api/types/ConfigurablePropObjectOptionsItem.ts +++ b/src/api/types/ConfigurablePropObjectOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropObjectOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropSql.ts b/src/api/types/ConfigurablePropSql.ts index 132a593..fc72f8e 100644 --- a/src/api/types/ConfigurablePropSql.ts +++ b/src/api/types/ConfigurablePropSql.ts @@ -4,27 +4,27 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropSql { type: "sql"; - auth?: Pipedream.ConfigurablePropSqlAuth; + auth?: Pipedream.ConfigurablePropSqlAuth | null; default?: Pipedream.ConfiguredPropValueSql; options?: Pipedream.ConfigurablePropSqlOptionsItem[]; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropSqlOptionsItem.ts b/src/api/types/ConfigurablePropSqlOptionsItem.ts index f476bef..89c47a4 100644 --- a/src/api/types/ConfigurablePropSqlOptionsItem.ts +++ b/src/api/types/ConfigurablePropSqlOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropSqlOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropString.ts b/src/api/types/ConfigurablePropString.ts index 82ecb69..472dd8a 100644 --- a/src/api/types/ConfigurablePropString.ts +++ b/src/api/types/ConfigurablePropString.ts @@ -5,27 +5,27 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropString { type: "string"; /** If true, this prop is a secret and should not be displayed in plain text. */ - secret?: boolean; + secret?: boolean | null; default?: Pipedream.ConfiguredPropValueString; options?: Pipedream.ConfigurablePropStringOptionsItem[]; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropStringArray.ts b/src/api/types/ConfigurablePropStringArray.ts index 42b99ec..506d1b2 100644 --- a/src/api/types/ConfigurablePropStringArray.ts +++ b/src/api/types/ConfigurablePropStringArray.ts @@ -5,28 +5,28 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropStringArray { type: "string[]"; /** If true, this prop is a secret and should not be displayed in plain text. */ - secret?: boolean; + secret?: boolean | null; /** The default value for this prop */ - default?: Pipedream.ConfiguredPropValueString[]; + default?: Pipedream.ConfiguredPropValueString[] | null; options?: Pipedream.ConfigurablePropStringArrayOptionsItem[]; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurablePropStringArrayOptionsItem.ts b/src/api/types/ConfigurablePropStringArrayOptionsItem.ts index 5cce8de..b7e6ae0 100644 --- a/src/api/types/ConfigurablePropStringArrayOptionsItem.ts +++ b/src/api/types/ConfigurablePropStringArrayOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropStringArrayOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropStringOptionsItem.ts b/src/api/types/ConfigurablePropStringOptionsItem.ts index 7e86373..723762a 100644 --- a/src/api/types/ConfigurablePropStringOptionsItem.ts +++ b/src/api/types/ConfigurablePropStringOptionsItem.ts @@ -6,4 +6,4 @@ export type ConfigurablePropStringOptionsItem = | Pipedream.PropOption | Pipedream.PropOptionNested | Pipedream.PropOptionValue - | undefined; + | null; diff --git a/src/api/types/ConfigurablePropTimer.ts b/src/api/types/ConfigurablePropTimer.ts index adeb3cb..92d4cd8 100644 --- a/src/api/types/ConfigurablePropTimer.ts +++ b/src/api/types/ConfigurablePropTimer.ts @@ -4,28 +4,28 @@ import type * as Pipedream from "../index.js"; export interface ConfigurablePropTimer { type: "$.interface.timer"; - static?: Pipedream.ConfigurablePropTimerStatic; - default?: Pipedream.ConfigurablePropTimerDefault; + static?: Pipedream.ConfigurablePropTimerStatic | null; + default?: Pipedream.ConfigurablePropTimerDefault | null; /** Available timer configuration options */ - options?: (Pipedream.ConfigurablePropTimerOption | undefined)[]; + options?: (Pipedream.ConfigurablePropTimerOption | null)[] | null; /** When building `configuredProps`, make sure to use this field as the key when setting the prop value */ name: string; /** Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. */ - label?: string; + label?: string | null; /** A description of the prop, shown to the user when configuring the component. */ - description?: string; + description?: string | null; /** If true, this prop does not need to be specified. */ - optional?: boolean; + optional?: boolean | null; /** If true, this prop will be ignored. */ - disabled?: boolean; + disabled?: boolean | null; /** If true, should not expose this prop to the user */ - hidden?: boolean; + hidden?: boolean | null; /** If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options */ - remoteOptions?: boolean; + remoteOptions?: boolean | null; /** If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options */ - useQuery?: boolean; + useQuery?: boolean | null; /** If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one */ - reloadProps?: boolean; + reloadProps?: boolean | null; /** If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label */ - withLabel?: boolean; + withLabel?: boolean | null; } diff --git a/src/api/types/ConfigurePropOptions.ts b/src/api/types/ConfigurePropOptions.ts index 38d44ad..91777f4 100644 --- a/src/api/types/ConfigurePropOptions.ts +++ b/src/api/types/ConfigurePropOptions.ts @@ -5,4 +5,4 @@ import type * as Pipedream from "../index.js"; /** * Available options (with labels) for the configured prop */ -export type ConfigurePropOptions = Pipedream.ConfigurePropOptionsItem[] | undefined; +export type ConfigurePropOptions = Pipedream.ConfigurePropOptionsItem[] | null; diff --git a/src/api/types/ConfigurePropOpts.ts b/src/api/types/ConfigurePropOpts.ts index aa88f9f..267bdb9 100644 --- a/src/api/types/ConfigurePropOpts.ts +++ b/src/api/types/ConfigurePropOpts.ts @@ -9,7 +9,7 @@ export interface ConfigurePropOpts { /** The component ID */ id: string; /** Optional component version (in SemVer format, for example '1.0.0'), defaults to latest */ - version?: string; + version?: string | null; /** The external user ID */ externalUserId: string; /** The name of the prop to configure */ diff --git a/src/api/types/ConfigurePropResponse.ts b/src/api/types/ConfigurePropResponse.ts index 6812e66..c86a453 100644 --- a/src/api/types/ConfigurePropResponse.ts +++ b/src/api/types/ConfigurePropResponse.ts @@ -6,12 +6,12 @@ import type * as Pipedream from "../index.js"; * Response received after configuring a component's prop */ export interface ConfigurePropResponse { - options?: Pipedream.ConfigurePropOptions | undefined; + options?: Pipedream.ConfigurePropOptions | null; /** Available options for the configured prop */ - stringOptions?: string[]; - observations?: Pipedream.Observation[]; + stringOptions?: string[] | null; + observations?: Pipedream.Observation[] | null; /** New context after configuring the prop */ - context?: Record; + context?: Record | null; /** Any errors that occurred during configuration */ errors?: string[]; } diff --git a/src/api/types/DeployedComponent.ts b/src/api/types/DeployedComponent.ts index c257a87..2384abf 100644 --- a/src/api/types/DeployedComponent.ts +++ b/src/api/types/DeployedComponent.ts @@ -13,7 +13,7 @@ export interface DeployedComponent { /** The ID of the component that was deployed */ componentId: string; /** The component key (name) that was deployed */ - componentKey?: string; + componentKey?: string | null; /** The configurable properties of the component */ configurableProps: Pipedream.ConfigurableProp[]; configuredProps: Pipedream.ConfiguredProps; @@ -28,5 +28,5 @@ export interface DeployedComponent { /** The name slug of the deployed component */ nameSlug: string; /** Callback observations for the deployed component */ - callbackObservations?: unknown; + callbackObservations?: unknown | null; } diff --git a/src/api/types/ProjectInfoResponseApp.ts b/src/api/types/ProjectInfoResponseApp.ts index 0b0c903..e91d19e 100644 --- a/src/api/types/ProjectInfoResponseApp.ts +++ b/src/api/types/ProjectInfoResponseApp.ts @@ -2,7 +2,7 @@ export interface ProjectInfoResponseApp { /** ID of the app. Only applies for OAuth apps. */ - id?: string; + id?: string | null; /** The name slug of the target app */ nameSlug?: string; } diff --git a/src/api/types/PropOption.ts b/src/api/types/PropOption.ts index d3dc209..65ec265 100644 --- a/src/api/types/PropOption.ts +++ b/src/api/types/PropOption.ts @@ -8,5 +8,5 @@ import type * as Pipedream from "../index.js"; export interface PropOption { /** The human-readable label for the option */ label: string; - value?: Pipedream.PropOptionValue; + value: Pipedream.PropOptionValue | null; } diff --git a/src/api/types/ProxyResponseBinary.ts b/src/api/types/ProxyResponseBinary.ts new file mode 100644 index 0000000..e9d59fa --- /dev/null +++ b/src/api/types/ProxyResponseBinary.ts @@ -0,0 +1,6 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * Binary response from the proxied API + */ +export type ProxyResponseBinary = string; diff --git a/src/api/types/ReloadPropsOpts.ts b/src/api/types/ReloadPropsOpts.ts index cf3cb42..2f94121 100644 --- a/src/api/types/ReloadPropsOpts.ts +++ b/src/api/types/ReloadPropsOpts.ts @@ -9,7 +9,7 @@ export interface ReloadPropsOpts { /** The component ID */ id: string; /** Optional component version (in SemVer format, for example '1.0.0'), defaults to latest */ - version?: string; + version?: string | null; /** The external user ID */ externalUserId: string; /** Whether this operation should block until completion */ diff --git a/src/api/types/RunActionOptsStashId.ts b/src/api/types/RunActionOptsStashId.ts index 47b6df4..583aee5 100644 --- a/src/api/types/RunActionOptsStashId.ts +++ b/src/api/types/RunActionOptsStashId.ts @@ -5,4 +5,4 @@ import type * as Pipedream from "../index.js"; /** * The ID of the File Stash to use for syncing the action's /tmp directory, or either `true` or 'NEW' to create a new stash */ -export type RunActionOptsStashId = (Pipedream.StashId | undefined) | undefined | "NEW" | boolean; +export type RunActionOptsStashId = Pipedream.StashId | null | "NEW" | boolean; diff --git a/src/api/types/RunActionResponse.ts b/src/api/types/RunActionResponse.ts index 93fd0d0..e358acc 100644 --- a/src/api/types/RunActionResponse.ts +++ b/src/api/types/RunActionResponse.ts @@ -12,5 +12,5 @@ export interface RunActionResponse { os?: unknown; /** The value returned by the action */ ret?: unknown; - stashId?: Pipedream.StashId | undefined; + stashId?: Pipedream.StashId | null; } diff --git a/src/api/types/StashId.ts b/src/api/types/StashId.ts index b864496..4bf289e 100644 --- a/src/api/types/StashId.ts +++ b/src/api/types/StashId.ts @@ -3,4 +3,4 @@ /** * The ID of the File Stash */ -export type StashId = string | undefined; +export type StashId = string | null; diff --git a/src/api/types/ToolAnnotations.ts b/src/api/types/ToolAnnotations.ts index d71cc0c..3fc890c 100644 --- a/src/api/types/ToolAnnotations.ts +++ b/src/api/types/ToolAnnotations.ts @@ -5,13 +5,13 @@ */ export interface ToolAnnotations { /** If true, the component may perform destructive updates to its environment. If false, the component performs only additive updates. */ - destructiveHint?: boolean; + destructiveHint?: boolean | null; /** If true, calling the component repeatedly with the same arguments will have no additional effect on the its environment. */ - idempotentHint?: boolean; + idempotentHint?: boolean | null; /** If true, this component may interact with an “open world” of external entities. If false, the component's domain of interaction is closed. For example, the world of a web search component is open, whereas that of a memory component is not. */ - openWorldHint?: boolean; + openWorldHint?: boolean | null; /** If true, the component does not modify its environment. */ - readOnlyHint?: boolean; + readOnlyHint?: boolean | null; /** A human-readable title for the component. */ - title?: string; + title?: string | null; } diff --git a/src/api/types/ValidateTokenResponse.ts b/src/api/types/ValidateTokenResponse.ts index 62011a0..27dc3eb 100644 --- a/src/api/types/ValidateTokenResponse.ts +++ b/src/api/types/ValidateTokenResponse.ts @@ -6,23 +6,23 @@ import type * as Pipedream from "../index.js"; * Response received when validating a connect token */ export interface ValidateTokenResponse { - app?: Pipedream.App; + app?: Pipedream.App | null; /** Error message if validation failed */ - error?: string; + error: string | null; /** URI to redirect to on error */ - errorRedirectUri?: string; + errorRedirectUri?: string | null; /** OAuth app ID if applicable */ - oauthAppId?: string; + oauthAppId?: string | null; /** Name of the project app */ - projectAppName?: string; + projectAppName?: string | null; /** Environment of the project */ - projectEnvironment?: string; + projectEnvironment?: string | null; /** ID of the project */ - projectId?: string; + projectId?: string | null; /** Support email for the project */ - projectSupportEmail?: string; + projectSupportEmail?: string | null; /** Whether the token validation was successful */ success: boolean; /** URI to redirect to on success */ - successRedirectUri?: string; + successRedirectUri?: string | null; } diff --git a/src/core/exports.ts b/src/core/exports.ts new file mode 100644 index 0000000..d277449 --- /dev/null +++ b/src/core/exports.ts @@ -0,0 +1,2 @@ +export * from "./logging/exports.js"; +export * from "./pagination/exports.js"; diff --git a/src/core/fetcher/Fetcher.ts b/src/core/fetcher/Fetcher.ts index 202e134..fedbcd8 100644 --- a/src/core/fetcher/Fetcher.ts +++ b/src/core/fetcher/Fetcher.ts @@ -1,4 +1,5 @@ import { toJson } from "../json.js"; +import { createLogger, type LogConfig, type Logger } from "../logging/logger.js"; import type { APIResponse } from "./APIResponse.js"; import { createRequestUrl } from "./createRequestUrl.js"; import type { EndpointMetadata } from "./EndpointMetadata.js"; @@ -7,6 +8,7 @@ import { getErrorResponseBody } from "./getErrorResponseBody.js"; import { getFetchFn } from "./getFetchFn.js"; import { getRequestBody } from "./getRequestBody.js"; import { getResponseBody } from "./getResponseBody.js"; +import { Headers } from "./Headers.js"; import { makeRequest } from "./makeRequest.js"; import { abortRawResponse, toRawResponse, unknownRawResponse } from "./RawResponse.js"; import { requestWithRetries } from "./requestWithRetries.js"; @@ -25,10 +27,12 @@ export declare namespace Fetcher { maxRetries?: number; withCredentials?: boolean; abortSignal?: AbortSignal; - requestType?: "json" | "file" | "bytes"; + requestType?: "json" | "file" | "bytes" | "form" | "other"; responseType?: "json" | "blob" | "sse" | "streaming" | "text" | "arrayBuffer" | "binary-response"; duplex?: "half"; endpointMetadata?: EndpointMetadata; + fetchFn?: typeof fetch; + logging?: LogConfig | Logger; } export type Error = FailedStatusCodeError | NonJsonError | TimeoutError | UnknownError; @@ -55,10 +59,164 @@ export declare namespace Fetcher { } } -async function getHeaders(args: Fetcher.Args): Promise> { - const newHeaders: Record = {}; +const SENSITIVE_HEADERS = new Set([ + "authorization", + "www-authenticate", + "x-api-key", + "api-key", + "apikey", + "x-api-token", + "x-auth-token", + "auth-token", + "cookie", + "set-cookie", + "proxy-authorization", + "proxy-authenticate", + "x-csrf-token", + "x-xsrf-token", + "x-session-token", + "x-access-token", +]); + +function redactHeaders(headers: Headers | Record): Record { + const filtered: Record = {}; + for (const [key, value] of headers instanceof Headers ? headers.entries() : Object.entries(headers)) { + if (SENSITIVE_HEADERS.has(key.toLowerCase())) { + filtered[key] = "[REDACTED]"; + } else { + filtered[key] = value; + } + } + return filtered; +} + +const SENSITIVE_QUERY_PARAMS = new Set([ + "api_key", + "api-key", + "apikey", + "token", + "access_token", + "access-token", + "auth_token", + "auth-token", + "password", + "passwd", + "secret", + "api_secret", + "api-secret", + "apisecret", + "key", + "session", + "session_id", + "session-id", +]); + +function redactQueryParameters(queryParameters?: Record): Record | undefined { + if (queryParameters == null) { + return queryParameters; + } + const redacted: Record = {}; + for (const [key, value] of Object.entries(queryParameters)) { + if (SENSITIVE_QUERY_PARAMS.has(key.toLowerCase())) { + redacted[key] = "[REDACTED]"; + } else { + redacted[key] = value; + } + } + return redacted; +} + +function redactUrl(url: string): string { + const protocolIndex = url.indexOf("://"); + if (protocolIndex === -1) return url; + + const afterProtocol = protocolIndex + 3; + + // Find the first delimiter that marks the end of the authority section + const pathStart = url.indexOf("/", afterProtocol); + let queryStart = url.indexOf("?", afterProtocol); + let fragmentStart = url.indexOf("#", afterProtocol); + + const firstDelimiter = Math.min( + pathStart === -1 ? url.length : pathStart, + queryStart === -1 ? url.length : queryStart, + fragmentStart === -1 ? url.length : fragmentStart, + ); + + // Find the LAST @ before the delimiter (handles multiple @ in credentials) + let atIndex = -1; + for (let i = afterProtocol; i < firstDelimiter; i++) { + if (url[i] === "@") { + atIndex = i; + } + } + + if (atIndex !== -1) { + url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`; + } + + // Recalculate queryStart since url might have changed + queryStart = url.indexOf("?"); + if (queryStart === -1) return url; + + fragmentStart = url.indexOf("#", queryStart); + const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length; + const queryString = url.slice(queryStart + 1, queryEnd); + + if (queryString.length === 0) return url; + + // FAST PATH: Quick check if any sensitive keywords present + // Using indexOf is faster than regex for simple substring matching + const lower = queryString.toLowerCase(); + const hasSensitive = + lower.includes("token") || + lower.includes("key") || + lower.includes("password") || + lower.includes("passwd") || + lower.includes("secret") || + lower.includes("session") || + lower.includes("auth"); + + if (!hasSensitive) { + return url; + } + + // SLOW PATH: Parse and redact + const redactedParams: string[] = []; + const params = queryString.split("&"); + + for (const param of params) { + const equalIndex = param.indexOf("="); + if (equalIndex === -1) { + redactedParams.push(param); + continue; + } + + const key = param.slice(0, equalIndex); + let shouldRedact = SENSITIVE_QUERY_PARAMS.has(key.toLowerCase()); + + if (!shouldRedact && key.includes("%")) { + try { + const decodedKey = decodeURIComponent(key); + shouldRedact = SENSITIVE_QUERY_PARAMS.has(decodedKey.toLowerCase()); + } catch {} + } + + redactedParams.push(shouldRedact ? `${key}=[REDACTED]` : param); + } + + return url.slice(0, queryStart + 1) + redactedParams.join("&") + url.slice(queryEnd); +} + +async function getHeaders(args: Fetcher.Args): Promise { + const newHeaders: Headers = new Headers(); + + newHeaders.set( + "Accept", + args.responseType === "json" ? "application/json" : args.responseType === "text" ? "text/plain" : "*/*", + ); if (args.body !== undefined && args.contentType != null) { - newHeaders["Content-Type"] = args.contentType; + newHeaders.set("Content-Type", args.contentType); } if (args.headers == null) { @@ -68,13 +226,13 @@ async function getHeaders(args: Fetcher.Args): Promise> { for (const [key, value] of Object.entries(args.headers)) { const result = await EndpointSupplier.get(value, { endpointMetadata: args.endpointMetadata ?? {} }); if (typeof result === "string") { - newHeaders[key] = result; + newHeaders.set(key, result); continue; } if (result == null) { continue; } - newHeaders[key] = `${result}`; + newHeaders.set(key, `${result}`); } return newHeaders; } @@ -83,9 +241,22 @@ export async function fetcherImpl(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise= 200 && response.status < 400) { + if (logger.isDebug()) { + const metadata = { + method: args.method, + url: redactUrl(url), + statusCode: response.status, + responseHeaders: redactHeaders(response.headers), + }; + logger.debug("HTTP request succeeded", metadata); + } return { ok: true, body: (await getResponseBody(response, args.responseType)) as R, @@ -112,6 +292,15 @@ export async function fetcherImpl(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise(args: Fetcher.Args): Promise { + if (type === "form") { + return toQueryString(body, { arrayFormat: "repeat", encode: true }); + } if (type.includes("json")) { return toJson(body); } else { diff --git a/src/core/fetcher/makeRequest.ts b/src/core/fetcher/makeRequest.ts index 5edce69..c8d3f2e 100644 --- a/src/core/fetcher/makeRequest.ts +++ b/src/core/fetcher/makeRequest.ts @@ -4,7 +4,7 @@ export const makeRequest = async ( fetchFn: (url: string, init: RequestInit) => Promise, url: string, method: string, - headers: Record, + headers: Headers | Record, requestBody: BodyInit | undefined, timeoutMs?: number, abortSignal?: AbortSignal, @@ -13,7 +13,6 @@ export const makeRequest = async ( ): Promise => { const signals: AbortSignal[] = []; - // Add timeout signal let timeoutAbortId: NodeJS.Timeout | undefined; if (timeoutMs != null) { const { signal, abortId } = getTimeoutSignal(timeoutMs); @@ -21,7 +20,6 @@ export const makeRequest = async ( signals.push(signal); } - // Add arbitrary signal if (abortSignal != null) { signals.push(abortSignal); } diff --git a/src/core/fetcher/requestWithRetries.ts b/src/core/fetcher/requestWithRetries.ts index 3d30bd1..1f68968 100644 --- a/src/core/fetcher/requestWithRetries.ts +++ b/src/core/fetcher/requestWithRetries.ts @@ -4,28 +4,23 @@ const DEFAULT_MAX_RETRIES = 2; const JITTER_FACTOR = 0.2; // 20% random jitter function addPositiveJitter(delay: number): number { - // Generate a random value between 0 and +JITTER_FACTOR const jitterMultiplier = 1 + Math.random() * JITTER_FACTOR; return delay * jitterMultiplier; } function addSymmetricJitter(delay: number): number { - // Generate a random value in a JITTER_FACTOR-sized percentage range around delay const jitterMultiplier = 1 + (Math.random() - 0.5) * JITTER_FACTOR; return delay * jitterMultiplier; } function getRetryDelayFromHeaders(response: Response, retryAttempt: number): number { - // Check for Retry-After header first (RFC 7231), with no jitter const retryAfter = response.headers.get("Retry-After"); if (retryAfter) { - // Parse as number of seconds... const retryAfterSeconds = parseInt(retryAfter, 10); if (!Number.isNaN(retryAfterSeconds) && retryAfterSeconds > 0) { return Math.min(retryAfterSeconds * 1000, MAX_RETRY_DELAY); } - // ...or as an HTTP date; both are valid const retryAfterDate = new Date(retryAfter); if (!Number.isNaN(retryAfterDate.getTime())) { const delay = retryAfterDate.getTime() - Date.now(); @@ -35,12 +30,10 @@ function getRetryDelayFromHeaders(response: Response, retryAttempt: number): num } } - // Then check for industry-standard X-RateLimit-Reset header, with positive jitter const rateLimitReset = response.headers.get("X-RateLimit-Reset"); if (rateLimitReset) { const resetTime = parseInt(rateLimitReset, 10); if (!Number.isNaN(resetTime)) { - // Assume Unix timestamp in epoch seconds const delay = resetTime * 1000 - Date.now(); if (delay > 0) { return addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY)); @@ -48,7 +41,6 @@ function getRetryDelayFromHeaders(response: Response, retryAttempt: number): num } } - // Fall back to exponential backoff, with symmetric jitter return addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * 2 ** retryAttempt, MAX_RETRY_DELAY)); } @@ -60,7 +52,6 @@ export async function requestWithRetries( for (let i = 0; i < maxRetries; ++i) { if ([408, 429].includes(response.status) || response.status >= 500) { - // Get delay with appropriate jitter applied const delay = getRetryDelayFromHeaders(response, i); await new Promise((resolve) => setTimeout(resolve, delay)); diff --git a/src/core/fetcher/signals.ts b/src/core/fetcher/signals.ts index a8d32a2..c9fcaef 100644 --- a/src/core/fetcher/signals.ts +++ b/src/core/fetcher/signals.ts @@ -6,29 +6,17 @@ export function getTimeoutSignal(timeoutMs: number): { signal: AbortSignal; abor return { signal: controller.signal, abortId }; } -/** - * Returns an abort signal that is getting aborted when - * at least one of the specified abort signals is aborted. - * - * Requires at least node.js 18. - */ export function anySignal(...args: AbortSignal[] | [AbortSignal[]]): AbortSignal { - // Allowing signals to be passed either as array - // of signals or as multiple arguments. const signals = (args.length === 1 && Array.isArray(args[0]) ? args[0] : args) as AbortSignal[]; const controller = new AbortController(); for (const signal of signals) { if (signal.aborted) { - // Exiting early if one of the signals - // is already aborted. controller.abort((signal as any)?.reason); break; } - // Listening for signals and removing the listeners - // when at least one symbol is aborted. signal.addEventListener("abort", () => controller.abort((signal as any)?.reason), { signal: controller.signal, }); diff --git a/src/core/headers.ts b/src/core/headers.ts index a723d22..78ed8b5 100644 --- a/src/core/headers.ts +++ b/src/core/headers.ts @@ -6,10 +6,11 @@ export function mergeHeaders( for (const [key, value] of headersArray .filter((headers) => headers != null) .flatMap((headers) => Object.entries(headers))) { + const insensitiveKey = key.toLowerCase(); if (value != null) { - result[key] = value; - } else if (key in result) { - delete result[key]; + result[insensitiveKey] = value; + } else if (insensitiveKey in result) { + delete result[insensitiveKey]; } } @@ -24,8 +25,9 @@ export function mergeOnlyDefinedHeaders( for (const [key, value] of headersArray .filter((headers) => headers != null) .flatMap((headers) => Object.entries(headers))) { + const insensitiveKey = key.toLowerCase(); if (value != null) { - result[key] = value; + result[insensitiveKey] = value; } } diff --git a/src/core/index.ts b/src/core/index.ts index 21e2365..70de501 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,6 +1,7 @@ export * from "./auth/index.js"; export * from "./base64.js"; export * from "./fetcher/index.js"; +export * as logging from "./logging/index.js"; export * from "./pagination/index.js"; export * from "./runtime/index.js"; export * as serialization from "./schemas/index.js"; diff --git a/src/core/logging/exports.ts b/src/core/logging/exports.ts new file mode 100644 index 0000000..88f6c00 --- /dev/null +++ b/src/core/logging/exports.ts @@ -0,0 +1,19 @@ +import * as logger from "./logger.js"; + +export namespace logging { + /** + * Configuration for logger instances. + */ + export type LogConfig = logger.LogConfig; + export type LogLevel = logger.LogLevel; + export const LogLevel: typeof logger.LogLevel = logger.LogLevel; + export type ILogger = logger.ILogger; + /** + * Console logger implementation that outputs to the console. + */ + export type ConsoleLogger = logger.ConsoleLogger; + /** + * Console logger implementation that outputs to the console. + */ + export const ConsoleLogger: typeof logger.ConsoleLogger = logger.ConsoleLogger; +} diff --git a/src/core/logging/index.ts b/src/core/logging/index.ts new file mode 100644 index 0000000..d81cc32 --- /dev/null +++ b/src/core/logging/index.ts @@ -0,0 +1 @@ +export * from "./logger.js"; diff --git a/src/core/logging/logger.ts b/src/core/logging/logger.ts new file mode 100644 index 0000000..a3f3673 --- /dev/null +++ b/src/core/logging/logger.ts @@ -0,0 +1,203 @@ +export const LogLevel = { + Debug: "debug", + Info: "info", + Warn: "warn", + Error: "error", +} as const; +export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel]; +const logLevelMap: Record = { + [LogLevel.Debug]: 1, + [LogLevel.Info]: 2, + [LogLevel.Warn]: 3, + [LogLevel.Error]: 4, +}; + +export interface ILogger { + /** + * Logs a debug message. + * @param message - The message to log + * @param args - Additional arguments to log + */ + debug(message: string, ...args: unknown[]): void; + /** + * Logs an info message. + * @param message - The message to log + * @param args - Additional arguments to log + */ + info(message: string, ...args: unknown[]): void; + /** + * Logs a warning message. + * @param message - The message to log + * @param args - Additional arguments to log + */ + warn(message: string, ...args: unknown[]): void; + /** + * Logs an error message. + * @param message - The message to log + * @param args - Additional arguments to log + */ + error(message: string, ...args: unknown[]): void; +} + +/** + * Configuration for logger initialization. + */ +export interface LogConfig { + /** + * Minimum log level to output. + * @default LogLevel.Info + */ + level?: LogLevel; + /** + * Logger implementation to use. + * @default new ConsoleLogger() + */ + logger?: ILogger; + /** + * Whether logging should be silenced. + * @default true + */ + silent?: boolean; +} + +/** + * Default console-based logger implementation. + */ +export class ConsoleLogger implements ILogger { + debug(message: string, ...args: unknown[]): void { + console.debug(message, ...args); + } + info(message: string, ...args: unknown[]): void { + console.info(message, ...args); + } + warn(message: string, ...args: unknown[]): void { + console.warn(message, ...args); + } + error(message: string, ...args: unknown[]): void { + console.error(message, ...args); + } +} + +/** + * Logger class that provides level-based logging functionality. + */ +export class Logger { + private readonly level: number; + private readonly logger: ILogger; + private readonly silent: boolean; + + /** + * Creates a new logger instance. + * @param config - Logger configuration + */ + constructor(config: Required) { + this.level = logLevelMap[config.level]; + this.logger = config.logger; + this.silent = config.silent; + } + + /** + * Checks if a log level should be output based on configuration. + * @param level - The log level to check + * @returns True if the level should be logged + */ + public shouldLog(level: LogLevel): boolean { + return !this.silent && this.level <= logLevelMap[level]; + } + + /** + * Checks if debug logging is enabled. + * @returns True if debug logs should be output + */ + public isDebug(): boolean { + return this.shouldLog(LogLevel.Debug); + } + + /** + * Logs a debug message if debug logging is enabled. + * @param message - The message to log + * @param args - Additional arguments to log + */ + public debug(message: string, ...args: unknown[]): void { + if (this.isDebug()) { + this.logger.debug(message, ...args); + } + } + + /** + * Checks if info logging is enabled. + * @returns True if info logs should be output + */ + public isInfo(): boolean { + return this.shouldLog(LogLevel.Info); + } + + /** + * Logs an info message if info logging is enabled. + * @param message - The message to log + * @param args - Additional arguments to log + */ + public info(message: string, ...args: unknown[]): void { + if (this.isInfo()) { + this.logger.info(message, ...args); + } + } + + /** + * Checks if warning logging is enabled. + * @returns True if warning logs should be output + */ + public isWarn(): boolean { + return this.shouldLog(LogLevel.Warn); + } + + /** + * Logs a warning message if warning logging is enabled. + * @param message - The message to log + * @param args - Additional arguments to log + */ + public warn(message: string, ...args: unknown[]): void { + if (this.isWarn()) { + this.logger.warn(message, ...args); + } + } + + /** + * Checks if error logging is enabled. + * @returns True if error logs should be output + */ + public isError(): boolean { + return this.shouldLog(LogLevel.Error); + } + + /** + * Logs an error message if error logging is enabled. + * @param message - The message to log + * @param args - Additional arguments to log + */ + public error(message: string, ...args: unknown[]): void { + if (this.isError()) { + this.logger.error(message, ...args); + } + } +} + +export function createLogger(config?: LogConfig | Logger): Logger { + if (config == null) { + return defaultLogger; + } + if (config instanceof Logger) { + return config; + } + config = config ?? {}; + config.level ??= LogLevel.Info; + config.logger ??= new ConsoleLogger(); + config.silent ??= true; + return new Logger(config as Required); +} + +const defaultLogger: Logger = new Logger({ + level: LogLevel.Info, + logger: new ConsoleLogger(), + silent: true, +}); diff --git a/src/core/pagination/Page.ts b/src/core/pagination/Page.ts index 1aa08e5..6621a6f 100644 --- a/src/core/pagination/Page.ts +++ b/src/core/pagination/Page.ts @@ -4,15 +4,16 @@ import type { HttpResponsePromise, RawResponse } from "../fetcher/index.js"; * A page of results from a paginated API. * * @template T The type of the items in the page. + * @template R The type of the API response. */ -export class Page implements AsyncIterable { +export class Page implements AsyncIterable { public data: T[]; public rawResponse: RawResponse; + public response: R; - private response: unknown; - private _hasNextPage: (response: unknown) => boolean; - private getItems: (response: unknown) => T[]; - private loadNextPage: (response: unknown) => HttpResponsePromise; + private _hasNextPage: (response: R) => boolean; + private getItems: (response: R) => T[]; + private loadNextPage: (response: R) => HttpResponsePromise; constructor({ response, @@ -21,11 +22,11 @@ export class Page implements AsyncIterable { getItems, loadPage, }: { - response: unknown; + response: R; rawResponse: RawResponse; - hasNextPage: (response: unknown) => boolean; - getItems: (response: unknown) => T[]; - loadPage: (response: unknown) => HttpResponsePromise; + hasNextPage: (response: R) => boolean; + getItems: (response: R) => T[]; + loadPage: (response: R) => HttpResponsePromise; }) { this.response = response; this.rawResponse = rawResponse; diff --git a/src/core/pagination/Pageable.ts b/src/core/pagination/Pageable.ts deleted file mode 100644 index 5689e1e..0000000 --- a/src/core/pagination/Pageable.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { RawResponse } from "../fetcher/index.js"; -import { Page } from "./Page.js"; - -export declare namespace Pageable { - interface Args { - response: Response; - rawResponse: RawResponse; - hasNextPage: (response: Response) => boolean; - getItems: (response: Response) => Item[]; - loadPage: (response: Response) => Promise; - } -} - -export class Pageable extends Page { - constructor(args: Pageable.Args) { - super(args as any); - } -} diff --git a/src/core/pagination/exports.ts b/src/core/pagination/exports.ts new file mode 100644 index 0000000..d3acc60 --- /dev/null +++ b/src/core/pagination/exports.ts @@ -0,0 +1 @@ +export type { Page } from "./Page.js"; diff --git a/src/core/pagination/index.ts b/src/core/pagination/index.ts index b0cd68f..7781cbd 100644 --- a/src/core/pagination/index.ts +++ b/src/core/pagination/index.ts @@ -1,2 +1 @@ export { Page } from "./Page.js"; -export { Pageable } from "./Pageable.js"; diff --git a/src/core/schemas/Schema.ts b/src/core/schemas/Schema.ts index 179edf6..4cd8b1d 100644 --- a/src/core/schemas/Schema.ts +++ b/src/core/schemas/Schema.ts @@ -24,6 +24,7 @@ export const SchemaType = { NUMBER: "number", STRING: "string", UNKNOWN: "unknown", + NEVER: "never", RECORD: "record", SET: "set", UNION: "union", @@ -32,6 +33,7 @@ export const SchemaType = { OPTIONAL: "optional", OPTIONAL_NULLABLE: "optionalNullable", } as const; + export type SchemaType = (typeof SchemaType)[keyof typeof SchemaType]; export type MaybeValid = Valid | Invalid; diff --git a/src/core/schemas/builders/primitives/index.ts b/src/core/schemas/builders/primitives/index.ts index 462a6d1..7a3ee01 100644 --- a/src/core/schemas/builders/primitives/index.ts +++ b/src/core/schemas/builders/primitives/index.ts @@ -1,5 +1,6 @@ export { any } from "./any.js"; export { boolean } from "./boolean.js"; +export { never } from "./never.js"; export { number } from "./number.js"; export { string } from "./string.js"; export { unknown } from "./unknown.js"; diff --git a/src/core/schemas/builders/primitives/never.ts b/src/core/schemas/builders/primitives/never.ts new file mode 100644 index 0000000..91f85d7 --- /dev/null +++ b/src/core/schemas/builders/primitives/never.ts @@ -0,0 +1,15 @@ +import { type Schema, SchemaType } from "../../Schema.js"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator.js"; + +export const never: () => Schema = createIdentitySchemaCreator( + SchemaType.NEVER, + (_value, { breadcrumbsPrefix = [] } = {}) => ({ + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: "Expected never", + }, + ], + }), +); diff --git a/src/core/url/join.ts b/src/core/url/join.ts index b872a90..7ca7dae 100644 --- a/src/core/url/join.ts +++ b/src/core/url/join.ts @@ -12,7 +12,6 @@ export function join(base: string, ...segments: string[]): string { try { url = new URL(base); } catch { - // Fallback to path joining if URL is malformed return joinPath(base, ...segments); } diff --git a/src/exports.ts b/src/exports.ts new file mode 100644 index 0000000..7b70ee1 --- /dev/null +++ b/src/exports.ts @@ -0,0 +1 @@ +export * from "./core/exports.js"; diff --git a/src/serialization/resources/accounts/client/requests/CreateAccountOpts.ts b/src/serialization/resources/accounts/client/requests/CreateAccountOpts.ts index 1ee7a52..c4fc1f2 100644 --- a/src/serialization/resources/accounts/client/requests/CreateAccountOpts.ts +++ b/src/serialization/resources/accounts/client/requests/CreateAccountOpts.ts @@ -6,7 +6,7 @@ import type * as serializers from "../../../../index.js"; export const CreateAccountOpts: core.serialization.Schema< serializers.CreateAccountOpts.Raw, - Omit + Omit > = core.serialization.object({ appSlug: core.serialization.property("app_slug", core.serialization.string()), cfmapJson: core.serialization.property("cfmap_json", core.serialization.string()), diff --git a/src/serialization/resources/actions/client/requests/RunActionOpts.ts b/src/serialization/resources/actions/client/requests/RunActionOpts.ts index 7c18bfa..36d3195 100644 --- a/src/serialization/resources/actions/client/requests/RunActionOpts.ts +++ b/src/serialization/resources/actions/client/requests/RunActionOpts.ts @@ -6,23 +6,25 @@ import type * as serializers from "../../../../index.js"; import { ConfiguredProps } from "../../../../types/ConfiguredProps.js"; import { RunActionOptsStashId } from "../../../../types/RunActionOptsStashId.js"; -export const RunActionOpts: core.serialization.Schema = - core.serialization.object({ - id: core.serialization.string(), - version: core.serialization.string().optional(), - externalUserId: core.serialization.property("external_user_id", core.serialization.string()), - configuredProps: core.serialization.property("configured_props", ConfiguredProps.optional()), - dynamicPropsId: core.serialization.property("dynamic_props_id", core.serialization.string().optional()), - stashId: core.serialization.property("stash_id", RunActionOptsStashId.optional()), - }); +export const RunActionOpts: core.serialization.Schema< + serializers.RunActionOpts.Raw, + Omit +> = core.serialization.object({ + id: core.serialization.string(), + version: core.serialization.string().optionalNullable(), + externalUserId: core.serialization.property("external_user_id", core.serialization.string()), + configuredProps: core.serialization.property("configured_props", ConfiguredProps.optional()), + dynamicPropsId: core.serialization.property("dynamic_props_id", core.serialization.string().optional()), + stashId: core.serialization.property("stash_id", RunActionOptsStashId.optionalNullable()), +}); export declare namespace RunActionOpts { export interface Raw { id: string; - version?: string | null; + version?: (string | null | undefined) | null; external_user_id: string; configured_props?: ConfiguredProps.Raw | null; dynamic_props_id?: string | null; - stash_id?: RunActionOptsStashId.Raw | null; + stash_id?: (RunActionOptsStashId.Raw | null | undefined) | null; } } diff --git a/src/serialization/resources/apps/types/AppsListRequestSortDirection.ts b/src/serialization/resources/apps/types/ListAppsRequestSortDirection.ts similarity index 60% rename from src/serialization/resources/apps/types/AppsListRequestSortDirection.ts rename to src/serialization/resources/apps/types/ListAppsRequestSortDirection.ts index 864082a..833fa96 100644 --- a/src/serialization/resources/apps/types/AppsListRequestSortDirection.ts +++ b/src/serialization/resources/apps/types/ListAppsRequestSortDirection.ts @@ -4,11 +4,11 @@ import type * as Pipedream from "../../../../api/index.js"; import * as core from "../../../../core/index.js"; import type * as serializers from "../../../index.js"; -export const AppsListRequestSortDirection: core.serialization.Schema< - serializers.AppsListRequestSortDirection.Raw, - Pipedream.AppsListRequestSortDirection +export const ListAppsRequestSortDirection: core.serialization.Schema< + serializers.ListAppsRequestSortDirection.Raw, + Pipedream.ListAppsRequestSortDirection > = core.serialization.enum_(["asc", "desc"]); -export declare namespace AppsListRequestSortDirection { +export declare namespace ListAppsRequestSortDirection { export type Raw = "asc" | "desc"; } diff --git a/src/serialization/resources/apps/types/AppsListRequestSortKey.ts b/src/serialization/resources/apps/types/ListAppsRequestSortKey.ts similarity index 65% rename from src/serialization/resources/apps/types/AppsListRequestSortKey.ts rename to src/serialization/resources/apps/types/ListAppsRequestSortKey.ts index 09b5bf6..9dadb43 100644 --- a/src/serialization/resources/apps/types/AppsListRequestSortKey.ts +++ b/src/serialization/resources/apps/types/ListAppsRequestSortKey.ts @@ -4,11 +4,11 @@ import type * as Pipedream from "../../../../api/index.js"; import * as core from "../../../../core/index.js"; import type * as serializers from "../../../index.js"; -export const AppsListRequestSortKey: core.serialization.Schema< - serializers.AppsListRequestSortKey.Raw, - Pipedream.AppsListRequestSortKey +export const ListAppsRequestSortKey: core.serialization.Schema< + serializers.ListAppsRequestSortKey.Raw, + Pipedream.ListAppsRequestSortKey > = core.serialization.enum_(["name", "name_slug", "featured_weight"]); -export declare namespace AppsListRequestSortKey { +export declare namespace ListAppsRequestSortKey { export type Raw = "name" | "name_slug" | "featured_weight"; } diff --git a/src/serialization/resources/apps/types/index.ts b/src/serialization/resources/apps/types/index.ts index 19ea38a..2982c6d 100644 --- a/src/serialization/resources/apps/types/index.ts +++ b/src/serialization/resources/apps/types/index.ts @@ -1,2 +1,2 @@ -export * from "./AppsListRequestSortDirection.js"; -export * from "./AppsListRequestSortKey.js"; +export * from "./ListAppsRequestSortDirection.js"; +export * from "./ListAppsRequestSortKey.js"; diff --git a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts index 2c8d307..4400d19 100644 --- a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts +++ b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerOpts.ts @@ -7,7 +7,7 @@ import { ConfiguredProps } from "../../../../types/ConfiguredProps.js"; export const UpdateTriggerOpts: core.serialization.Schema< serializers.UpdateTriggerOpts.Raw, - Omit + Omit > = core.serialization.object({ active: core.serialization.boolean().optional(), configuredProps: core.serialization.property("configured_props", ConfiguredProps.optional()), diff --git a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts index 996afbc..c302962 100644 --- a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts +++ b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWebhooksOpts.ts @@ -6,7 +6,7 @@ import type * as serializers from "../../../../index.js"; export const UpdateTriggerWebhooksOpts: core.serialization.Schema< serializers.UpdateTriggerWebhooksOpts.Raw, - Omit + Omit > = core.serialization.object({ webhookUrls: core.serialization.property("webhook_urls", core.serialization.list(core.serialization.string())), }); diff --git a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts index 85fa52b..cd50718 100644 --- a/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts +++ b/src/serialization/resources/deployedTriggers/client/requests/UpdateTriggerWorkflowsOpts.ts @@ -6,7 +6,7 @@ import type * as serializers from "../../../../index.js"; export const UpdateTriggerWorkflowsOpts: core.serialization.Schema< serializers.UpdateTriggerWorkflowsOpts.Raw, - Omit + Omit > = core.serialization.object({ workflowIds: core.serialization.property("workflow_ids", core.serialization.list(core.serialization.string())), }); diff --git a/src/serialization/resources/tokens/client/requests/CreateTokenOpts.ts b/src/serialization/resources/tokens/client/requests/CreateTokenOpts.ts index 0b07d29..e1a3933 100644 --- a/src/serialization/resources/tokens/client/requests/CreateTokenOpts.ts +++ b/src/serialization/resources/tokens/client/requests/CreateTokenOpts.ts @@ -4,17 +4,19 @@ import type * as Pipedream from "../../../../../api/index.js"; import * as core from "../../../../../core/index.js"; import type * as serializers from "../../../../index.js"; -export const CreateTokenOpts: core.serialization.Schema = - core.serialization.object({ - allowedOrigins: core.serialization.property( - "allowed_origins", - core.serialization.list(core.serialization.string()).optional(), - ), - errorRedirectUri: core.serialization.property("error_redirect_uri", core.serialization.string().optional()), - externalUserId: core.serialization.property("external_user_id", core.serialization.string()), - successRedirectUri: core.serialization.property("success_redirect_uri", core.serialization.string().optional()), - webhookUri: core.serialization.property("webhook_uri", core.serialization.string().optional()), - }); +export const CreateTokenOpts: core.serialization.Schema< + serializers.CreateTokenOpts.Raw, + Omit +> = core.serialization.object({ + allowedOrigins: core.serialization.property( + "allowed_origins", + core.serialization.list(core.serialization.string()).optional(), + ), + errorRedirectUri: core.serialization.property("error_redirect_uri", core.serialization.string().optional()), + externalUserId: core.serialization.property("external_user_id", core.serialization.string()), + successRedirectUri: core.serialization.property("success_redirect_uri", core.serialization.string().optional()), + webhookUri: core.serialization.property("webhook_uri", core.serialization.string().optional()), +}); export declare namespace CreateTokenOpts { export interface Raw { diff --git a/src/serialization/resources/triggers/client/requests/DeployTriggerOpts.ts b/src/serialization/resources/triggers/client/requests/DeployTriggerOpts.ts index a97c6dd..0087342 100644 --- a/src/serialization/resources/triggers/client/requests/DeployTriggerOpts.ts +++ b/src/serialization/resources/triggers/client/requests/DeployTriggerOpts.ts @@ -7,10 +7,10 @@ import { ConfiguredProps } from "../../../../types/ConfiguredProps.js"; export const DeployTriggerOpts: core.serialization.Schema< serializers.DeployTriggerOpts.Raw, - Pipedream.DeployTriggerOpts + Omit > = core.serialization.object({ id: core.serialization.string(), - version: core.serialization.string().optional(), + version: core.serialization.string().optionalNullable(), externalUserId: core.serialization.property("external_user_id", core.serialization.string()), configuredProps: core.serialization.property("configured_props", ConfiguredProps.optional()), dynamicPropsId: core.serialization.property("dynamic_props_id", core.serialization.string().optional()), @@ -21,7 +21,7 @@ export const DeployTriggerOpts: core.serialization.Schema< export declare namespace DeployTriggerOpts { export interface Raw { id: string; - version?: string | null; + version?: (string | null | undefined) | null; external_user_id: string; configured_props?: ConfiguredProps.Raw | null; dynamic_props_id?: string | null; diff --git a/src/serialization/types/Account.ts b/src/serialization/types/Account.ts index d4c870c..0f2b5e5 100644 --- a/src/serialization/types/Account.ts +++ b/src/serialization/types/Account.ts @@ -9,34 +9,36 @@ import { App } from "./App.js"; export const Account: core.serialization.ObjectSchema = core.serialization.object({ id: AccountId, - name: core.serialization.string().optional(), + name: core.serialization.string().optionalNullable(), externalId: core.serialization.property("external_id", core.serialization.string().optional()), healthy: core.serialization.boolean().optional(), - dead: core.serialization.boolean().optional(), + dead: core.serialization.boolean().optionalNullable(), app: App.optional(), createdAt: core.serialization.property("created_at", core.serialization.date().optional()), updatedAt: core.serialization.property("updated_at", core.serialization.date().optional()), - credentials: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(), + credentials: core.serialization + .record(core.serialization.string(), core.serialization.unknown()) + .optionalNullable(), expiresAt: core.serialization.property("expires_at", core.serialization.date().optional()), - error: core.serialization.string().optional(), + error: core.serialization.string().optionalNullable(), lastRefreshedAt: core.serialization.property("last_refreshed_at", core.serialization.date().optional()), - nextRefreshAt: core.serialization.property("next_refresh_at", core.serialization.date().optional()), + nextRefreshAt: core.serialization.property("next_refresh_at", core.serialization.date().optionalNullable()), }); export declare namespace Account { export interface Raw { id: AccountId.Raw; - name?: string | null; + name?: (string | null | undefined) | null; external_id?: string | null; healthy?: boolean | null; - dead?: boolean | null; + dead?: (boolean | null | undefined) | null; app?: App.Raw | null; created_at?: string | null; updated_at?: string | null; - credentials?: Record | null; + credentials?: (Record | null | undefined) | null; expires_at?: string | null; - error?: string | null; + error?: (string | null | undefined) | null; last_refreshed_at?: string | null; - next_refresh_at?: string | null; + next_refresh_at?: (string | null | undefined) | null; } } diff --git a/src/serialization/types/App.ts b/src/serialization/types/App.ts index 035f362..98f1ff1 100644 --- a/src/serialization/types/App.ts +++ b/src/serialization/types/App.ts @@ -6,24 +6,24 @@ import type * as serializers from "../index.js"; import { AppAuthType } from "./AppAuthType.js"; export const App: core.serialization.ObjectSchema = core.serialization.object({ - id: core.serialization.string().optional(), + id: core.serialization.string().optionalNullable(), nameSlug: core.serialization.property("name_slug", core.serialization.string()), name: core.serialization.string(), - authType: core.serialization.property("auth_type", AppAuthType.optional()), - description: core.serialization.string().optional(), + authType: core.serialization.property("auth_type", AppAuthType.optionalNullable()), + description: core.serialization.string().optionalNullable(), imgSrc: core.serialization.property("img_src", core.serialization.string()), - customFieldsJson: core.serialization.property("custom_fields_json", core.serialization.string().optional()), + customFieldsJson: core.serialization.property("custom_fields_json", core.serialization.string().nullable()), categories: core.serialization.list(core.serialization.string()), featuredWeight: core.serialization.property("featured_weight", core.serialization.number()), }); export declare namespace App { export interface Raw { - id?: string | null; + id?: (string | null | undefined) | null; name_slug: string; name: string; - auth_type?: AppAuthType.Raw | null; - description?: string | null; + auth_type?: (AppAuthType.Raw | null | undefined) | null; + description?: (string | null | undefined) | null; img_src: string; custom_fields_json?: string | null; categories: string[]; diff --git a/src/serialization/types/AppCategory.ts b/src/serialization/types/AppCategory.ts index 48cb3b3..fd3ad4f 100644 --- a/src/serialization/types/AppCategory.ts +++ b/src/serialization/types/AppCategory.ts @@ -8,13 +8,13 @@ export const AppCategory: core.serialization.ObjectSchema = core.serialization.object({ name: core.serialization.string(), type: ConfigurablePropType, - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurableProp { export interface Raw { name: string; type: ConfigurablePropType.Raw; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAirtableBaseId.ts b/src/serialization/types/ConfigurablePropAirtableBaseId.ts index 61078b0..3555464 100644 --- a/src/serialization/types/ConfigurablePropAirtableBaseId.ts +++ b/src/serialization/types/ConfigurablePropAirtableBaseId.ts @@ -11,15 +11,15 @@ export const ConfigurablePropAirtableBaseId: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("$.airtable.baseId"), appProp: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAirtableBaseId { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropAirtableBaseId { type: "$.airtable.baseId"; appProp: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAirtableFieldId.ts b/src/serialization/types/ConfigurablePropAirtableFieldId.ts index 2d1e337..031b027 100644 --- a/src/serialization/types/ConfigurablePropAirtableFieldId.ts +++ b/src/serialization/types/ConfigurablePropAirtableFieldId.ts @@ -11,15 +11,15 @@ export const ConfigurablePropAirtableFieldId: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("$.airtable.fieldId"), tableIdProp: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAirtableFieldId { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropAirtableFieldId { type: "$.airtable.fieldId"; tableIdProp: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAirtableTableId.ts b/src/serialization/types/ConfigurablePropAirtableTableId.ts index 920b272..b102cd1 100644 --- a/src/serialization/types/ConfigurablePropAirtableTableId.ts +++ b/src/serialization/types/ConfigurablePropAirtableTableId.ts @@ -11,15 +11,15 @@ export const ConfigurablePropAirtableTableId: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("$.airtable.tableId"), baseIdProp: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAirtableTableId { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropAirtableTableId { type: "$.airtable.tableId"; baseIdProp: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAirtableViewId.ts b/src/serialization/types/ConfigurablePropAirtableViewId.ts index 3cb92f0..ac89039 100644 --- a/src/serialization/types/ConfigurablePropAirtableViewId.ts +++ b/src/serialization/types/ConfigurablePropAirtableViewId.ts @@ -11,15 +11,15 @@ export const ConfigurablePropAirtableViewId: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("$.airtable.viewId"), tableIdProp: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAirtableViewId { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropAirtableViewId { type: "$.airtable.viewId"; tableIdProp: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAlert.ts b/src/serialization/types/ConfigurablePropAlert.ts index 98d0e8c..0129686 100644 --- a/src/serialization/types/ConfigurablePropAlert.ts +++ b/src/serialization/types/ConfigurablePropAlert.ts @@ -13,15 +13,15 @@ export const ConfigurablePropAlert: core.serialization.ObjectSchema< alertType: ConfigurablePropAlertType.optional(), content: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAlert { @@ -30,14 +30,14 @@ export declare namespace ConfigurablePropAlert { alertType?: ConfigurablePropAlertType.Raw | null; content: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAny.ts b/src/serialization/types/ConfigurablePropAny.ts index 0fa0d68..536b8cc 100644 --- a/src/serialization/types/ConfigurablePropAny.ts +++ b/src/serialization/types/ConfigurablePropAny.ts @@ -14,15 +14,15 @@ export const ConfigurablePropAny: core.serialization.ObjectSchema< default: ConfiguredPropValueAny.optional(), options: core.serialization.list(ConfigurablePropAnyOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropAny { @@ -31,14 +31,14 @@ export declare namespace ConfigurablePropAny { default?: (ConfiguredPropValueAny.Raw | undefined) | null; options?: ConfigurablePropAnyOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropAnyOptionsItem.ts b/src/serialization/types/ConfigurablePropAnyOptionsItem.ts index b277c27..ce7b8eb 100644 --- a/src/serialization/types/ConfigurablePropAnyOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropAnyOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropAnyOptionsItem: core.serialization.Schema< serializers.ConfigurablePropAnyOptionsItem.Raw, Pipedream.ConfigurablePropAnyOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropAnyOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropApp.ts b/src/serialization/types/ConfigurablePropApp.ts index b765c5a..fcbc305 100644 --- a/src/serialization/types/ConfigurablePropApp.ts +++ b/src/serialization/types/ConfigurablePropApp.ts @@ -11,15 +11,15 @@ export const ConfigurablePropApp: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("app"), app: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropApp { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropApp { type: "app"; app: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropApphook.ts b/src/serialization/types/ConfigurablePropApphook.ts index 29e1c54..cab2ca1 100644 --- a/src/serialization/types/ConfigurablePropApphook.ts +++ b/src/serialization/types/ConfigurablePropApphook.ts @@ -10,37 +10,37 @@ export const ConfigurablePropApphook: core.serialization.ObjectSchema< > = core.serialization.object({ type: core.serialization.stringLiteral("$.interface.apphook"), appProp: core.serialization.string(), - eventNames: core.serialization.list(core.serialization.string()).optional(), - remote: core.serialization.boolean().optional(), - static: core.serialization.list(core.serialization.unknown()).optional(), + eventNames: core.serialization.list(core.serialization.string()).optionalNullable(), + remote: core.serialization.boolean().optionalNullable(), + static: core.serialization.list(core.serialization.unknown()).optionalNullable(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropApphook { export interface Raw { type: "$.interface.apphook"; appProp: string; - eventNames?: string[] | null; - remote?: boolean | null; - static?: unknown[] | null; + eventNames?: (string[] | null | undefined) | null; + remote?: (boolean | null | undefined) | null; + static?: (unknown[] | null | undefined) | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropBoolean.ts b/src/serialization/types/ConfigurablePropBoolean.ts index 8838725..65ea767 100644 --- a/src/serialization/types/ConfigurablePropBoolean.ts +++ b/src/serialization/types/ConfigurablePropBoolean.ts @@ -14,15 +14,15 @@ export const ConfigurablePropBoolean: core.serialization.ObjectSchema< default: ConfiguredPropValueBoolean.optional(), options: core.serialization.list(ConfigurablePropBooleanOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropBoolean { @@ -31,14 +31,14 @@ export declare namespace ConfigurablePropBoolean { default?: ConfiguredPropValueBoolean.Raw | null; options?: ConfigurablePropBooleanOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropBooleanOptionsItem.ts b/src/serialization/types/ConfigurablePropBooleanOptionsItem.ts index 72b8c24..adb9f97 100644 --- a/src/serialization/types/ConfigurablePropBooleanOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropBooleanOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropBooleanOptionsItem: core.serialization.Schema< serializers.ConfigurablePropBooleanOptionsItem.Raw, Pipedream.ConfigurablePropBooleanOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropBooleanOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropDb.ts b/src/serialization/types/ConfigurablePropDb.ts index e9a11e0..eb53067 100644 --- a/src/serialization/types/ConfigurablePropDb.ts +++ b/src/serialization/types/ConfigurablePropDb.ts @@ -10,29 +10,29 @@ export const ConfigurablePropDb: core.serialization.ObjectSchema< > = core.serialization.object({ type: core.serialization.stringLiteral("$.service.db"), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropDb { export interface Raw { type: "$.service.db"; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropDiscord.ts b/src/serialization/types/ConfigurablePropDiscord.ts index b3875f6..853487b 100644 --- a/src/serialization/types/ConfigurablePropDiscord.ts +++ b/src/serialization/types/ConfigurablePropDiscord.ts @@ -10,29 +10,29 @@ export const ConfigurablePropDiscord: core.serialization.ObjectSchema< > = core.serialization.object({ type: core.serialization.stringLiteral("$.discord.channel"), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropDiscord { export interface Raw { type: "$.discord.channel"; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropDiscordChannel.ts b/src/serialization/types/ConfigurablePropDiscordChannel.ts index 05ef503..63aaa69 100644 --- a/src/serialization/types/ConfigurablePropDiscordChannel.ts +++ b/src/serialization/types/ConfigurablePropDiscordChannel.ts @@ -11,15 +11,15 @@ export const ConfigurablePropDiscordChannel: core.serialization.ObjectSchema< type: core.serialization.stringLiteral("$.discord.channel"), appProp: core.serialization.string(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropDiscordChannel { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropDiscordChannel { type: "$.discord.channel"; appProp: string; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropDiscordChannelArray.ts b/src/serialization/types/ConfigurablePropDiscordChannelArray.ts index 4108782..9c8fa85 100644 --- a/src/serialization/types/ConfigurablePropDiscordChannelArray.ts +++ b/src/serialization/types/ConfigurablePropDiscordChannelArray.ts @@ -11,15 +11,15 @@ export const ConfigurablePropDiscordChannelArray: core.serialization.ObjectSchem type: core.serialization.stringLiteral("$.discord.channel[]"), appProp: core.serialization.string().optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropDiscordChannelArray { @@ -27,14 +27,14 @@ export declare namespace ConfigurablePropDiscordChannelArray { type: "$.discord.channel[]"; appProp?: string | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropHttp.ts b/src/serialization/types/ConfigurablePropHttp.ts index 41c2b00..fd427b6 100644 --- a/src/serialization/types/ConfigurablePropHttp.ts +++ b/src/serialization/types/ConfigurablePropHttp.ts @@ -9,32 +9,32 @@ export const ConfigurablePropHttp: core.serialization.ObjectSchema< Pipedream.ConfigurablePropHttp > = core.serialization.object({ type: core.serialization.stringLiteral("$.interface.http"), - customResponse: core.serialization.boolean().optional(), + customResponse: core.serialization.boolean().optionalNullable(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropHttp { export interface Raw { type: "$.interface.http"; - customResponse?: boolean | null; + customResponse?: (boolean | null | undefined) | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropInteger.ts b/src/serialization/types/ConfigurablePropInteger.ts index bd54031..1e947eb 100644 --- a/src/serialization/types/ConfigurablePropInteger.ts +++ b/src/serialization/types/ConfigurablePropInteger.ts @@ -11,38 +11,38 @@ export const ConfigurablePropInteger: core.serialization.ObjectSchema< Pipedream.ConfigurablePropInteger > = core.serialization.object({ type: core.serialization.stringLiteral("integer"), - min: core.serialization.number().optional(), - max: core.serialization.number().optional(), + min: core.serialization.number().optionalNullable(), + max: core.serialization.number().optionalNullable(), default: ConfiguredPropValueInteger.optional(), - options: core.serialization.list(ConfigurablePropIntegerOptionsItem).optional(), + options: core.serialization.list(ConfigurablePropIntegerOptionsItem).optionalNullable(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropInteger { export interface Raw { type: "integer"; - min?: number | null; - max?: number | null; + min?: (number | null | undefined) | null; + max?: (number | null | undefined) | null; default?: ConfiguredPropValueInteger.Raw | null; - options?: ConfigurablePropIntegerOptionsItem.Raw[] | null; + options?: (ConfigurablePropIntegerOptionsItem.Raw[] | null | undefined) | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropIntegerArray.ts b/src/serialization/types/ConfigurablePropIntegerArray.ts index 15c2b46..11fd97a 100644 --- a/src/serialization/types/ConfigurablePropIntegerArray.ts +++ b/src/serialization/types/ConfigurablePropIntegerArray.ts @@ -11,38 +11,38 @@ export const ConfigurablePropIntegerArray: core.serialization.ObjectSchema< Pipedream.ConfigurablePropIntegerArray > = core.serialization.object({ type: core.serialization.stringLiteral("integer[]"), - min: core.serialization.number().optional(), - max: core.serialization.number().optional(), - default: core.serialization.list(ConfiguredPropValueInteger).optional(), - options: core.serialization.list(ConfigurablePropIntegerArrayOptionsItem).optional(), + min: core.serialization.number().optionalNullable(), + max: core.serialization.number().optionalNullable(), + default: core.serialization.list(ConfiguredPropValueInteger).optionalNullable(), + options: core.serialization.list(ConfigurablePropIntegerArrayOptionsItem).optionalNullable(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropIntegerArray { export interface Raw { type: "integer[]"; - min?: number | null; - max?: number | null; - default?: ConfiguredPropValueInteger.Raw[] | null; - options?: ConfigurablePropIntegerArrayOptionsItem.Raw[] | null; + min?: (number | null | undefined) | null; + max?: (number | null | undefined) | null; + default?: (ConfiguredPropValueInteger.Raw[] | null | undefined) | null; + options?: (ConfigurablePropIntegerArrayOptionsItem.Raw[] | null | undefined) | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropIntegerArrayOptionsItem.ts b/src/serialization/types/ConfigurablePropIntegerArrayOptionsItem.ts index d5d79e2..4106a26 100644 --- a/src/serialization/types/ConfigurablePropIntegerArrayOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropIntegerArrayOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropIntegerArrayOptionsItem: core.serialization.Schema< serializers.ConfigurablePropIntegerArrayOptionsItem.Raw, Pipedream.ConfigurablePropIntegerArrayOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropIntegerArrayOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropIntegerOptionsItem.ts b/src/serialization/types/ConfigurablePropIntegerOptionsItem.ts index 54973f2..e48b534 100644 --- a/src/serialization/types/ConfigurablePropIntegerOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropIntegerOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropIntegerOptionsItem: core.serialization.Schema< serializers.ConfigurablePropIntegerOptionsItem.Raw, Pipedream.ConfigurablePropIntegerOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropIntegerOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropObject.ts b/src/serialization/types/ConfigurablePropObject.ts index 1a7480d..4114f8f 100644 --- a/src/serialization/types/ConfigurablePropObject.ts +++ b/src/serialization/types/ConfigurablePropObject.ts @@ -14,15 +14,15 @@ export const ConfigurablePropObject: core.serialization.ObjectSchema< default: ConfiguredPropValueObject.optional(), options: core.serialization.list(ConfigurablePropObjectOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropObject { @@ -31,14 +31,14 @@ export declare namespace ConfigurablePropObject { default?: ConfiguredPropValueObject.Raw | null; options?: ConfigurablePropObjectOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropObjectOptionsItem.ts b/src/serialization/types/ConfigurablePropObjectOptionsItem.ts index cd9490f..2b0e48c 100644 --- a/src/serialization/types/ConfigurablePropObjectOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropObjectOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropObjectOptionsItem: core.serialization.Schema< serializers.ConfigurablePropObjectOptionsItem.Raw, Pipedream.ConfigurablePropObjectOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropObjectOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropSql.ts b/src/serialization/types/ConfigurablePropSql.ts index 227c8f8..d812e22 100644 --- a/src/serialization/types/ConfigurablePropSql.ts +++ b/src/serialization/types/ConfigurablePropSql.ts @@ -12,36 +12,36 @@ export const ConfigurablePropSql: core.serialization.ObjectSchema< Pipedream.ConfigurablePropSql > = core.serialization.object({ type: core.serialization.stringLiteral("sql"), - auth: ConfigurablePropSqlAuth.optional(), + auth: ConfigurablePropSqlAuth.optionalNullable(), default: ConfiguredPropValueSql.optional(), options: core.serialization.list(ConfigurablePropSqlOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropSql { export interface Raw { type: "sql"; - auth?: ConfigurablePropSqlAuth.Raw | null; + auth?: (ConfigurablePropSqlAuth.Raw | null | undefined) | null; default?: ConfiguredPropValueSql.Raw | null; options?: ConfigurablePropSqlOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropSqlOptionsItem.ts b/src/serialization/types/ConfigurablePropSqlOptionsItem.ts index 2d7086e..56e31bc 100644 --- a/src/serialization/types/ConfigurablePropSqlOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropSqlOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropSqlOptionsItem: core.serialization.Schema< serializers.ConfigurablePropSqlOptionsItem.Raw, Pipedream.ConfigurablePropSqlOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropSqlOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropString.ts b/src/serialization/types/ConfigurablePropString.ts index 88036c1..95d2b6d 100644 --- a/src/serialization/types/ConfigurablePropString.ts +++ b/src/serialization/types/ConfigurablePropString.ts @@ -11,36 +11,36 @@ export const ConfigurablePropString: core.serialization.ObjectSchema< Pipedream.ConfigurablePropString > = core.serialization.object({ type: core.serialization.stringLiteral("string"), - secret: core.serialization.boolean().optional(), + secret: core.serialization.boolean().optionalNullable(), default: ConfiguredPropValueString.optional(), options: core.serialization.list(ConfigurablePropStringOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropString { export interface Raw { type: "string"; - secret?: boolean | null; + secret?: (boolean | null | undefined) | null; default?: ConfiguredPropValueString.Raw | null; options?: ConfigurablePropStringOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropStringArray.ts b/src/serialization/types/ConfigurablePropStringArray.ts index a9324f5..63a865e 100644 --- a/src/serialization/types/ConfigurablePropStringArray.ts +++ b/src/serialization/types/ConfigurablePropStringArray.ts @@ -11,36 +11,36 @@ export const ConfigurablePropStringArray: core.serialization.ObjectSchema< Pipedream.ConfigurablePropStringArray > = core.serialization.object({ type: core.serialization.stringLiteral("string[]"), - secret: core.serialization.boolean().optional(), - default: core.serialization.list(ConfiguredPropValueString).optional(), + secret: core.serialization.boolean().optionalNullable(), + default: core.serialization.list(ConfiguredPropValueString).optionalNullable(), options: core.serialization.list(ConfigurablePropStringArrayOptionsItem).optional(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropStringArray { export interface Raw { type: "string[]"; - secret?: boolean | null; - default?: ConfiguredPropValueString.Raw[] | null; + secret?: (boolean | null | undefined) | null; + default?: (ConfiguredPropValueString.Raw[] | null | undefined) | null; options?: ConfigurablePropStringArrayOptionsItem.Raw[] | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurablePropStringArrayOptionsItem.ts b/src/serialization/types/ConfigurablePropStringArrayOptionsItem.ts index 485f1ad..9bd1569 100644 --- a/src/serialization/types/ConfigurablePropStringArrayOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropStringArrayOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropStringArrayOptionsItem: core.serialization.Schema< serializers.ConfigurablePropStringArrayOptionsItem.Raw, Pipedream.ConfigurablePropStringArrayOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropStringArrayOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropStringOptionsItem.ts b/src/serialization/types/ConfigurablePropStringOptionsItem.ts index 33bbe18..f7c974f 100644 --- a/src/serialization/types/ConfigurablePropStringOptionsItem.ts +++ b/src/serialization/types/ConfigurablePropStringOptionsItem.ts @@ -10,7 +10,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const ConfigurablePropStringOptionsItem: core.serialization.Schema< serializers.ConfigurablePropStringOptionsItem.Raw, Pipedream.ConfigurablePropStringOptionsItem -> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.optional()]); +> = core.serialization.undiscriminatedUnion([PropOption, PropOptionNested, PropOptionValue.nullable()]); export declare namespace ConfigurablePropStringOptionsItem { export type Raw = PropOption.Raw | PropOptionNested.Raw | (PropOptionValue.Raw | null | undefined); diff --git a/src/serialization/types/ConfigurablePropTimer.ts b/src/serialization/types/ConfigurablePropTimer.ts index 2ccc73e..a249eba 100644 --- a/src/serialization/types/ConfigurablePropTimer.ts +++ b/src/serialization/types/ConfigurablePropTimer.ts @@ -12,36 +12,36 @@ export const ConfigurablePropTimer: core.serialization.ObjectSchema< Pipedream.ConfigurablePropTimer > = core.serialization.object({ type: core.serialization.stringLiteral("$.interface.timer"), - static: ConfigurablePropTimerStatic.optional(), - default: ConfigurablePropTimerDefault.optional(), - options: core.serialization.list(ConfigurablePropTimerOption.optional()).optional(), + static: ConfigurablePropTimerStatic.optionalNullable(), + default: ConfigurablePropTimerDefault.optionalNullable(), + options: core.serialization.list(ConfigurablePropTimerOption.nullable()).optionalNullable(), name: core.serialization.string(), - label: core.serialization.string().optional(), - description: core.serialization.string().optional(), - optional: core.serialization.boolean().optional(), - disabled: core.serialization.boolean().optional(), - hidden: core.serialization.boolean().optional(), - remoteOptions: core.serialization.boolean().optional(), - useQuery: core.serialization.boolean().optional(), - reloadProps: core.serialization.boolean().optional(), - withLabel: core.serialization.boolean().optional(), + label: core.serialization.string().optionalNullable(), + description: core.serialization.string().optionalNullable(), + optional: core.serialization.boolean().optionalNullable(), + disabled: core.serialization.boolean().optionalNullable(), + hidden: core.serialization.boolean().optionalNullable(), + remoteOptions: core.serialization.boolean().optionalNullable(), + useQuery: core.serialization.boolean().optionalNullable(), + reloadProps: core.serialization.boolean().optionalNullable(), + withLabel: core.serialization.boolean().optionalNullable(), }); export declare namespace ConfigurablePropTimer { export interface Raw { type: "$.interface.timer"; - static?: ConfigurablePropTimerStatic.Raw | null; - default?: ConfigurablePropTimerDefault.Raw | null; - options?: (ConfigurablePropTimerOption.Raw | null | undefined)[] | null; + static?: (ConfigurablePropTimerStatic.Raw | null | undefined) | null; + default?: (ConfigurablePropTimerDefault.Raw | null | undefined) | null; + options?: ((ConfigurablePropTimerOption.Raw | null | undefined)[] | null | undefined) | null; name: string; - label?: string | null; - description?: string | null; - optional?: boolean | null; - disabled?: boolean | null; - hidden?: boolean | null; - remoteOptions?: boolean | null; - useQuery?: boolean | null; - reloadProps?: boolean | null; - withLabel?: boolean | null; + label?: (string | null | undefined) | null; + description?: (string | null | undefined) | null; + optional?: (boolean | null | undefined) | null; + disabled?: (boolean | null | undefined) | null; + hidden?: (boolean | null | undefined) | null; + remoteOptions?: (boolean | null | undefined) | null; + useQuery?: (boolean | null | undefined) | null; + reloadProps?: (boolean | null | undefined) | null; + withLabel?: (boolean | null | undefined) | null; } } diff --git a/src/serialization/types/ConfigurePropOptions.ts b/src/serialization/types/ConfigurePropOptions.ts index 24e0e28..9ae1850 100644 --- a/src/serialization/types/ConfigurePropOptions.ts +++ b/src/serialization/types/ConfigurePropOptions.ts @@ -8,7 +8,7 @@ import { ConfigurePropOptionsItem } from "./ConfigurePropOptionsItem.js"; export const ConfigurePropOptions: core.serialization.Schema< serializers.ConfigurePropOptions.Raw, Pipedream.ConfigurePropOptions -> = core.serialization.list(ConfigurePropOptionsItem).optional(); +> = core.serialization.list(ConfigurePropOptionsItem).nullable(); export declare namespace ConfigurePropOptions { export type Raw = ConfigurePropOptionsItem.Raw[] | null | undefined; diff --git a/src/serialization/types/ConfigurePropOpts.ts b/src/serialization/types/ConfigurePropOpts.ts index 911d02d..ec3ef7d 100644 --- a/src/serialization/types/ConfigurePropOpts.ts +++ b/src/serialization/types/ConfigurePropOpts.ts @@ -10,7 +10,7 @@ export const ConfigurePropOpts: core.serialization.ObjectSchema< Pipedream.ConfigurePropOpts > = core.serialization.object({ id: core.serialization.string(), - version: core.serialization.string().optional(), + version: core.serialization.string().optionalNullable(), externalUserId: core.serialization.property("external_user_id", core.serialization.string()), propName: core.serialization.property("prop_name", core.serialization.string()), blocking: core.serialization.boolean().optional(), @@ -27,7 +27,7 @@ export const ConfigurePropOpts: core.serialization.ObjectSchema< export declare namespace ConfigurePropOpts { export interface Raw { id: string; - version?: string | null; + version?: (string | null | undefined) | null; external_user_id: string; prop_name: string; blocking?: boolean | null; diff --git a/src/serialization/types/ConfigurePropResponse.ts b/src/serialization/types/ConfigurePropResponse.ts index a128d93..4aba7a8 100644 --- a/src/serialization/types/ConfigurePropResponse.ts +++ b/src/serialization/types/ConfigurePropResponse.ts @@ -10,22 +10,22 @@ export const ConfigurePropResponse: core.serialization.ObjectSchema< serializers.ConfigurePropResponse.Raw, Pipedream.ConfigurePropResponse > = core.serialization.object({ - options: ConfigurePropOptions.optional(), + options: ConfigurePropOptions.optionalNullable(), stringOptions: core.serialization.property( "string_options", - core.serialization.list(core.serialization.string()).optional(), + core.serialization.list(core.serialization.string()).optionalNullable(), ), - observations: core.serialization.list(Observation).optional(), - context: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optional(), + observations: core.serialization.list(Observation).optionalNullable(), + context: core.serialization.record(core.serialization.string(), core.serialization.unknown()).optionalNullable(), errors: core.serialization.list(core.serialization.string()).optional(), }); export declare namespace ConfigurePropResponse { export interface Raw { - options?: (ConfigurePropOptions.Raw | undefined) | null; - string_options?: string[] | null; - observations?: Observation.Raw[] | null; - context?: Record | null; + options?: ((ConfigurePropOptions.Raw | undefined) | null | undefined) | null; + string_options?: (string[] | null | undefined) | null; + observations?: (Observation.Raw[] | null | undefined) | null; + context?: (Record | null | undefined) | null; errors?: string[] | null; } } diff --git a/src/serialization/types/DeployedComponent.ts b/src/serialization/types/DeployedComponent.ts index b15e59a..02f2eab 100644 --- a/src/serialization/types/DeployedComponent.ts +++ b/src/serialization/types/DeployedComponent.ts @@ -13,7 +13,7 @@ export const DeployedComponent: core.serialization.ObjectSchema< id: core.serialization.string(), ownerId: core.serialization.property("owner_id", core.serialization.string()), componentId: core.serialization.property("component_id", core.serialization.string()), - componentKey: core.serialization.property("component_key", core.serialization.string().optional()), + componentKey: core.serialization.property("component_key", core.serialization.string().optionalNullable()), configurableProps: core.serialization.property("configurable_props", core.serialization.list(ConfigurableProp)), configuredProps: core.serialization.property("configured_props", ConfiguredProps), active: core.serialization.boolean(), @@ -21,7 +21,10 @@ export const DeployedComponent: core.serialization.ObjectSchema< updatedAt: core.serialization.property("updated_at", core.serialization.number()), name: core.serialization.string(), nameSlug: core.serialization.property("name_slug", core.serialization.string()), - callbackObservations: core.serialization.property("callback_observations", core.serialization.unknown().optional()), + callbackObservations: core.serialization.property( + "callback_observations", + core.serialization.unknown().optionalNullable(), + ), }); export declare namespace DeployedComponent { @@ -29,7 +32,7 @@ export declare namespace DeployedComponent { id: string; owner_id: string; component_id: string; - component_key?: string | null; + component_key?: (string | null | undefined) | null; configurable_props: ConfigurableProp.Raw[]; configured_props: ConfiguredProps.Raw; active: boolean; @@ -37,6 +40,6 @@ export declare namespace DeployedComponent { updated_at: number; name: string; name_slug: string; - callback_observations?: unknown | null; + callback_observations?: (unknown | null | undefined) | null; } } diff --git a/src/serialization/types/ProjectInfoResponseApp.ts b/src/serialization/types/ProjectInfoResponseApp.ts index eea9ba2..a60969d 100644 --- a/src/serialization/types/ProjectInfoResponseApp.ts +++ b/src/serialization/types/ProjectInfoResponseApp.ts @@ -8,13 +8,13 @@ export const ProjectInfoResponseApp: core.serialization.ObjectSchema< serializers.ProjectInfoResponseApp.Raw, Pipedream.ProjectInfoResponseApp > = core.serialization.object({ - id: core.serialization.string().optional(), + id: core.serialization.string().optionalNullable(), nameSlug: core.serialization.property("name_slug", core.serialization.string().optional()), }); export declare namespace ProjectInfoResponseApp { export interface Raw { - id?: string | null; + id?: (string | null | undefined) | null; name_slug?: string | null; } } diff --git a/src/serialization/types/PropOption.ts b/src/serialization/types/PropOption.ts index fcde481..1c2c043 100644 --- a/src/serialization/types/PropOption.ts +++ b/src/serialization/types/PropOption.ts @@ -8,7 +8,7 @@ import { PropOptionValue } from "./PropOptionValue.js"; export const PropOption: core.serialization.ObjectSchema = core.serialization.object({ label: core.serialization.string(), - value: PropOptionValue.optional(), + value: PropOptionValue.nullable(), }); export declare namespace PropOption { diff --git a/src/serialization/types/ProxyResponseBinary.ts b/src/serialization/types/ProxyResponseBinary.ts new file mode 100644 index 0000000..8a05a96 --- /dev/null +++ b/src/serialization/types/ProxyResponseBinary.ts @@ -0,0 +1,14 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Pipedream from "../../api/index.js"; +import * as core from "../../core/index.js"; +import type * as serializers from "../index.js"; + +export const ProxyResponseBinary: core.serialization.Schema< + serializers.ProxyResponseBinary.Raw, + Pipedream.ProxyResponseBinary +> = core.serialization.string(); + +export declare namespace ProxyResponseBinary { + export type Raw = string; +} diff --git a/src/serialization/types/ReloadPropsOpts.ts b/src/serialization/types/ReloadPropsOpts.ts index 5339cef..5bd484f 100644 --- a/src/serialization/types/ReloadPropsOpts.ts +++ b/src/serialization/types/ReloadPropsOpts.ts @@ -10,7 +10,7 @@ export const ReloadPropsOpts: core.serialization.ObjectSchema< Pipedream.ReloadPropsOpts > = core.serialization.object({ id: core.serialization.string(), - version: core.serialization.string().optional(), + version: core.serialization.string().optionalNullable(), externalUserId: core.serialization.property("external_user_id", core.serialization.string()), blocking: core.serialization.boolean().optional(), configuredProps: core.serialization.property("configured_props", ConfiguredProps.optional()), @@ -20,7 +20,7 @@ export const ReloadPropsOpts: core.serialization.ObjectSchema< export declare namespace ReloadPropsOpts { export interface Raw { id: string; - version?: string | null; + version?: (string | null | undefined) | null; external_user_id: string; blocking?: boolean | null; configured_props?: ConfiguredProps.Raw | null; diff --git a/src/serialization/types/RunActionOptsStashId.ts b/src/serialization/types/RunActionOptsStashId.ts index 400d412..b23e413 100644 --- a/src/serialization/types/RunActionOptsStashId.ts +++ b/src/serialization/types/RunActionOptsStashId.ts @@ -9,7 +9,7 @@ export const RunActionOptsStashId: core.serialization.Schema< serializers.RunActionOptsStashId.Raw, Pipedream.RunActionOptsStashId > = core.serialization.undiscriminatedUnion([ - StashId.optional(), + StashId.nullable(), core.serialization.stringLiteral("NEW"), core.serialization.boolean(), ]); diff --git a/src/serialization/types/RunActionResponse.ts b/src/serialization/types/RunActionResponse.ts index bd2a81e..bf8d3cd 100644 --- a/src/serialization/types/RunActionResponse.ts +++ b/src/serialization/types/RunActionResponse.ts @@ -12,7 +12,7 @@ export const RunActionResponse: core.serialization.ObjectSchema< exports: core.serialization.unknown().optional(), os: core.serialization.unknown().optional(), ret: core.serialization.unknown().optional(), - stashId: core.serialization.property("stash_id", StashId.optional()), + stashId: core.serialization.property("stash_id", StashId.optionalNullable()), }); export declare namespace RunActionResponse { @@ -20,6 +20,6 @@ export declare namespace RunActionResponse { exports?: unknown | null; os?: unknown | null; ret?: unknown | null; - stash_id?: (StashId.Raw | undefined) | null; + stash_id?: ((StashId.Raw | undefined) | null | undefined) | null; } } diff --git a/src/serialization/types/StashId.ts b/src/serialization/types/StashId.ts index 5e2d63a..b0107ad 100644 --- a/src/serialization/types/StashId.ts +++ b/src/serialization/types/StashId.ts @@ -6,7 +6,7 @@ import type * as serializers from "../index.js"; export const StashId: core.serialization.Schema = core.serialization .string() - .optional(); + .nullable(); export declare namespace StashId { export type Raw = string | null | undefined; diff --git a/src/serialization/types/ToolAnnotations.ts b/src/serialization/types/ToolAnnotations.ts index 62a67d9..69af6de 100644 --- a/src/serialization/types/ToolAnnotations.ts +++ b/src/serialization/types/ToolAnnotations.ts @@ -8,19 +8,19 @@ export const ToolAnnotations: core.serialization.ObjectSchema< serializers.ToolAnnotations.Raw, Pipedream.ToolAnnotations > = core.serialization.object({ - destructiveHint: core.serialization.boolean().optional(), - idempotentHint: core.serialization.boolean().optional(), - openWorldHint: core.serialization.boolean().optional(), - readOnlyHint: core.serialization.boolean().optional(), - title: core.serialization.string().optional(), + destructiveHint: core.serialization.boolean().optionalNullable(), + idempotentHint: core.serialization.boolean().optionalNullable(), + openWorldHint: core.serialization.boolean().optionalNullable(), + readOnlyHint: core.serialization.boolean().optionalNullable(), + title: core.serialization.string().optionalNullable(), }); export declare namespace ToolAnnotations { export interface Raw { - destructiveHint?: boolean | null; - idempotentHint?: boolean | null; - openWorldHint?: boolean | null; - readOnlyHint?: boolean | null; - title?: string | null; + destructiveHint?: (boolean | null | undefined) | null; + idempotentHint?: (boolean | null | undefined) | null; + openWorldHint?: (boolean | null | undefined) | null; + readOnlyHint?: (boolean | null | undefined) | null; + title?: (string | null | undefined) | null; } } diff --git a/src/serialization/types/ValidateTokenResponse.ts b/src/serialization/types/ValidateTokenResponse.ts index a4a4b2f..a021dc3 100644 --- a/src/serialization/types/ValidateTokenResponse.ts +++ b/src/serialization/types/ValidateTokenResponse.ts @@ -9,29 +9,38 @@ export const ValidateTokenResponse: core.serialization.ObjectSchema< serializers.ValidateTokenResponse.Raw, Pipedream.ValidateTokenResponse > = core.serialization.object({ - app: App.optional(), - error: core.serialization.string().optional(), - errorRedirectUri: core.serialization.property("error_redirect_uri", core.serialization.string().optional()), - oauthAppId: core.serialization.property("oauth_app_id", core.serialization.string().optional()), - projectAppName: core.serialization.property("project_app_name", core.serialization.string().optional()), - projectEnvironment: core.serialization.property("project_environment", core.serialization.string().optional()), - projectId: core.serialization.property("project_id", core.serialization.string().optional()), - projectSupportEmail: core.serialization.property("project_support_email", core.serialization.string().optional()), + app: App.optionalNullable(), + error: core.serialization.string().nullable(), + errorRedirectUri: core.serialization.property("error_redirect_uri", core.serialization.string().optionalNullable()), + oauthAppId: core.serialization.property("oauth_app_id", core.serialization.string().optionalNullable()), + projectAppName: core.serialization.property("project_app_name", core.serialization.string().optionalNullable()), + projectEnvironment: core.serialization.property( + "project_environment", + core.serialization.string().optionalNullable(), + ), + projectId: core.serialization.property("project_id", core.serialization.string().optionalNullable()), + projectSupportEmail: core.serialization.property( + "project_support_email", + core.serialization.string().optionalNullable(), + ), success: core.serialization.boolean(), - successRedirectUri: core.serialization.property("success_redirect_uri", core.serialization.string().optional()), + successRedirectUri: core.serialization.property( + "success_redirect_uri", + core.serialization.string().optionalNullable(), + ), }); export declare namespace ValidateTokenResponse { export interface Raw { - app?: App.Raw | null; + app?: (App.Raw | null | undefined) | null; error?: string | null; - error_redirect_uri?: string | null; - oauth_app_id?: string | null; - project_app_name?: string | null; - project_environment?: string | null; - project_id?: string | null; - project_support_email?: string | null; + error_redirect_uri?: (string | null | undefined) | null; + oauth_app_id?: (string | null | undefined) | null; + project_app_name?: (string | null | undefined) | null; + project_environment?: (string | null | undefined) | null; + project_id?: (string | null | undefined) | null; + project_support_email?: (string | null | undefined) | null; success: boolean; - success_redirect_uri?: string | null; + success_redirect_uri?: (string | null | undefined) | null; } } diff --git a/src/serialization/types/index.ts b/src/serialization/types/index.ts index b0d7929..4bfba31 100644 --- a/src/serialization/types/index.ts +++ b/src/serialization/types/index.ts @@ -94,6 +94,7 @@ export * from "./PropOption.js"; export * from "./PropOptionNested.js"; export * from "./PropOptionValue.js"; export * from "./ProxyResponse.js"; +export * from "./ProxyResponseBinary.js"; export * from "./ReloadPropsOpts.js"; export * from "./ReloadPropsResponse.js"; export * from "./RunActionOptsStashId.js"; diff --git a/src/version.ts b/src/version.ts index 13d9985..7fc9811 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const SDK_VERSION = "2.2.0"; +export const SDK_VERSION = "2.2.1"; diff --git a/tests/mock-server/mockEndpointBuilder.ts b/tests/mock-server/mockEndpointBuilder.ts index 18557ec..1b0e510 100644 --- a/tests/mock-server/mockEndpointBuilder.ts +++ b/tests/mock-server/mockEndpointBuilder.ts @@ -2,6 +2,7 @@ import { type DefaultBodyType, type HttpHandler, HttpResponse, type HttpResponse import { url } from "../../src/core"; import { toJson } from "../../src/core/json"; +import { withFormUrlEncoded } from "./withFormUrlEncoded"; import { withHeaders } from "./withHeaders"; import { withJson } from "./withJson"; @@ -26,6 +27,7 @@ interface RequestHeadersStage extends RequestBodyStage, ResponseStage { interface RequestBodyStage extends ResponseStage { jsonBody(body: unknown): ResponseStage; + formUrlEncodedBody(body: unknown): ResponseStage; } interface ResponseStage { @@ -135,6 +137,16 @@ class RequestBuilder implements MethodStage, RequestHeadersStage, RequestBodySta return this; } + formUrlEncodedBody(body: unknown): ResponseStage { + if (body === undefined) { + throw new Error( + "Undefined is not valid for form-urlencoded. Do not call formUrlEncodedBody if you want an empty body.", + ); + } + this.predicates.push((resolver) => withFormUrlEncoded(body, resolver)); + return this; + } + respondWith(): ResponseStatusStage { return new ResponseBuilder(this.method, this.buildUrl(), this.predicates, this.handlerOptions); } diff --git a/tests/mock-server/withFormUrlEncoded.ts b/tests/mock-server/withFormUrlEncoded.ts new file mode 100644 index 0000000..e9e6ff2 --- /dev/null +++ b/tests/mock-server/withFormUrlEncoded.ts @@ -0,0 +1,80 @@ +import { type HttpResponseResolver, passthrough } from "msw"; + +import { toJson } from "../../src/core/json"; + +/** + * Creates a request matcher that validates if the request form-urlencoded body exactly matches the expected object + * @param expectedBody - The exact body object to match against + * @param resolver - Response resolver to execute if body matches + */ +export function withFormUrlEncoded(expectedBody: unknown, resolver: HttpResponseResolver): HttpResponseResolver { + return async (args) => { + const { request } = args; + + let clonedRequest: Request; + let bodyText: string | undefined; + let actualBody: Record; + try { + clonedRequest = request.clone(); + bodyText = await clonedRequest.text(); + if (bodyText === "") { + console.error("Request body is empty, expected a form-urlencoded body."); + return passthrough(); + } + const params = new URLSearchParams(bodyText); + actualBody = {}; + for (const [key, value] of params.entries()) { + actualBody[key] = value; + } + } catch (error) { + console.error(`Error processing form-urlencoded request body:\n\tError: ${error}\n\tBody: ${bodyText}`); + return passthrough(); + } + + const mismatches = findMismatches(actualBody, expectedBody); + if (Object.keys(mismatches).length > 0) { + console.error("Form-urlencoded body mismatch:", toJson(mismatches, undefined, 2)); + return passthrough(); + } + + return resolver(args); + }; +} + +function findMismatches(actual: any, expected: any): Record { + const mismatches: Record = {}; + + if (typeof actual !== typeof expected) { + return { value: { actual, expected } }; + } + + if (typeof actual !== "object" || actual === null || expected === null) { + if (actual !== expected) { + return { value: { actual, expected } }; + } + return {}; + } + + const actualKeys = Object.keys(actual); + const expectedKeys = Object.keys(expected); + + const allKeys = new Set([...actualKeys, ...expectedKeys]); + + for (const key of allKeys) { + if (!expectedKeys.includes(key)) { + if (actual[key] === undefined) { + continue; + } + mismatches[key] = { actual: actual[key], expected: undefined }; + } else if (!actualKeys.includes(key)) { + if (expected[key] === undefined) { + continue; + } + mismatches[key] = { actual: undefined, expected: expected[key] }; + } else if (actual[key] !== expected[key]) { + mismatches[key] = { actual: actual[key], expected: expected[key] }; + } + } + + return mismatches; +} diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 0000000..a5651f8 --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,80 @@ +import { expect } from "vitest"; + +interface CustomMatchers { + toContainHeaders(expectedHeaders: Record): R; +} + +declare module "vitest" { + interface Assertion extends CustomMatchers {} + interface AsymmetricMatchersContaining extends CustomMatchers {} +} + +expect.extend({ + toContainHeaders(actual: unknown, expectedHeaders: Record) { + const isHeaders = actual instanceof Headers; + const isPlainObject = typeof actual === "object" && actual !== null && !Array.isArray(actual); + + if (!isHeaders && !isPlainObject) { + throw new TypeError("Received value must be an instance of Headers or a plain object!"); + } + + if (typeof expectedHeaders !== "object" || expectedHeaders === null || Array.isArray(expectedHeaders)) { + throw new TypeError("Expected headers must be a plain object!"); + } + + const missingHeaders: string[] = []; + const mismatchedHeaders: Array<{ key: string; expected: string; actual: string | null }> = []; + + for (const [key, value] of Object.entries(expectedHeaders)) { + let actualValue: string | null = null; + + if (isHeaders) { + // Headers.get() is already case-insensitive + actualValue = (actual as Headers).get(key); + } else { + // For plain objects, do case-insensitive lookup + const actualObj = actual as Record; + const lowerKey = key.toLowerCase(); + const foundKey = Object.keys(actualObj).find((k) => k.toLowerCase() === lowerKey); + actualValue = foundKey ? actualObj[foundKey] : null; + } + + if (actualValue === null || actualValue === undefined) { + missingHeaders.push(key); + } else if (actualValue !== value) { + mismatchedHeaders.push({ key, expected: value, actual: actualValue }); + } + } + + const pass = missingHeaders.length === 0 && mismatchedHeaders.length === 0; + + const actualType = isHeaders ? "Headers" : "object"; + + if (pass) { + return { + message: () => `expected ${actualType} not to contain ${this.utils.printExpected(expectedHeaders)}`, + pass: true, + }; + } else { + const messages: string[] = []; + + if (missingHeaders.length > 0) { + messages.push(`Missing headers: ${this.utils.printExpected(missingHeaders.join(", "))}`); + } + + if (mismatchedHeaders.length > 0) { + const mismatches = mismatchedHeaders.map( + ({ key, expected, actual }) => + `${key}: expected ${this.utils.printExpected(expected)} but got ${this.utils.printReceived(actual)}`, + ); + messages.push(mismatches.join("\n")); + } + + return { + message: () => + `expected ${actualType} to contain ${this.utils.printExpected(expectedHeaders)}\n\n${messages.join("\n")}`, + pass: false, + }; + } + }, +}); diff --git a/tests/unit/auth/BasicAuth.test.ts b/tests/unit/auth/BasicAuth.test.ts index 90bbc7e..9b51233 100644 --- a/tests/unit/auth/BasicAuth.test.ts +++ b/tests/unit/auth/BasicAuth.test.ts @@ -1,58 +1,92 @@ import { BasicAuth } from "../../../src/core/auth/BasicAuth"; describe("BasicAuth", () => { - describe("toAuthorizationHeader", () => { - it("correctly converts to header", () => { - expect( - BasicAuth.toAuthorizationHeader({ - username: "username", - password: "password", - }), - ).toBe("Basic dXNlcm5hbWU6cGFzc3dvcmQ="); - }); - }); - describe("fromAuthorizationHeader", () => { - it("correctly parses header", () => { - expect(BasicAuth.fromAuthorizationHeader("Basic dXNlcm5hbWU6cGFzc3dvcmQ=")).toEqual({ - username: "username", - password: "password", - }); - }); + interface ToHeaderTestCase { + description: string; + input: { username: string; password: string }; + expected: string; + } - it("handles password with colons", () => { - expect(BasicAuth.fromAuthorizationHeader("Basic dXNlcjpwYXNzOndvcmQ=")).toEqual({ - username: "user", - password: "pass:word", - }); - }); + interface FromHeaderTestCase { + description: string; + input: string; + expected: { username: string; password: string }; + } - it("handles empty username and password (just colon)", () => { - expect(BasicAuth.fromAuthorizationHeader("Basic Og==")).toEqual({ - username: "", - password: "", - }); - }); + interface ErrorTestCase { + description: string; + input: string; + expectedError: string; + } + + describe("toAuthorizationHeader", () => { + const toHeaderTests: ToHeaderTestCase[] = [ + { + description: "correctly converts to header", + input: { username: "username", password: "password" }, + expected: "Basic dXNlcm5hbWU6cGFzc3dvcmQ=", + }, + ]; - it("handles empty username", () => { - expect(BasicAuth.fromAuthorizationHeader("Basic OnBhc3N3b3Jk")).toEqual({ - username: "", - password: "password", + toHeaderTests.forEach(({ description, input, expected }) => { + it(description, () => { + expect(BasicAuth.toAuthorizationHeader(input)).toBe(expected); }); }); + }); - it("handles empty password", () => { - expect(BasicAuth.fromAuthorizationHeader("Basic dXNlcm5hbWU6")).toEqual({ - username: "username", - password: "", + describe("fromAuthorizationHeader", () => { + const fromHeaderTests: FromHeaderTestCase[] = [ + { + description: "correctly parses header", + input: "Basic dXNlcm5hbWU6cGFzc3dvcmQ=", + expected: { username: "username", password: "password" }, + }, + { + description: "handles password with colons", + input: "Basic dXNlcjpwYXNzOndvcmQ=", + expected: { username: "user", password: "pass:word" }, + }, + { + description: "handles empty username and password (just colon)", + input: "Basic Og==", + expected: { username: "", password: "" }, + }, + { + description: "handles empty username", + input: "Basic OnBhc3N3b3Jk", + expected: { username: "", password: "password" }, + }, + { + description: "handles empty password", + input: "Basic dXNlcm5hbWU6", + expected: { username: "username", password: "" }, + }, + ]; + + fromHeaderTests.forEach(({ description, input, expected }) => { + it(description, () => { + expect(BasicAuth.fromAuthorizationHeader(input)).toEqual(expected); }); }); - it("throws error for completely empty credentials", () => { - expect(() => BasicAuth.fromAuthorizationHeader("Basic ")).toThrow("Invalid basic auth"); - }); + const errorTests: ErrorTestCase[] = [ + { + description: "throws error for completely empty credentials", + input: "Basic ", + expectedError: "Invalid basic auth", + }, + { + description: "throws error for credentials without colon", + input: "Basic dXNlcm5hbWU=", + expectedError: "Invalid basic auth", + }, + ]; - it("throws error for credentials without colon", () => { - expect(() => BasicAuth.fromAuthorizationHeader("Basic dXNlcm5hbWU=")).toThrow("Invalid basic auth"); + errorTests.forEach(({ description, input, expectedError }) => { + it(description, () => { + expect(() => BasicAuth.fromAuthorizationHeader(input)).toThrow(expectedError); + }); }); }); }); diff --git a/tests/unit/fetcher/Fetcher.test.ts b/tests/unit/fetcher/Fetcher.test.ts index bfc6429..60df2b5 100644 --- a/tests/unit/fetcher/Fetcher.test.ts +++ b/tests/unit/fetcher/Fetcher.test.ts @@ -13,6 +13,7 @@ describe("Test fetcherImpl", () => { body: { data: "test" }, contentType: "application/json", requestType: "json", + maxRetries: 0, responseType: "json", }; @@ -33,7 +34,7 @@ describe("Test fetcherImpl", () => { "https://httpbin.org/post", expect.objectContaining({ method: "POST", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), body: JSON.stringify({ data: "test" }), }), ); @@ -47,6 +48,7 @@ describe("Test fetcherImpl", () => { headers: { "X-Test": "x-test-header" }, contentType: "application/octet-stream", requestType: "bytes", + maxRetries: 0, responseType: "json", body: fs.createReadStream(join(__dirname, "test-file.txt")), }; @@ -64,7 +66,7 @@ describe("Test fetcherImpl", () => { url, expect.objectContaining({ method: "POST", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), body: expect.any(fs.ReadStream), }), ); @@ -80,6 +82,7 @@ describe("Test fetcherImpl", () => { url, method: "GET", headers: { "X-Test": "x-test-header" }, + maxRetries: 0, responseType: "binary-response", }; @@ -99,7 +102,7 @@ describe("Test fetcherImpl", () => { url, expect.objectContaining({ method: "GET", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), }), ); expect(result.ok).toBe(true); @@ -125,6 +128,7 @@ describe("Test fetcherImpl", () => { url, method: "GET", headers: { "X-Test": "x-test-header" }, + maxRetries: 0, responseType: "binary-response", }; @@ -144,7 +148,7 @@ describe("Test fetcherImpl", () => { url, expect.objectContaining({ method: "GET", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), }), ); expect(result.ok).toBe(true); @@ -170,6 +174,7 @@ describe("Test fetcherImpl", () => { url, method: "GET", headers: { "X-Test": "x-test-header" }, + maxRetries: 0, responseType: "binary-response", }; @@ -189,7 +194,7 @@ describe("Test fetcherImpl", () => { url, expect.objectContaining({ method: "GET", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), }), ); expect(result.ok).toBe(true); @@ -213,6 +218,7 @@ describe("Test fetcherImpl", () => { url, method: "GET", headers: { "X-Test": "x-test-header" }, + maxRetries: 0, responseType: "binary-response", }; @@ -232,7 +238,7 @@ describe("Test fetcherImpl", () => { url, expect.objectContaining({ method: "GET", - headers: expect.objectContaining({ "X-Test": "x-test-header" }), + headers: expect.toContainHeaders({ "X-Test": "x-test-header" }), }), ); expect(result.ok).toBe(true); diff --git a/tests/unit/fetcher/createRequestUrl.test.ts b/tests/unit/fetcher/createRequestUrl.test.ts index 06e03b2..a92f1b5 100644 --- a/tests/unit/fetcher/createRequestUrl.test.ts +++ b/tests/unit/fetcher/createRequestUrl.test.ts @@ -1,160 +1,163 @@ import { createRequestUrl } from "../../../src/core/fetcher/createRequestUrl"; describe("Test createRequestUrl", () => { - it("should return the base URL when no query parameters are provided", () => { - const baseUrl = "https://api.example.com"; - expect(createRequestUrl(baseUrl)).toBe(baseUrl); - }); - - it("should append simple query parameters", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { key: "value", another: "param" }; - expect(createRequestUrl(baseUrl, queryParams)).toBe("https://api.example.com?key=value&another=param"); - }); - - it("should handle array query parameters", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { items: ["a", "b", "c"] }; - expect(createRequestUrl(baseUrl, queryParams)).toBe("https://api.example.com?items=a&items=b&items=c"); - }); - - it("should handle object query parameters", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { filter: { name: "John", age: 30 } }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?filter%5Bname%5D=John&filter%5Bage%5D=30", - ); - }); - - it("should handle mixed types of query parameters", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - simple: "value", - array: ["x", "y"], - object: { key: "value" }, - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?simple=value&array=x&array=y&object%5Bkey%5D=value", - ); - }); - - it("should handle empty query parameters object", () => { - const baseUrl = "https://api.example.com"; - expect(createRequestUrl(baseUrl, {})).toBe(baseUrl); - }); - - it("should encode special characters in query parameters", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { special: "a&b=c d" }; - expect(createRequestUrl(baseUrl, queryParams)).toBe("https://api.example.com?special=a%26b%3Dc%20d"); - }); - - // Additional tests for edge cases and different value types - it("should handle numeric values", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { count: 42, price: 19.99, active: 1, inactive: 0 }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?count=42&price=19.99&active=1&inactive=0", - ); - }); - - it("should handle boolean values", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { enabled: true, disabled: false }; - expect(createRequestUrl(baseUrl, queryParams)).toBe("https://api.example.com?enabled=true&disabled=false"); - }); - - it("should handle null and undefined values", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - valid: "value", - nullValue: null, - undefinedValue: undefined, - emptyString: "", - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?valid=value&nullValue=&emptyString=", - ); - }); - - it("should handle deeply nested objects", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - user: { - profile: { - name: "John", - settings: { theme: "dark" }, + const BASE_URL = "https://api.example.com"; + + interface TestCase { + description: string; + baseUrl: string; + queryParams?: Record; + expected: string; + } + + const testCases: TestCase[] = [ + { + description: "should return the base URL when no query parameters are provided", + baseUrl: BASE_URL, + expected: BASE_URL, + }, + { + description: "should append simple query parameters", + baseUrl: BASE_URL, + queryParams: { key: "value", another: "param" }, + expected: "https://api.example.com?key=value&another=param", + }, + { + description: "should handle array query parameters", + baseUrl: BASE_URL, + queryParams: { items: ["a", "b", "c"] }, + expected: "https://api.example.com?items=a&items=b&items=c", + }, + { + description: "should handle object query parameters", + baseUrl: BASE_URL, + queryParams: { filter: { name: "John", age: 30 } }, + expected: "https://api.example.com?filter%5Bname%5D=John&filter%5Bage%5D=30", + }, + { + description: "should handle mixed types of query parameters", + baseUrl: BASE_URL, + queryParams: { + simple: "value", + array: ["x", "y"], + object: { key: "value" }, + }, + expected: "https://api.example.com?simple=value&array=x&array=y&object%5Bkey%5D=value", + }, + { + description: "should handle empty query parameters object", + baseUrl: BASE_URL, + queryParams: {}, + expected: BASE_URL, + }, + { + description: "should encode special characters in query parameters", + baseUrl: BASE_URL, + queryParams: { special: "a&b=c d" }, + expected: "https://api.example.com?special=a%26b%3Dc%20d", + }, + { + description: "should handle numeric values", + baseUrl: BASE_URL, + queryParams: { count: 42, price: 19.99, active: 1, inactive: 0 }, + expected: "https://api.example.com?count=42&price=19.99&active=1&inactive=0", + }, + { + description: "should handle boolean values", + baseUrl: BASE_URL, + queryParams: { enabled: true, disabled: false }, + expected: "https://api.example.com?enabled=true&disabled=false", + }, + { + description: "should handle null and undefined values", + baseUrl: BASE_URL, + queryParams: { + valid: "value", + nullValue: null, + undefinedValue: undefined, + emptyString: "", + }, + expected: "https://api.example.com?valid=value&nullValue=&emptyString=", + }, + { + description: "should handle deeply nested objects", + baseUrl: BASE_URL, + queryParams: { + user: { + profile: { + name: "John", + settings: { theme: "dark" }, + }, }, }, - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?user%5Bprofile%5D%5Bname%5D=John&user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark", - ); - }); - - it("should handle arrays of objects", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - users: [ - { name: "John", age: 30 }, - { name: "Jane", age: 25 }, - ], - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?users%5Bname%5D=John&users%5Bage%5D=30&users%5Bname%5D=Jane&users%5Bage%5D=25", - ); - }); - - it("should handle mixed arrays", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - mixed: ["string", 42, true, { key: "value" }], - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?mixed=string&mixed=42&mixed=true&mixed%5Bkey%5D=value", - ); - }); - - it("should handle empty arrays", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { emptyArray: [] }; - expect(createRequestUrl(baseUrl, queryParams)).toBe(baseUrl); - }); - - it("should handle empty objects", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { emptyObject: {} }; - expect(createRequestUrl(baseUrl, queryParams)).toBe(baseUrl); - }); - - it("should handle special characters in keys", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { "key with spaces": "value", "key[with]brackets": "value" }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?key%20with%20spaces=value&key%5Bwith%5Dbrackets=value", - ); - }); - - it("should handle URL with existing query parameters", () => { - const baseUrl = "https://api.example.com?existing=param"; - const queryParams = { new: "value" }; - expect(createRequestUrl(baseUrl, queryParams)).toBe("https://api.example.com?existing=param?new=value"); - }); - - it("should handle complex nested structures", () => { - const baseUrl = "https://api.example.com"; - const queryParams = { - filters: { - status: ["active", "pending"], - category: { - type: "electronics", - subcategories: ["phones", "laptops"], + expected: + "https://api.example.com?user%5Bprofile%5D%5Bname%5D=John&user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark", + }, + { + description: "should handle arrays of objects", + baseUrl: BASE_URL, + queryParams: { + users: [ + { name: "John", age: 30 }, + { name: "Jane", age: 25 }, + ], + }, + expected: + "https://api.example.com?users%5Bname%5D=John&users%5Bage%5D=30&users%5Bname%5D=Jane&users%5Bage%5D=25", + }, + { + description: "should handle mixed arrays", + baseUrl: BASE_URL, + queryParams: { + mixed: ["string", 42, true, { key: "value" }], + }, + expected: "https://api.example.com?mixed=string&mixed=42&mixed=true&mixed%5Bkey%5D=value", + }, + { + description: "should handle empty arrays", + baseUrl: BASE_URL, + queryParams: { emptyArray: [] }, + expected: BASE_URL, + }, + { + description: "should handle empty objects", + baseUrl: BASE_URL, + queryParams: { emptyObject: {} }, + expected: BASE_URL, + }, + { + description: "should handle special characters in keys", + baseUrl: BASE_URL, + queryParams: { "key with spaces": "value", "key[with]brackets": "value" }, + expected: "https://api.example.com?key%20with%20spaces=value&key%5Bwith%5Dbrackets=value", + }, + { + description: "should handle URL with existing query parameters", + baseUrl: "https://api.example.com?existing=param", + queryParams: { new: "value" }, + expected: "https://api.example.com?existing=param?new=value", + }, + { + description: "should handle complex nested structures", + baseUrl: BASE_URL, + queryParams: { + filters: { + status: ["active", "pending"], + category: { + type: "electronics", + subcategories: ["phones", "laptops"], + }, }, + sort: { field: "name", direction: "asc" }, }, - sort: { field: "name", direction: "asc" }, - }; - expect(createRequestUrl(baseUrl, queryParams)).toBe( - "https://api.example.com?filters%5Bstatus%5D=active&filters%5Bstatus%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", - ); + expected: + "https://api.example.com?filters%5Bstatus%5D=active&filters%5Bstatus%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", + }, + ]; + + testCases.forEach(({ description, baseUrl, queryParams, expected }) => { + it(description, () => { + expect(createRequestUrl(baseUrl, queryParams)).toBe(expected); + }); }); }); diff --git a/tests/unit/fetcher/getRequestBody.test.ts b/tests/unit/fetcher/getRequestBody.test.ts index e864c8b..8a6c3a5 100644 --- a/tests/unit/fetcher/getRequestBody.test.ts +++ b/tests/unit/fetcher/getRequestBody.test.ts @@ -2,15 +2,117 @@ import { getRequestBody } from "../../../src/core/fetcher/getRequestBody"; import { RUNTIME } from "../../../src/core/runtime"; describe("Test getRequestBody", () => { - it("should stringify body if not FormData in Node environment", async () => { - if (RUNTIME.type === "node") { - const body = { key: "value" }; + interface TestCase { + description: string; + input: any; + type: "json" | "form" | "file" | "bytes" | "other"; + expected: any; + skipCondition?: () => boolean; + } + + const testCases: TestCase[] = [ + { + description: "should stringify body if not FormData in Node environment", + input: { key: "value" }, + type: "json", + expected: '{"key":"value"}', + skipCondition: () => RUNTIME.type !== "node", + }, + { + description: "should stringify body if not FormData in browser environment", + input: { key: "value" }, + type: "json", + expected: '{"key":"value"}', + skipCondition: () => RUNTIME.type !== "browser", + }, + { + description: "should return the Uint8Array", + input: new Uint8Array([1, 2, 3]), + type: "bytes", + expected: new Uint8Array([1, 2, 3]), + }, + { + description: "should serialize objects for form-urlencoded content type", + input: { username: "johndoe", email: "john@example.com" }, + type: "form", + expected: "username=johndoe&email=john%40example.com", + }, + { + description: "should serialize complex nested objects and arrays for form-urlencoded content type", + input: { + user: { + profile: { + name: "John Doe", + settings: { + theme: "dark", + notifications: true, + }, + }, + tags: ["admin", "user"], + contacts: [ + { type: "email", value: "john@example.com" }, + { type: "phone", value: "+1234567890" }, + ], + }, + filters: { + status: ["active", "pending"], + metadata: { + created: "2024-01-01", + categories: ["electronics", "books"], + }, + }, + preferences: ["notifications", "updates"], + }, + type: "form", + expected: + "user%5Bprofile%5D%5Bname%5D=John%20Doe&" + + "user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark&" + + "user%5Bprofile%5D%5Bsettings%5D%5Bnotifications%5D=true&" + + "user%5Btags%5D=admin&" + + "user%5Btags%5D=user&" + + "user%5Bcontacts%5D%5Btype%5D=email&" + + "user%5Bcontacts%5D%5Bvalue%5D=john%40example.com&" + + "user%5Bcontacts%5D%5Btype%5D=phone&" + + "user%5Bcontacts%5D%5Bvalue%5D=%2B1234567890&" + + "filters%5Bstatus%5D=active&" + + "filters%5Bstatus%5D=pending&" + + "filters%5Bmetadata%5D%5Bcreated%5D=2024-01-01&" + + "filters%5Bmetadata%5D%5Bcategories%5D=electronics&" + + "filters%5Bmetadata%5D%5Bcategories%5D=books&" + + "preferences=notifications&" + + "preferences=updates", + }, + { + description: "should return the input for pre-serialized form-urlencoded strings", + input: "key=value&another=param", + type: "other", + expected: "key=value&another=param", + }, + { + description: "should JSON stringify objects", + input: { key: "value" }, + type: "json", + expected: '{"key":"value"}', + }, + ]; + + testCases.forEach(({ description, input, type, expected, skipCondition }) => { + it(description, async () => { + if (skipCondition?.()) { + return; + } + const result = await getRequestBody({ - body, - type: "json", + body: input, + type, }); - expect(result).toBe('{"key":"value"}'); - } + + if (input instanceof Uint8Array) { + expect(result).toBe(input); + } else { + expect(result).toBe(expected); + } + }); }); it("should return FormData in browser environment", async () => { @@ -24,42 +126,4 @@ describe("Test getRequestBody", () => { expect(result).toBe(formData); } }); - - it("should stringify body if not FormData in browser environment", async () => { - if (RUNTIME.type === "browser") { - const body = { key: "value" }; - const result = await getRequestBody({ - body, - type: "json", - }); - expect(result).toBe('{"key":"value"}'); - } - }); - - it("should return the Uint8Array", async () => { - const input = new Uint8Array([1, 2, 3]); - const result = await getRequestBody({ - body: input, - type: "bytes", - }); - expect(result).toBe(input); - }); - - it("should return the input for content-type 'application/x-www-form-urlencoded'", async () => { - const input = "key=value&another=param"; - const result = await getRequestBody({ - body: input, - type: "other", - }); - expect(result).toBe(input); - }); - - it("should JSON stringify objects", async () => { - const input = { key: "value" }; - const result = await getRequestBody({ - body: input, - type: "json", - }); - expect(result).toBe('{"key":"value"}'); - }); }); diff --git a/tests/unit/fetcher/getResponseBody.test.ts b/tests/unit/fetcher/getResponseBody.test.ts index 151843a..ad6be7f 100644 --- a/tests/unit/fetcher/getResponseBody.test.ts +++ b/tests/unit/fetcher/getResponseBody.test.ts @@ -1,7 +1,61 @@ import { getResponseBody } from "../../../src/core/fetcher/getResponseBody"; + import { RUNTIME } from "../../../src/core/runtime"; describe("Test getResponseBody", () => { + interface SimpleTestCase { + description: string; + responseData: string | Record; + responseType?: "blob" | "sse" | "streaming" | "text"; + expected: any; + skipCondition?: () => boolean; + } + + const simpleTestCases: SimpleTestCase[] = [ + { + description: "should handle text response type", + responseData: "test text", + responseType: "text", + expected: "test text", + }, + { + description: "should handle JSON response", + responseData: { key: "value" }, + expected: { key: "value" }, + }, + { + description: "should handle empty response", + responseData: "", + expected: undefined, + }, + { + description: "should handle non-JSON response", + responseData: "invalid json", + expected: { + ok: false, + error: { + reason: "non-json", + statusCode: 200, + rawBody: "invalid json", + }, + }, + }, + ]; + + simpleTestCases.forEach(({ description, responseData, responseType, expected, skipCondition }) => { + it(description, async () => { + if (skipCondition?.()) { + return; + } + + const mockResponse = new Response( + typeof responseData === "string" ? responseData : JSON.stringify(responseData), + ); + const result = await getResponseBody(mockResponse, responseType); + expect(result).toEqual(expected); + }); + }); + it("should handle blob response type", async () => { const mockBlob = new Blob(["test"], { type: "text/plain" }); const mockResponse = new Response(mockBlob); @@ -20,7 +74,6 @@ describe("Test getResponseBody", () => { }); it("should handle streaming response type", async () => { - // Create a ReadableStream with some test data const encoder = new TextEncoder(); const testData = "test stream data"; const mockStream = new ReadableStream({ @@ -35,43 +88,10 @@ describe("Test getResponseBody", () => { expect(result).toBeInstanceOf(ReadableStream); - // Read and verify the stream content const reader = result.getReader(); const decoder = new TextDecoder(); const { value } = await reader.read(); const streamContent = decoder.decode(value); expect(streamContent).toBe(testData); }); - - it("should handle text response type", async () => { - const mockResponse = new Response("test text"); - const result = await getResponseBody(mockResponse, "text"); - expect(result).toBe("test text"); - }); - - it("should handle JSON response", async () => { - const mockJson = { key: "value" }; - const mockResponse = new Response(JSON.stringify(mockJson)); - const result = await getResponseBody(mockResponse); - expect(result).toEqual(mockJson); - }); - - it("should handle empty response", async () => { - const mockResponse = new Response(""); - const result = await getResponseBody(mockResponse); - expect(result).toBeUndefined(); - }); - - it("should handle non-JSON response", async () => { - const mockResponse = new Response("invalid json"); - const result = await getResponseBody(mockResponse); - expect(result).toEqual({ - ok: false, - error: { - reason: "non-json", - statusCode: 200, - rawBody: "invalid json", - }, - }); - }); }); diff --git a/tests/unit/fetcher/logging.test.ts b/tests/unit/fetcher/logging.test.ts new file mode 100644 index 0000000..366c9b6 --- /dev/null +++ b/tests/unit/fetcher/logging.test.ts @@ -0,0 +1,517 @@ +import { fetcherImpl } from "../../../src/core/fetcher/Fetcher"; + +function createMockLogger() { + return { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }; +} + +function mockSuccessResponse(data: unknown = { data: "test" }, status = 200, statusText = "OK") { + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify(data), { + status, + statusText, + }), + ); +} + +function mockErrorResponse(data: unknown = { error: "Error" }, status = 404, statusText = "Not Found") { + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify(data), { + status, + statusText, + }), + ); +} + +describe("Fetcher Logging Integration", () => { + describe("Request Logging", () => { + it("should log successful request at debug level", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "POST", + headers: { "Content-Type": "application/json" }, + body: { test: "data" }, + contentType: "application/json", + requestType: "json", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + method: "POST", + url: "https://example.com/api", + headers: expect.toContainHeaders({ + "Content-Type": "application/json", + }), + hasBody: true, + }), + ); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "HTTP request succeeded", + expect.objectContaining({ + method: "POST", + url: "https://example.com/api", + statusCode: 200, + }), + ); + }); + + it("should not log debug messages at info level for successful requests", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "info", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).not.toHaveBeenCalled(); + }); + + it("should log request with body flag", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "POST", + body: { data: "test" }, + contentType: "application/json", + requestType: "json", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + hasBody: true, + }), + ); + }); + + it("should log request without body flag", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + hasBody: false, + }), + ); + }); + + it("should not log when silent mode is enabled", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: true, + }, + }); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).not.toHaveBeenCalled(); + expect(mockLogger.warn).not.toHaveBeenCalled(); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it("should not log when no logging config is provided", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + }); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + }); + }); + + describe("Error Logging", () => { + it("should log 4xx errors at error level", async () => { + const mockLogger = createMockLogger(); + mockErrorResponse({ error: "Not found" }, 404, "Not Found"); + + const result = await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(result.ok).toBe(false); + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request failed with error status", + expect.objectContaining({ + method: "GET", + url: "https://example.com/api", + statusCode: 404, + }), + ); + }); + + it("should log 5xx errors at error level", async () => { + const mockLogger = createMockLogger(); + mockErrorResponse({ error: "Internal error" }, 500, "Internal Server Error"); + + const result = await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(result.ok).toBe(false); + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request failed with error status", + expect.objectContaining({ + method: "GET", + url: "https://example.com/api", + statusCode: 500, + }), + ); + }); + + it("should log aborted request errors", async () => { + const mockLogger = createMockLogger(); + + const abortController = new AbortController(); + abortController.abort(); + + global.fetch = vi.fn().mockRejectedValue(new Error("Aborted")); + + const result = await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + abortSignal: abortController.signal, + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(result.ok).toBe(false); + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request was aborted", + expect.objectContaining({ + method: "GET", + url: "https://example.com/api", + }), + ); + }); + + it("should log timeout errors", async () => { + const mockLogger = createMockLogger(); + + const timeoutError = new Error("Request timeout"); + timeoutError.name = "AbortError"; + + global.fetch = vi.fn().mockRejectedValue(timeoutError); + + const result = await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(result.ok).toBe(false); + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request timed out", + expect.objectContaining({ + method: "GET", + url: "https://example.com/api", + timeoutMs: undefined, + }), + ); + }); + + it("should log unknown errors", async () => { + const mockLogger = createMockLogger(); + + const unknownError = new Error("Unknown error"); + + global.fetch = vi.fn().mockRejectedValue(unknownError); + + const result = await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(result.ok).toBe(false); + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request failed with error", + expect.objectContaining({ + method: "GET", + url: "https://example.com/api", + errorMessage: "Unknown error", + }), + ); + }); + }); + + describe("Logging with Redaction", () => { + it("should redact sensitive data in error logs", async () => { + const mockLogger = createMockLogger(); + mockErrorResponse({ error: "Unauthorized" }, 401, "Unauthorized"); + + await fetcherImpl({ + url: "https://example.com/api?api_key=secret", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request failed with error status", + expect.objectContaining({ + url: "https://example.com/api?api_key=[REDACTED]", + }), + ); + }); + }); + + describe("Different HTTP Methods", () => { + it("should log GET requests", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + method: "GET", + }), + ); + }); + + it("should log POST requests", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse({ data: "test" }, 201, "Created"); + + await fetcherImpl({ + url: "https://example.com/api", + method: "POST", + body: { data: "test" }, + contentType: "application/json", + requestType: "json", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + method: "POST", + }), + ); + }); + + it("should log PUT requests", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "PUT", + body: { data: "test" }, + contentType: "application/json", + requestType: "json", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + method: "PUT", + }), + ); + }); + + it("should log DELETE requests", async () => { + const mockLogger = createMockLogger(); + global.fetch = vi.fn().mockResolvedValue( + new Response(null, { + status: 200, + statusText: "OK", + }), + ); + + await fetcherImpl({ + url: "https://example.com/api", + method: "DELETE", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + method: "DELETE", + }), + ); + }); + }); + + describe("Status Code Logging", () => { + it("should log 2xx success status codes", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse({ data: "test" }, 201, "Created"); + + await fetcherImpl({ + url: "https://example.com/api", + method: "POST", + body: { data: "test" }, + contentType: "application/json", + requestType: "json", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "HTTP request succeeded", + expect.objectContaining({ + statusCode: 201, + }), + ); + }); + + it("should log 3xx redirect status codes as success", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse({ data: "test" }, 301, "Moved Permanently"); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "HTTP request succeeded", + expect.objectContaining({ + statusCode: 301, + }), + ); + }); + }); +}); diff --git a/tests/unit/fetcher/makeRequest.test.ts b/tests/unit/fetcher/makeRequest.test.ts index f6203cd..ea49466 100644 --- a/tests/unit/fetcher/makeRequest.test.ts +++ b/tests/unit/fetcher/makeRequest.test.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { makeRequest } from "../../../src/core/fetcher/makeRequest"; describe("Test makeRequest", () => { @@ -6,7 +7,7 @@ describe("Test makeRequest", () => { const mockHeaders = { "Content-Type": "application/json" }; const mockBody = JSON.stringify({ key: "value" }); - let mockFetch: import("vitest").Mock; + let mockFetch: Mock; beforeEach(() => { mockFetch = vi.fn(); diff --git a/tests/unit/fetcher/redacting.test.ts b/tests/unit/fetcher/redacting.test.ts new file mode 100644 index 0000000..d599376 --- /dev/null +++ b/tests/unit/fetcher/redacting.test.ts @@ -0,0 +1,1115 @@ +import { fetcherImpl } from "../../../src/core/fetcher/Fetcher"; + +function createMockLogger() { + return { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }; +} + +function mockSuccessResponse(data: unknown = { data: "test" }, status = 200, statusText = "OK") { + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify(data), { + status, + statusText, + }), + ); +} + +describe("Redacting Logic", () => { + describe("Header Redaction", () => { + it("should redact authorization header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { Authorization: "Bearer secret-token-12345" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + Authorization: "[REDACTED]", + }), + }), + ); + }); + + it("should redact api-key header (case-insensitive)", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "X-API-KEY": "secret-api-key" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "X-API-KEY": "[REDACTED]", + }), + }), + ); + }); + + it("should redact cookie header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { Cookie: "session=abc123; token=xyz789" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + Cookie: "[REDACTED]", + }), + }), + ); + }); + + it("should redact x-auth-token header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "x-auth-token": "auth-token-12345" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "x-auth-token": "[REDACTED]", + }), + }), + ); + }); + + it("should redact proxy-authorization header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "Proxy-Authorization": "Basic credentials" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "Proxy-Authorization": "[REDACTED]", + }), + }), + ); + }); + + it("should redact x-csrf-token header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "X-CSRF-Token": "csrf-token-abc" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "X-CSRF-Token": "[REDACTED]", + }), + }), + ); + }); + + it("should redact www-authenticate header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "WWW-Authenticate": "Bearer realm=example" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "WWW-Authenticate": "[REDACTED]", + }), + }), + ); + }); + + it("should redact x-session-token header", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { "X-Session-Token": "session-token-xyz" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "X-Session-Token": "[REDACTED]", + }), + }), + ); + }); + + it("should not redact non-sensitive headers", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { + "Content-Type": "application/json", + "User-Agent": "Test/1.0", + Accept: "application/json", + }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + "Content-Type": "application/json", + "User-Agent": "Test/1.0", + Accept: "application/json", + }), + }), + ); + }); + + it("should redact multiple sensitive headers at once", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + headers: { + Authorization: "Bearer token", + "X-API-Key": "api-key", + Cookie: "session=123", + "Content-Type": "application/json", + }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + headers: expect.toContainHeaders({ + Authorization: "[REDACTED]", + "X-API-Key": "[REDACTED]", + Cookie: "[REDACTED]", + "Content-Type": "application/json", + }), + }), + ); + }); + }); + + describe("Response Header Redaction", () => { + it("should redact Set-Cookie in response headers", async () => { + const mockLogger = createMockLogger(); + + const mockHeaders = new Headers(); + mockHeaders.set("Set-Cookie", "session=abc123; HttpOnly; Secure"); + mockHeaders.set("Content-Type", "application/json"); + + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ data: "test" }), { + status: 200, + statusText: "OK", + headers: mockHeaders, + }), + ); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "HTTP request succeeded", + expect.objectContaining({ + responseHeaders: expect.toContainHeaders({ + "set-cookie": "[REDACTED]", + "content-type": "application/json", + }), + }), + ); + }); + + it("should redact authorization in response headers", async () => { + const mockLogger = createMockLogger(); + + const mockHeaders = new Headers(); + mockHeaders.set("Authorization", "Bearer token-123"); + mockHeaders.set("Content-Type", "application/json"); + + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ data: "test" }), { + status: 200, + statusText: "OK", + headers: mockHeaders, + }), + ); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "HTTP request succeeded", + expect.objectContaining({ + responseHeaders: expect.toContainHeaders({ + authorization: "[REDACTED]", + "content-type": "application/json", + }), + }), + ); + }); + + it("should redact response headers in error responses", async () => { + const mockLogger = createMockLogger(); + + const mockHeaders = new Headers(); + mockHeaders.set("WWW-Authenticate", "Bearer realm=example"); + mockHeaders.set("Content-Type", "application/json"); + + global.fetch = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ error: "Unauthorized" }), { + status: 401, + statusText: "Unauthorized", + headers: mockHeaders, + }), + ); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "error", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.error).toHaveBeenCalledWith( + "HTTP request failed with error status", + expect.objectContaining({ + responseHeaders: expect.toContainHeaders({ + "www-authenticate": "[REDACTED]", + "content-type": "application/json", + }), + }), + ); + }); + }); + + describe("Query Parameter Redaction", () => { + it("should redact api_key query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { api_key: "secret-key" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + api_key: "[REDACTED]", + }), + }), + ); + }); + + it("should redact token query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { token: "secret-token" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + token: "[REDACTED]", + }), + }), + ); + }); + + it("should redact access_token query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { access_token: "secret-access-token" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + access_token: "[REDACTED]", + }), + }), + ); + }); + + it("should redact password query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { password: "secret-password" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + password: "[REDACTED]", + }), + }), + ); + }); + + it("should redact secret query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { secret: "secret-value" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + secret: "[REDACTED]", + }), + }), + ); + }); + + it("should redact session_id query parameter", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { session_id: "session-123" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + session_id: "[REDACTED]", + }), + }), + ); + }); + + it("should not redact non-sensitive query parameters", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { + page: "1", + limit: "10", + sort: "name", + }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + page: "1", + limit: "10", + sort: "name", + }), + }), + ); + }); + + it("should not redact parameters containing 'auth' substring like 'author'", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { + author: "john", + authenticate: "false", + authorization_level: "user", + }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + author: "john", + authenticate: "false", + authorization_level: "user", + }), + }), + ); + }); + + it("should handle undefined query parameters", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: undefined, + }), + ); + }); + + it("should redact case-insensitive query parameters", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + queryParameters: { API_KEY: "secret-key", Token: "secret-token" }, + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + queryParameters: expect.objectContaining({ + API_KEY: "[REDACTED]", + Token: "[REDACTED]", + }), + }), + ); + }); + }); + + describe("URL Redaction", () => { + it("should redact credentials in URL", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://user:password@example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://[REDACTED]@example.com/api", + }), + ); + }); + + it("should redact api_key in query string", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?api_key=secret-key&page=1", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?api_key=[REDACTED]&page=1", + }), + ); + }); + + it("should redact token in query string", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?token=secret-token", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?token=[REDACTED]", + }), + ); + }); + + it("should redact password in query string", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?username=user&password=secret", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?username=user&password=[REDACTED]", + }), + ); + }); + + it("should not redact non-sensitive query strings", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?page=1&limit=10&sort=name", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?page=1&limit=10&sort=name", + }), + ); + }); + + it("should not redact URL parameters containing 'auth' substring like 'author'", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?author=john&authenticate=false&page=1", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?author=john&authenticate=false&page=1", + }), + ); + }); + + it("should handle URL with fragment", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?token=secret#section", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?token=[REDACTED]#section", + }), + ); + }); + + it("should redact URL-encoded query parameters", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?api%5Fkey=secret", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?api%5Fkey=[REDACTED]", + }), + ); + }); + + it("should handle URL without query string", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api", + }), + ); + }); + + it("should handle empty query string", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?", + }), + ); + }); + + it("should redact multiple sensitive parameters in URL", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?api_key=secret1&token=secret2&page=1", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?api_key=[REDACTED]&token=[REDACTED]&page=1", + }), + ); + }); + + it("should redact both credentials and query parameters", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://user:pass@example.com/api?token=secret", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://[REDACTED]@example.com/api?token=[REDACTED]", + }), + ); + }); + + it("should use fast path for URLs without sensitive keywords", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?page=1&limit=10&sort=name&filter=value", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?page=1&limit=10&sort=name&filter=value", + }), + ); + }); + + it("should handle query parameter without value", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?flag&token=secret", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?flag&token=[REDACTED]", + }), + ); + }); + + it("should handle URL with multiple @ symbols in credentials", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://user@example.com:pass@host.com/api", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://[REDACTED]@host.com/api", + }), + ); + }); + + it("should handle URL with @ in query parameter but not in credentials", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://example.com/api?email=user@example.com", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://example.com/api?email=user@example.com", + }), + ); + }); + + it("should handle URL with both credentials and @ in path", async () => { + const mockLogger = createMockLogger(); + mockSuccessResponse(); + + await fetcherImpl({ + url: "https://user:pass@example.com/users/@username", + method: "GET", + responseType: "json", + maxRetries: 0, + logging: { + level: "debug", + logger: mockLogger, + silent: false, + }, + }); + + expect(mockLogger.debug).toHaveBeenCalledWith( + "Making HTTP request", + expect.objectContaining({ + url: "https://[REDACTED]@example.com/users/@username", + }), + ); + }); + }); +}); diff --git a/tests/unit/fetcher/requestWithRetries.test.ts b/tests/unit/fetcher/requestWithRetries.test.ts index 7d46082..d226613 100644 --- a/tests/unit/fetcher/requestWithRetries.test.ts +++ b/tests/unit/fetcher/requestWithRetries.test.ts @@ -1,15 +1,15 @@ +import type { Mock, MockInstance } from "vitest"; import { requestWithRetries } from "../../../src/core/fetcher/requestWithRetries"; describe("requestWithRetries", () => { - let mockFetch: import("vitest").Mock; + let mockFetch: Mock; let originalMathRandom: typeof Math.random; - let setTimeoutSpy: import("vitest").MockInstance; + let setTimeoutSpy: MockInstance; beforeEach(() => { mockFetch = vi.fn(); originalMathRandom = Math.random; - // Mock Math.random for consistent jitter Math.random = vi.fn(() => 0.5); vi.useFakeTimers({ @@ -99,6 +99,67 @@ describe("requestWithRetries", () => { } }); + interface RetryHeaderTestCase { + description: string; + headerName: string; + headerValue: string | (() => string); + expectedDelayMin: number; + expectedDelayMax: number; + } + + const retryHeaderTests: RetryHeaderTestCase[] = [ + { + description: "should respect retry-after header with seconds value", + headerName: "retry-after", + headerValue: "5", + expectedDelayMin: 4000, + expectedDelayMax: 6000, + }, + { + description: "should respect retry-after header with HTTP date value", + headerName: "retry-after", + headerValue: () => new Date(Date.now() + 3000).toUTCString(), + expectedDelayMin: 2000, + expectedDelayMax: 4000, + }, + { + description: "should respect x-ratelimit-reset header", + headerName: "x-ratelimit-reset", + headerValue: () => Math.floor((Date.now() + 4000) / 1000).toString(), + expectedDelayMin: 3000, + expectedDelayMax: 6000, + }, + ]; + + retryHeaderTests.forEach(({ description, headerName, headerValue, expectedDelayMin, expectedDelayMax }) => { + it(description, async () => { + setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { + process.nextTick(callback); + return null as any; + }); + + const value = typeof headerValue === "function" ? headerValue() : headerValue; + mockFetch + .mockResolvedValueOnce( + new Response("", { + status: 429, + headers: new Headers({ [headerName]: value }), + }), + ) + .mockResolvedValueOnce(new Response("", { status: 200 })); + + const responsePromise = requestWithRetries(() => mockFetch(), 1); + await vi.runAllTimersAsync(); + const response = await responsePromise; + + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), expect.any(Number)); + const actualDelay = setTimeoutSpy.mock.calls[0][1]; + expect(actualDelay).toBeGreaterThan(expectedDelayMin); + expect(actualDelay).toBeLessThan(expectedDelayMax); + expect(response.status).toBe(200); + }); + }); + it("should apply correct exponential backoff with jitter", async () => { setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { process.nextTick(callback); @@ -113,7 +174,6 @@ describe("requestWithRetries", () => { await vi.runAllTimersAsync(); await responsePromise; - // Verify setTimeout calls expect(setTimeoutSpy).toHaveBeenCalledTimes(expectedDelays.length); expectedDelays.forEach((delay, index) => { @@ -145,85 +205,6 @@ describe("requestWithRetries", () => { expect(response2.status).toBe(200); }); - it("should respect retry-after header with seconds value", async () => { - setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { - process.nextTick(callback); - return null as any; - }); - - mockFetch - .mockResolvedValueOnce( - new Response("", { - status: 429, - headers: new Headers({ "retry-after": "5" }), - }), - ) - .mockResolvedValueOnce(new Response("", { status: 200 })); - - const responsePromise = requestWithRetries(() => mockFetch(), 1); - await vi.runAllTimersAsync(); - const response = await responsePromise; - - expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 5000); // 5 seconds = 5000ms - expect(response.status).toBe(200); - }); - - it("should respect retry-after header with HTTP date value", async () => { - setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { - process.nextTick(callback); - return null as any; - }); - - const futureDate = new Date(Date.now() + 3000); // 3 seconds from now - mockFetch - .mockResolvedValueOnce( - new Response("", { - status: 429, - headers: new Headers({ "retry-after": futureDate.toUTCString() }), - }), - ) - .mockResolvedValueOnce(new Response("", { status: 200 })); - - const responsePromise = requestWithRetries(() => mockFetch(), 1); - await vi.runAllTimersAsync(); - const response = await responsePromise; - - // Should use the date-based delay (approximately 3000ms, but with jitter) - expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), expect.any(Number)); - const actualDelay = setTimeoutSpy.mock.calls[0][1]; - expect(actualDelay).toBeGreaterThan(2000); - expect(actualDelay).toBeLessThan(4000); - expect(response.status).toBe(200); - }); - - it("should respect x-ratelimit-reset header", async () => { - setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { - process.nextTick(callback); - return null as any; - }); - - const resetTime = Math.floor((Date.now() + 4000) / 1000); // 4 seconds from now in Unix timestamp - mockFetch - .mockResolvedValueOnce( - new Response("", { - status: 429, - headers: new Headers({ "x-ratelimit-reset": resetTime.toString() }), - }), - ) - .mockResolvedValueOnce(new Response("", { status: 200 })); - - const responsePromise = requestWithRetries(() => mockFetch(), 1); - await vi.runAllTimersAsync(); - const response = await responsePromise; - - // Should use the x-ratelimit-reset delay (approximately 4000ms, but with positive jitter) - expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), expect.any(Number)); - const actualDelay = setTimeoutSpy.mock.calls[0][1]; - expect(actualDelay).toBeGreaterThan(3000); - expect(actualDelay).toBeLessThan(6000); - expect(response.status).toBe(200); - }); - it("should cap delay at MAX_RETRY_DELAY for large header values", async () => { setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((callback: (args: void) => void) => { process.nextTick(callback); @@ -243,8 +224,7 @@ describe("requestWithRetries", () => { await vi.runAllTimersAsync(); const response = await responsePromise; - // Should be capped at MAX_RETRY_DELAY (60000ms) with jitter applied - expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 60000); // Exactly MAX_RETRY_DELAY since jitter with 0.5 random keeps it at 60000 + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 60000); expect(response.status).toBe(200); }); }); diff --git a/tests/unit/logging/logger.test.ts b/tests/unit/logging/logger.test.ts new file mode 100644 index 0000000..2e0b5fe --- /dev/null +++ b/tests/unit/logging/logger.test.ts @@ -0,0 +1,454 @@ +import { ConsoleLogger, createLogger, Logger, LogLevel } from "../../../src/core/logging/logger"; + +function createMockLogger() { + return { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }; +} + +describe("Logger", () => { + describe("LogLevel", () => { + it("should have correct log levels", () => { + expect(LogLevel.Debug).toBe("debug"); + expect(LogLevel.Info).toBe("info"); + expect(LogLevel.Warn).toBe("warn"); + expect(LogLevel.Error).toBe("error"); + }); + }); + + describe("ConsoleLogger", () => { + let consoleLogger: ConsoleLogger; + let consoleSpy: { + debug: ReturnType; + info: ReturnType; + warn: ReturnType; + error: ReturnType; + }; + + beforeEach(() => { + consoleLogger = new ConsoleLogger(); + consoleSpy = { + debug: vi.spyOn(console, "debug").mockImplementation(() => {}), + info: vi.spyOn(console, "info").mockImplementation(() => {}), + warn: vi.spyOn(console, "warn").mockImplementation(() => {}), + error: vi.spyOn(console, "error").mockImplementation(() => {}), + }; + }); + + afterEach(() => { + consoleSpy.debug.mockRestore(); + consoleSpy.info.mockRestore(); + consoleSpy.warn.mockRestore(); + consoleSpy.error.mockRestore(); + }); + + it("should log debug messages", () => { + consoleLogger.debug("debug message", { data: "test" }); + expect(consoleSpy.debug).toHaveBeenCalledWith("debug message", { data: "test" }); + }); + + it("should log info messages", () => { + consoleLogger.info("info message", { data: "test" }); + expect(consoleSpy.info).toHaveBeenCalledWith("info message", { data: "test" }); + }); + + it("should log warn messages", () => { + consoleLogger.warn("warn message", { data: "test" }); + expect(consoleSpy.warn).toHaveBeenCalledWith("warn message", { data: "test" }); + }); + + it("should log error messages", () => { + consoleLogger.error("error message", { data: "test" }); + expect(consoleSpy.error).toHaveBeenCalledWith("error message", { data: "test" }); + }); + + it("should handle multiple arguments", () => { + consoleLogger.debug("message", "arg1", "arg2", { key: "value" }); + expect(consoleSpy.debug).toHaveBeenCalledWith("message", "arg1", "arg2", { key: "value" }); + }); + }); + + describe("Logger with level filtering", () => { + let mockLogger: { + debug: ReturnType; + info: ReturnType; + warn: ReturnType; + error: ReturnType; + }; + + beforeEach(() => { + mockLogger = createMockLogger(); + }); + + describe("Debug level", () => { + it("should log all levels when set to debug", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + logger.debug("debug"); + logger.info("info"); + logger.warn("warn"); + logger.error("error"); + + expect(mockLogger.debug).toHaveBeenCalledWith("debug"); + expect(mockLogger.info).toHaveBeenCalledWith("info"); + expect(mockLogger.warn).toHaveBeenCalledWith("warn"); + expect(mockLogger.error).toHaveBeenCalledWith("error"); + }); + + it("should report correct level checks", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + expect(logger.isDebug()).toBe(true); + expect(logger.isInfo()).toBe(true); + expect(logger.isWarn()).toBe(true); + expect(logger.isError()).toBe(true); + }); + }); + + describe("Info level", () => { + it("should log info, warn, and error when set to info", () => { + const logger = new Logger({ + level: LogLevel.Info, + logger: mockLogger, + silent: false, + }); + + logger.debug("debug"); + logger.info("info"); + logger.warn("warn"); + logger.error("error"); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).toHaveBeenCalledWith("info"); + expect(mockLogger.warn).toHaveBeenCalledWith("warn"); + expect(mockLogger.error).toHaveBeenCalledWith("error"); + }); + + it("should report correct level checks", () => { + const logger = new Logger({ + level: LogLevel.Info, + logger: mockLogger, + silent: false, + }); + + expect(logger.isDebug()).toBe(false); + expect(logger.isInfo()).toBe(true); + expect(logger.isWarn()).toBe(true); + expect(logger.isError()).toBe(true); + }); + }); + + describe("Warn level", () => { + it("should log warn and error when set to warn", () => { + const logger = new Logger({ + level: LogLevel.Warn, + logger: mockLogger, + silent: false, + }); + + logger.debug("debug"); + logger.info("info"); + logger.warn("warn"); + logger.error("error"); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).not.toHaveBeenCalled(); + expect(mockLogger.warn).toHaveBeenCalledWith("warn"); + expect(mockLogger.error).toHaveBeenCalledWith("error"); + }); + + it("should report correct level checks", () => { + const logger = new Logger({ + level: LogLevel.Warn, + logger: mockLogger, + silent: false, + }); + + expect(logger.isDebug()).toBe(false); + expect(logger.isInfo()).toBe(false); + expect(logger.isWarn()).toBe(true); + expect(logger.isError()).toBe(true); + }); + }); + + describe("Error level", () => { + it("should only log error when set to error", () => { + const logger = new Logger({ + level: LogLevel.Error, + logger: mockLogger, + silent: false, + }); + + logger.debug("debug"); + logger.info("info"); + logger.warn("warn"); + logger.error("error"); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).not.toHaveBeenCalled(); + expect(mockLogger.warn).not.toHaveBeenCalled(); + expect(mockLogger.error).toHaveBeenCalledWith("error"); + }); + + it("should report correct level checks", () => { + const logger = new Logger({ + level: LogLevel.Error, + logger: mockLogger, + silent: false, + }); + + expect(logger.isDebug()).toBe(false); + expect(logger.isInfo()).toBe(false); + expect(logger.isWarn()).toBe(false); + expect(logger.isError()).toBe(true); + }); + }); + + describe("Silent mode", () => { + it("should not log anything when silent is true", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: true, + }); + + logger.debug("debug"); + logger.info("info"); + logger.warn("warn"); + logger.error("error"); + + expect(mockLogger.debug).not.toHaveBeenCalled(); + expect(mockLogger.info).not.toHaveBeenCalled(); + expect(mockLogger.warn).not.toHaveBeenCalled(); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it("should report all level checks as false when silent", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: true, + }); + + expect(logger.isDebug()).toBe(false); + expect(logger.isInfo()).toBe(false); + expect(logger.isWarn()).toBe(false); + expect(logger.isError()).toBe(false); + }); + }); + + describe("shouldLog", () => { + it("should correctly determine if level should be logged", () => { + const logger = new Logger({ + level: LogLevel.Info, + logger: mockLogger, + silent: false, + }); + + expect(logger.shouldLog(LogLevel.Debug)).toBe(false); + expect(logger.shouldLog(LogLevel.Info)).toBe(true); + expect(logger.shouldLog(LogLevel.Warn)).toBe(true); + expect(logger.shouldLog(LogLevel.Error)).toBe(true); + }); + + it("should return false for all levels when silent", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: true, + }); + + expect(logger.shouldLog(LogLevel.Debug)).toBe(false); + expect(logger.shouldLog(LogLevel.Info)).toBe(false); + expect(logger.shouldLog(LogLevel.Warn)).toBe(false); + expect(logger.shouldLog(LogLevel.Error)).toBe(false); + }); + }); + + describe("Multiple arguments", () => { + it("should pass multiple arguments to logger", () => { + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + logger.debug("message", "arg1", { key: "value" }, 123); + expect(mockLogger.debug).toHaveBeenCalledWith("message", "arg1", { key: "value" }, 123); + }); + }); + }); + + describe("createLogger", () => { + it("should return default logger when no config provided", () => { + const logger = createLogger(); + expect(logger).toBeInstanceOf(Logger); + }); + + it("should return same logger instance when Logger is passed", () => { + const customLogger = new Logger({ + level: LogLevel.Debug, + logger: new ConsoleLogger(), + silent: false, + }); + + const result = createLogger(customLogger); + expect(result).toBe(customLogger); + }); + + it("should create logger with custom config", () => { + const mockLogger = createMockLogger(); + + const logger = createLogger({ + level: LogLevel.Warn, + logger: mockLogger, + silent: false, + }); + + expect(logger).toBeInstanceOf(Logger); + logger.warn("test"); + expect(mockLogger.warn).toHaveBeenCalledWith("test"); + }); + + it("should use default values for missing config", () => { + const logger = createLogger({}); + expect(logger).toBeInstanceOf(Logger); + }); + + it("should override default level", () => { + const mockLogger = createMockLogger(); + + const logger = createLogger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + logger.debug("test"); + expect(mockLogger.debug).toHaveBeenCalledWith("test"); + }); + + it("should override default silent mode", () => { + const mockLogger = createMockLogger(); + + const logger = createLogger({ + logger: mockLogger, + silent: false, + }); + + logger.info("test"); + expect(mockLogger.info).toHaveBeenCalledWith("test"); + }); + + it("should use provided logger implementation", () => { + const customLogger = createMockLogger(); + + const logger = createLogger({ + logger: customLogger, + level: LogLevel.Debug, + silent: false, + }); + + logger.debug("test"); + expect(customLogger.debug).toHaveBeenCalledWith("test"); + }); + + it("should default to silent: true", () => { + const mockLogger = createMockLogger(); + + const logger = createLogger({ + logger: mockLogger, + level: LogLevel.Debug, + }); + + logger.debug("test"); + expect(mockLogger.debug).not.toHaveBeenCalled(); + }); + }); + + describe("Default logger", () => { + it("should have silent: true by default", () => { + const logger = createLogger(); + expect(logger.shouldLog(LogLevel.Info)).toBe(false); + }); + + it("should not log when using default logger", () => { + const logger = createLogger(); + + logger.info("test"); + expect(logger.isInfo()).toBe(false); + }); + }); + + describe("Edge cases", () => { + it("should handle empty message", () => { + const mockLogger = createMockLogger(); + + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + logger.debug(""); + expect(mockLogger.debug).toHaveBeenCalledWith(""); + }); + + it("should handle no arguments", () => { + const mockLogger = createMockLogger(); + + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + logger.debug("message"); + expect(mockLogger.debug).toHaveBeenCalledWith("message"); + }); + + it("should handle complex objects", () => { + const mockLogger = createMockLogger(); + + const logger = new Logger({ + level: LogLevel.Debug, + logger: mockLogger, + silent: false, + }); + + const complexObject = { + nested: { key: "value" }, + array: [1, 2, 3], + fn: () => "test", + }; + + logger.debug("message", complexObject); + expect(mockLogger.debug).toHaveBeenCalledWith("message", complexObject); + }); + + it("should handle errors as arguments", () => { + const mockLogger = createMockLogger(); + + const logger = new Logger({ + level: LogLevel.Error, + logger: mockLogger, + silent: false, + }); + + const error = new Error("Test error"); + logger.error("Error occurred", error); + expect(mockLogger.error).toHaveBeenCalledWith("Error occurred", error); + }); + }); +}); diff --git a/tests/unit/schemas/primitives/never.test.ts b/tests/unit/schemas/primitives/never.test.ts new file mode 100644 index 0000000..1d18eba --- /dev/null +++ b/tests/unit/schemas/primitives/never.test.ts @@ -0,0 +1,54 @@ +import { never } from "../../../../src/core/schemas/builders"; + +describe("never", () => { + it("always fails to parse", () => { + const schema = never(); + const result = schema.parse("test"); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.errors).toHaveLength(1); + expect(result.errors[0]?.message).toBe("Expected never"); + } + }); + + it("always fails to json", () => { + const schema = never(); + const result = schema.json("test"); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.errors).toHaveLength(1); + expect(result.errors[0]?.message).toBe("Expected never"); + } + }); + + it("fails with any value including undefined", () => { + const schema = never(); + expect(schema.parse(undefined).ok).toBe(false); + expect(schema.parse(null).ok).toBe(false); + expect(schema.parse(0).ok).toBe(false); + expect(schema.parse("").ok).toBe(false); + expect(schema.parse({}).ok).toBe(false); + expect(schema.parse([]).ok).toBe(false); + }); + + it("works when called without options parameter", () => { + const schema = never(); + // This tests that the default = {} parameter works correctly + const result = schema.parse("test"); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.errors).toHaveLength(1); + expect(result.errors[0]?.message).toBe("Expected never"); + expect(result.errors[0]?.path).toEqual([]); + } + }); + + it("succeeds with skipValidation", () => { + const schema = never(); + const result = schema.parse("test", { skipValidation: true }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.value).toBe("test"); + } + }); +}); diff --git a/tests/unit/url/join.test.ts b/tests/unit/url/join.test.ts index 1956a8c..123488f 100644 --- a/tests/unit/url/join.test.ts +++ b/tests/unit/url/join.test.ts @@ -1,88 +1,223 @@ import { join } from "../../../src/core/url/index"; describe("join", () => { - describe("basic functionality", () => { - it("should return empty string for empty base", () => { - expect(join("")).toBe(""); - expect(join("", "path")).toBe(""); - }); + interface TestCase { + description: string; + base: string; + segments: string[]; + expected: string; + } - it("should handle single segment", () => { - expect(join("base", "segment")).toBe("base/segment"); - expect(join("base/", "segment")).toBe("base/segment"); - expect(join("base", "/segment")).toBe("base/segment"); - expect(join("base/", "/segment")).toBe("base/segment"); - }); + describe("basic functionality", () => { + const basicTests: TestCase[] = [ + { description: "should return empty string for empty base", base: "", segments: [], expected: "" }, + { + description: "should return empty string for empty base with path", + base: "", + segments: ["path"], + expected: "", + }, + { + description: "should handle single segment", + base: "base", + segments: ["segment"], + expected: "base/segment", + }, + { + description: "should handle single segment with trailing slash on base", + base: "base/", + segments: ["segment"], + expected: "base/segment", + }, + { + description: "should handle single segment with leading slash", + base: "base", + segments: ["/segment"], + expected: "base/segment", + }, + { + description: "should handle single segment with both slashes", + base: "base/", + segments: ["/segment"], + expected: "base/segment", + }, + { + description: "should handle multiple segments", + base: "base", + segments: ["path1", "path2", "path3"], + expected: "base/path1/path2/path3", + }, + { + description: "should handle multiple segments with slashes", + base: "base/", + segments: ["/path1/", "/path2/", "/path3/"], + expected: "base/path1/path2/path3/", + }, + ]; - it("should handle multiple segments", () => { - expect(join("base", "path1", "path2", "path3")).toBe("base/path1/path2/path3"); - expect(join("base/", "/path1/", "/path2/", "/path3/")).toBe("base/path1/path2/path3/"); + basicTests.forEach(({ description, base, segments, expected }) => { + it(description, () => { + expect(join(base, ...segments)).toBe(expected); + }); }); }); describe("URL handling", () => { - it("should handle absolute URLs", () => { - expect(join("https://example.com", "api", "v1")).toBe("https://example.com/api/v1"); - expect(join("https://example.com/", "/api/", "/v1/")).toBe("https://example.com/api/v1/"); - expect(join("https://example.com/base", "api", "v1")).toBe("https://example.com/base/api/v1"); - }); + const urlTests: TestCase[] = [ + { + description: "should handle absolute URLs", + base: "https://example.com", + segments: ["api", "v1"], + expected: "https://example.com/api/v1", + }, + { + description: "should handle absolute URLs with slashes", + base: "https://example.com/", + segments: ["/api/", "/v1/"], + expected: "https://example.com/api/v1/", + }, + { + description: "should handle absolute URLs with base path", + base: "https://example.com/base", + segments: ["api", "v1"], + expected: "https://example.com/base/api/v1", + }, + { + description: "should preserve URL query parameters", + base: "https://example.com?query=1", + segments: ["api"], + expected: "https://example.com/api?query=1", + }, + { + description: "should preserve URL fragments", + base: "https://example.com#fragment", + segments: ["api"], + expected: "https://example.com/api#fragment", + }, + { + description: "should preserve URL query and fragments", + base: "https://example.com?query=1#fragment", + segments: ["api"], + expected: "https://example.com/api?query=1#fragment", + }, + { + description: "should handle http protocol", + base: "http://example.com", + segments: ["api"], + expected: "http://example.com/api", + }, + { + description: "should handle ftp protocol", + base: "ftp://example.com", + segments: ["files"], + expected: "ftp://example.com/files", + }, + { + description: "should handle ws protocol", + base: "ws://example.com", + segments: ["socket"], + expected: "ws://example.com/socket", + }, + { + description: "should fallback to path joining for malformed URLs", + base: "not-a-url://", + segments: ["path"], + expected: "not-a-url:///path", + }, + ]; - it("should preserve URL query parameters and fragments", () => { - expect(join("https://example.com?query=1", "api")).toBe("https://example.com/api?query=1"); - expect(join("https://example.com#fragment", "api")).toBe("https://example.com/api#fragment"); - expect(join("https://example.com?query=1#fragment", "api")).toBe( - "https://example.com/api?query=1#fragment", - ); - }); - - it("should handle different protocols", () => { - expect(join("http://example.com", "api")).toBe("http://example.com/api"); - expect(join("ftp://example.com", "files")).toBe("ftp://example.com/files"); - expect(join("ws://example.com", "socket")).toBe("ws://example.com/socket"); - }); - - it("should fallback to path joining for malformed URLs", () => { - expect(join("not-a-url://", "path")).toBe("not-a-url:///path"); + urlTests.forEach(({ description, base, segments, expected }) => { + it(description, () => { + expect(join(base, ...segments)).toBe(expected); + }); }); }); describe("edge cases", () => { - it("should handle empty segments", () => { - expect(join("base", "", "path")).toBe("base/path"); - expect(join("base", null as any, "path")).toBe("base/path"); - expect(join("base", undefined as any, "path")).toBe("base/path"); - }); - - it("should handle segments with only slashes", () => { - expect(join("base", "/", "path")).toBe("base/path"); - expect(join("base", "//", "path")).toBe("base/path"); - }); - - it("should handle base paths with trailing slashes", () => { - expect(join("base/", "path")).toBe("base/path"); - }); + const edgeCaseTests: TestCase[] = [ + { + description: "should handle empty segments", + base: "base", + segments: ["", "path"], + expected: "base/path", + }, + { + description: "should handle null segments", + base: "base", + segments: [null as any, "path"], + expected: "base/path", + }, + { + description: "should handle undefined segments", + base: "base", + segments: [undefined as any, "path"], + expected: "base/path", + }, + { + description: "should handle segments with only single slash", + base: "base", + segments: ["/", "path"], + expected: "base/path", + }, + { + description: "should handle segments with only double slash", + base: "base", + segments: ["//", "path"], + expected: "base/path", + }, + { + description: "should handle base paths with trailing slashes", + base: "base/", + segments: ["path"], + expected: "base/path", + }, + { + description: "should handle complex nested paths", + base: "api/v1/", + segments: ["/users/", "/123/", "/profile"], + expected: "api/v1/users/123/profile", + }, + ]; - it("should handle complex nested paths", () => { - expect(join("api/v1/", "/users/", "/123/", "/profile")).toBe("api/v1/users/123/profile"); + edgeCaseTests.forEach(({ description, base, segments, expected }) => { + it(description, () => { + expect(join(base, ...segments)).toBe(expected); + }); }); }); describe("real-world scenarios", () => { - it("should handle API endpoint construction", () => { - const baseUrl = "https://api.example.com/v1"; - expect(join(baseUrl, "users", "123", "posts")).toBe("https://api.example.com/v1/users/123/posts"); - }); - - it("should handle file path construction", () => { - expect(join("/var/www", "html", "assets", "images")).toBe("/var/www/html/assets/images"); - }); + const realWorldTests: TestCase[] = [ + { + description: "should handle API endpoint construction", + base: "https://api.example.com/v1", + segments: ["users", "123", "posts"], + expected: "https://api.example.com/v1/users/123/posts", + }, + { + description: "should handle file path construction", + base: "/var/www", + segments: ["html", "assets", "images"], + expected: "/var/www/html/assets/images", + }, + { + description: "should handle relative path construction", + base: "../parent", + segments: ["child", "grandchild"], + expected: "../parent/child/grandchild", + }, + { + description: "should handle Windows-style paths", + base: "C:\\Users", + segments: ["Documents", "file.txt"], + expected: "C:\\Users/Documents/file.txt", + }, + ]; - it("should handle relative path construction", () => { - expect(join("../parent", "child", "grandchild")).toBe("../parent/child/grandchild"); - }); - - it("should handle Windows-style paths", () => { - expect(join("C:\\Users", "Documents", "file.txt")).toBe("C:\\Users/Documents/file.txt"); + realWorldTests.forEach(({ description, base, segments, expected }) => { + it(description, () => { + expect(join(base, ...segments)).toBe(expected); + }); }); }); @@ -100,21 +235,50 @@ describe("join", () => { }); describe("trailing slash preservation", () => { - it("should preserve trailing slash on final result when base has trailing slash and no segments", () => { - expect(join("https://api.example.com/")).toBe("https://api.example.com/"); - expect(join("https://api.example.com/v1/")).toBe("https://api.example.com/v1/"); - }); - - it("should preserve trailing slash when last segment has trailing slash", () => { - expect(join("https://api.example.com", "users/")).toBe("https://api.example.com/users/"); - expect(join("api/v1", "users/")).toBe("api/v1/users/"); - }); + const trailingSlashTests: TestCase[] = [ + { + description: + "should preserve trailing slash on final result when base has trailing slash and no segments", + base: "https://api.example.com/", + segments: [], + expected: "https://api.example.com/", + }, + { + description: "should preserve trailing slash on v1 path", + base: "https://api.example.com/v1/", + segments: [], + expected: "https://api.example.com/v1/", + }, + { + description: "should preserve trailing slash when last segment has trailing slash", + base: "https://api.example.com", + segments: ["users/"], + expected: "https://api.example.com/users/", + }, + { + description: "should preserve trailing slash with relative path", + base: "api/v1", + segments: ["users/"], + expected: "api/v1/users/", + }, + { + description: "should preserve trailing slash with multiple segments", + base: "https://api.example.com", + segments: ["v1", "collections/"], + expected: "https://api.example.com/v1/collections/", + }, + { + description: "should preserve trailing slash with base path", + base: "base", + segments: ["path1", "path2/"], + expected: "base/path1/path2/", + }, + ]; - it("should preserve trailing slash with multiple segments where last has trailing slash", () => { - expect(join("https://api.example.com", "v1", "collections/")).toBe( - "https://api.example.com/v1/collections/", - ); - expect(join("base", "path1", "path2/")).toBe("base/path1/path2/"); + trailingSlashTests.forEach(({ description, base, segments, expected }) => { + it(description, () => { + expect(join(base, ...segments)).toBe(expected); + }); }); }); }); diff --git a/tests/unit/url/qs.test.ts b/tests/unit/url/qs.test.ts index 80e7e04..42cdffb 100644 --- a/tests/unit/url/qs.test.ts +++ b/tests/unit/url/qs.test.ts @@ -1,187 +1,278 @@ import { toQueryString } from "../../../src/core/url/index"; describe("Test qs toQueryString", () => { - describe("Basic functionality", () => { - it("should return empty string for null/undefined", () => { - expect(toQueryString(null)).toBe(""); - expect(toQueryString(undefined)).toBe(""); - }); + interface BasicTestCase { + description: string; + input: any; + expected: string; + } - it("should return empty string for primitive values", () => { - expect(toQueryString("hello")).toBe(""); - expect(toQueryString(42)).toBe(""); - expect(toQueryString(true)).toBe(""); - expect(toQueryString(false)).toBe(""); - }); - - it("should handle empty objects", () => { - expect(toQueryString({})).toBe(""); - }); + describe("Basic functionality", () => { + const basicTests: BasicTestCase[] = [ + { description: "should return empty string for null", input: null, expected: "" }, + { description: "should return empty string for undefined", input: undefined, expected: "" }, + { description: "should return empty string for string primitive", input: "hello", expected: "" }, + { description: "should return empty string for number primitive", input: 42, expected: "" }, + { description: "should return empty string for true boolean", input: true, expected: "" }, + { description: "should return empty string for false boolean", input: false, expected: "" }, + { description: "should handle empty objects", input: {}, expected: "" }, + { + description: "should handle simple key-value pairs", + input: { name: "John", age: 30 }, + expected: "name=John&age=30", + }, + ]; - it("should handle simple key-value pairs", () => { - const obj = { name: "John", age: 30 }; - expect(toQueryString(obj)).toBe("name=John&age=30"); + basicTests.forEach(({ description, input, expected }) => { + it(description, () => { + expect(toQueryString(input)).toBe(expected); + }); }); }); describe("Array handling", () => { - it("should handle arrays with indices format (default)", () => { - const obj = { items: ["a", "b", "c"] }; - expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=b&items%5B2%5D=c"); - }); - - it("should handle arrays with repeat format", () => { - const obj = { items: ["a", "b", "c"] }; - expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe("items=a&items=b&items=c"); - }); + interface ArrayTestCase { + description: string; + input: any; + options?: { arrayFormat?: "repeat" | "indices" }; + expected: string; + } - it("should handle empty arrays", () => { - const obj = { items: [] }; - expect(toQueryString(obj)).toBe(""); - }); - - it("should handle arrays with mixed types", () => { - const obj = { mixed: ["string", 42, true, false] }; - expect(toQueryString(obj)).toBe("mixed%5B0%5D=string&mixed%5B1%5D=42&mixed%5B2%5D=true&mixed%5B3%5D=false"); - }); - - it("should handle arrays with objects", () => { - const obj = { users: [{ name: "John" }, { name: "Jane" }] }; - expect(toQueryString(obj)).toBe("users%5B0%5D%5Bname%5D=John&users%5B1%5D%5Bname%5D=Jane"); - }); + const arrayTests: ArrayTestCase[] = [ + { + description: "should handle arrays with indices format (default)", + input: { items: ["a", "b", "c"] }, + expected: "items%5B0%5D=a&items%5B1%5D=b&items%5B2%5D=c", + }, + { + description: "should handle arrays with repeat format", + input: { items: ["a", "b", "c"] }, + options: { arrayFormat: "repeat" }, + expected: "items=a&items=b&items=c", + }, + { + description: "should handle empty arrays", + input: { items: [] }, + expected: "", + }, + { + description: "should handle arrays with mixed types", + input: { mixed: ["string", 42, true, false] }, + expected: "mixed%5B0%5D=string&mixed%5B1%5D=42&mixed%5B2%5D=true&mixed%5B3%5D=false", + }, + { + description: "should handle arrays with objects", + input: { users: [{ name: "John" }, { name: "Jane" }] }, + expected: "users%5B0%5D%5Bname%5D=John&users%5B1%5D%5Bname%5D=Jane", + }, + { + description: "should handle arrays with objects in repeat format", + input: { users: [{ name: "John" }, { name: "Jane" }] }, + options: { arrayFormat: "repeat" }, + expected: "users%5Bname%5D=John&users%5Bname%5D=Jane", + }, + ]; - it("should handle arrays with objects in repeat format", () => { - const obj = { users: [{ name: "John" }, { name: "Jane" }] }; - expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe("users%5Bname%5D=John&users%5Bname%5D=Jane"); + arrayTests.forEach(({ description, input, options, expected }) => { + it(description, () => { + expect(toQueryString(input, options)).toBe(expected); + }); }); }); describe("Nested objects", () => { - it("should handle nested objects", () => { - const obj = { user: { name: "John", age: 30 } }; - expect(toQueryString(obj)).toBe("user%5Bname%5D=John&user%5Bage%5D=30"); - }); - - it("should handle deeply nested objects", () => { - const obj = { user: { profile: { name: "John", settings: { theme: "dark" } } } }; - expect(toQueryString(obj)).toBe( - "user%5Bprofile%5D%5Bname%5D=John&user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark", - ); - }); + const nestedTests: BasicTestCase[] = [ + { + description: "should handle nested objects", + input: { user: { name: "John", age: 30 } }, + expected: "user%5Bname%5D=John&user%5Bage%5D=30", + }, + { + description: "should handle deeply nested objects", + input: { user: { profile: { name: "John", settings: { theme: "dark" } } } }, + expected: "user%5Bprofile%5D%5Bname%5D=John&user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark", + }, + { + description: "should handle empty nested objects", + input: { user: {} }, + expected: "", + }, + ]; - it("should handle empty nested objects", () => { - const obj = { user: {} }; - expect(toQueryString(obj)).toBe(""); + nestedTests.forEach(({ description, input, expected }) => { + it(description, () => { + expect(toQueryString(input)).toBe(expected); + }); }); }); describe("Encoding", () => { - it("should encode by default", () => { - const obj = { name: "John Doe", email: "john@example.com" }; - expect(toQueryString(obj)).toBe("name=John%20Doe&email=john%40example.com"); - }); + interface EncodingTestCase { + description: string; + input: any; + options?: { encode?: boolean }; + expected: string; + } - it("should not encode when encode is false", () => { - const obj = { name: "John Doe", email: "john@example.com" }; - expect(toQueryString(obj, { encode: false })).toBe("name=John Doe&email=john@example.com"); - }); - - it("should encode special characters in keys", () => { - const obj = { "user name": "John", "email[primary]": "john@example.com" }; - expect(toQueryString(obj)).toBe("user%20name=John&email%5Bprimary%5D=john%40example.com"); - }); + const encodingTests: EncodingTestCase[] = [ + { + description: "should encode by default", + input: { name: "John Doe", email: "john@example.com" }, + expected: "name=John%20Doe&email=john%40example.com", + }, + { + description: "should not encode when encode is false", + input: { name: "John Doe", email: "john@example.com" }, + options: { encode: false }, + expected: "name=John Doe&email=john@example.com", + }, + { + description: "should encode special characters in keys", + input: { "user name": "John", "email[primary]": "john@example.com" }, + expected: "user%20name=John&email%5Bprimary%5D=john%40example.com", + }, + { + description: "should not encode special characters in keys when encode is false", + input: { "user name": "John", "email[primary]": "john@example.com" }, + options: { encode: false }, + expected: "user name=John&email[primary]=john@example.com", + }, + ]; - it("should not encode special characters in keys when encode is false", () => { - const obj = { "user name": "John", "email[primary]": "john@example.com" }; - expect(toQueryString(obj, { encode: false })).toBe("user name=John&email[primary]=john@example.com"); + encodingTests.forEach(({ description, input, options, expected }) => { + it(description, () => { + expect(toQueryString(input, options)).toBe(expected); + }); }); }); describe("Mixed scenarios", () => { - it("should handle complex nested structures", () => { - const obj = { - filters: { - status: ["active", "pending"], - category: { - type: "electronics", - subcategories: ["phones", "laptops"], + interface MixedTestCase { + description: string; + input: any; + options?: { arrayFormat?: "repeat" | "indices" }; + expected: string; + } + + const mixedTests: MixedTestCase[] = [ + { + description: "should handle complex nested structures", + input: { + filters: { + status: ["active", "pending"], + category: { + type: "electronics", + subcategories: ["phones", "laptops"], + }, }, + sort: { field: "name", direction: "asc" }, }, - sort: { field: "name", direction: "asc" }, - }; - expect(toQueryString(obj)).toBe( - "filters%5Bstatus%5D%5B0%5D=active&filters%5Bstatus%5D%5B1%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D%5B0%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D%5B1%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", - ); - }); - - it("should handle complex nested structures with repeat format", () => { - const obj = { - filters: { - status: ["active", "pending"], - category: { - type: "electronics", - subcategories: ["phones", "laptops"], + expected: + "filters%5Bstatus%5D%5B0%5D=active&filters%5Bstatus%5D%5B1%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D%5B0%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D%5B1%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", + }, + { + description: "should handle complex nested structures with repeat format", + input: { + filters: { + status: ["active", "pending"], + category: { + type: "electronics", + subcategories: ["phones", "laptops"], + }, }, + sort: { field: "name", direction: "asc" }, }, - sort: { field: "name", direction: "asc" }, - }; - expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe( - "filters%5Bstatus%5D=active&filters%5Bstatus%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", - ); - }); - - it("should handle arrays with null/undefined values", () => { - const obj = { items: ["a", null, "c", undefined, "e"] }; - expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c&items%5B4%5D=e"); - }); + options: { arrayFormat: "repeat" }, + expected: + "filters%5Bstatus%5D=active&filters%5Bstatus%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc", + }, + { + description: "should handle arrays with null/undefined values", + input: { items: ["a", null, "c", undefined, "e"] }, + expected: "items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c&items%5B4%5D=e", + }, + { + description: "should handle objects with null/undefined values", + input: { name: "John", age: null, email: undefined, active: true }, + expected: "name=John&age=&active=true", + }, + ]; - it("should handle objects with null/undefined values", () => { - const obj = { name: "John", age: null, email: undefined, active: true }; - expect(toQueryString(obj)).toBe("name=John&age=&active=true"); + mixedTests.forEach(({ description, input, options, expected }) => { + it(description, () => { + expect(toQueryString(input, options)).toBe(expected); + }); }); }); describe("Edge cases", () => { - it("should handle numeric keys", () => { - const obj = { "0": "zero", "1": "one" }; - expect(toQueryString(obj)).toBe("0=zero&1=one"); - }); - - it("should handle boolean values in objects", () => { - const obj = { enabled: true, disabled: false }; - expect(toQueryString(obj)).toBe("enabled=true&disabled=false"); - }); - - it("should handle empty strings", () => { - const obj = { name: "", description: "test" }; - expect(toQueryString(obj)).toBe("name=&description=test"); - }); + const edgeCaseTests: BasicTestCase[] = [ + { + description: "should handle numeric keys", + input: { "0": "zero", "1": "one" }, + expected: "0=zero&1=one", + }, + { + description: "should handle boolean values in objects", + input: { enabled: true, disabled: false }, + expected: "enabled=true&disabled=false", + }, + { + description: "should handle empty strings", + input: { name: "", description: "test" }, + expected: "name=&description=test", + }, + { + description: "should handle zero values", + input: { count: 0, price: 0.0 }, + expected: "count=0&price=0", + }, + { + description: "should handle arrays with empty strings", + input: { items: ["a", "", "c"] }, + expected: "items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c", + }, + ]; - it("should handle zero values", () => { - const obj = { count: 0, price: 0.0 }; - expect(toQueryString(obj)).toBe("count=0&price=0"); - }); - - it("should handle arrays with empty strings", () => { - const obj = { items: ["a", "", "c"] }; - expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c"); + edgeCaseTests.forEach(({ description, input, expected }) => { + it(description, () => { + expect(toQueryString(input)).toBe(expected); + }); }); }); describe("Options combinations", () => { - it("should respect both arrayFormat and encode options", () => { - const obj = { items: ["a & b", "c & d"] }; - expect(toQueryString(obj, { arrayFormat: "repeat", encode: false })).toBe("items=a & b&items=c & d"); - }); + interface OptionsTestCase { + description: string; + input: any; + options?: { arrayFormat?: "repeat" | "indices"; encode?: boolean }; + expected: string; + } - it("should use default options when none provided", () => { - const obj = { items: ["a", "b"] }; - expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=b"); - }); + const optionsTests: OptionsTestCase[] = [ + { + description: "should respect both arrayFormat and encode options", + input: { items: ["a & b", "c & d"] }, + options: { arrayFormat: "repeat", encode: false }, + expected: "items=a & b&items=c & d", + }, + { + description: "should use default options when none provided", + input: { items: ["a", "b"] }, + expected: "items%5B0%5D=a&items%5B1%5D=b", + }, + { + description: "should merge provided options with defaults", + input: { items: ["a", "b"], name: "John Doe" }, + options: { encode: false }, + expected: "items[0]=a&items[1]=b&name=John Doe", + }, + ]; - it("should merge provided options with defaults", () => { - const obj = { items: ["a", "b"], name: "John Doe" }; - expect(toQueryString(obj, { encode: false })).toBe("items[0]=a&items[1]=b&name=John Doe"); + optionsTests.forEach(({ description, input, options, expected }) => { + it(description, () => { + expect(toQueryString(input, options)).toBe(expected); + }); }); }); }); diff --git a/vitest.config.ts b/vitest.config.mts similarity index 85% rename from vitest.config.ts rename to vitest.config.mts index 677c585..ba2ec4f 100644 --- a/vitest.config.ts +++ b/vitest.config.mts @@ -10,6 +10,7 @@ export default defineConfig({ root: "./tests", include: ["**/*.test.{js,ts,jsx,tsx}"], exclude: ["wire/**"], + setupFiles: ["./setup.ts"], }, }, { @@ -18,7 +19,7 @@ export default defineConfig({ name: "wire", environment: "node", root: "./tests/wire", - setupFiles: ["../mock-server/setup.ts"], + setupFiles: ["../setup.ts", "../mock-server/setup.ts"], }, }, ],