From 1e51bebf61057dd84d10b0cf22f0db1425f5ffa1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 14:16:29 +0000 Subject: [PATCH 001/118] initial commit --- .devcontainer/devcontainer.json | 15 + .github/workflows/ci.yml | 88 + .gitignore | 10 + .prettierignore | 7 + .prettierrc.json | 7 + .stats.yml | 4 + Brewfile | 1 + CONTRIBUTING.md | 93 + LICENSE | 201 + README.md | 362 +- SECURITY.md | 23 + api.md | 124 + bin/publish-npm | 61 + eslint.config.mjs | 42 + examples/.keep | 4 + jest.config.ts | 23 + package.json | 69 + scripts/bootstrap | 18 + scripts/build | 51 + scripts/format | 12 + scripts/lint | 21 + scripts/mock | 41 + scripts/test | 56 + scripts/utils/attw-report.cjs | 24 + scripts/utils/check-is-in-git-install.sh | 9 + scripts/utils/check-version.cjs | 20 + scripts/utils/fix-index-exports.cjs | 17 + scripts/utils/git-swap.sh | 13 + scripts/utils/make-dist-package-json.cjs | 21 + scripts/utils/postprocess-files.cjs | 94 + scripts/utils/upload-artifact.sh | 25 + src/api-promise.ts | 2 + src/client.ts | 741 ++++ src/core/README.md | 3 + src/core/api-promise.ts | 92 + src/core/error.ts | 130 + src/core/resource.ts | 11 + src/core/uploads.ts | 2 + src/error.ts | 2 + src/index.ts | 22 + src/internal/README.md | 3 + src/internal/builtin-types.ts | 93 + src/internal/detect-platform.ts | 196 + src/internal/errors.ts | 33 + src/internal/headers.ts | 97 + src/internal/parse.ts | 50 + src/internal/request-options.ts | 91 + src/internal/shim-types.ts | 26 + src/internal/shims.ts | 107 + src/internal/to-file.ts | 154 + src/internal/types.ts | 95 + src/internal/uploads.ts | 187 + src/internal/utils.ts | 8 + src/internal/utils/base64.ts | 40 + src/internal/utils/bytes.ts | 32 + src/internal/utils/env.ts | 18 + src/internal/utils/log.ts | 126 + src/internal/utils/path.ts | 88 + src/internal/utils/sleep.ts | 3 + src/internal/utils/uuid.ts | 17 + src/internal/utils/values.ts | 105 + src/lib/.keep | 4 + src/resource.ts | 2 + src/resources.ts | 1 + src/resources/documents.ts | 3 + src/resources/documents/documents.ts | 15 + src/resources/documents/index.ts | 4 + src/resources/documents/v1.ts | 3 + src/resources/documents/v1/generate.ts | 118 + src/resources/documents/v1/index.ts | 10 + src/resources/documents/v1/v1.ts | 81 + src/resources/emails.ts | 3 + src/resources/emails/emails.ts | 20 + src/resources/emails/index.ts | 4 + src/resources/emails/v1.ts | 3 + src/resources/emails/v1/index.ts | 10 + src/resources/emails/v1/send.ts | 100 + src/resources/emails/v1/v1.ts | 101 + src/resources/index.ts | 6 + src/resources/pages.ts | 3 + src/resources/pages/index.ts | 4 + src/resources/pages/pages.ts | 15 + src/resources/pages/v1.ts | 37 + src/resources/project.ts | 3 + src/resources/project/index.ts | 4 + src/resources/project/project.ts | 15 + src/resources/project/v1.ts | 3 + src/resources/project/v1/api-keys.ts | 177 + src/resources/project/v1/domains.ts | 148 + src/resources/project/v1/index.ts | 30 + src/resources/project/v1/templates.ts | 176 + src/resources/project/v1/v1.ts | 112 + src/uploads.ts | 2 + src/version.ts | 1 + .../documents/v1/generate.test.ts | 60 + tests/api-resources/documents/v1/v1.test.ts | 22 + tests/api-resources/emails/v1/send.test.ts | 58 + tests/api-resources/emails/v1/v1.test.ts | 39 + tests/api-resources/pages/v1.test.ts | 27 + .../api-resources/project/v1/api-keys.test.ts | 87 + .../api-resources/project/v1/domains.test.ts | 83 + .../project/v1/templates.test.ts | 91 + tests/api-resources/project/v1/v1.test.ts | 22 + tests/base64.test.ts | 80 + tests/buildHeaders.test.ts | 88 + tests/form.test.ts | 85 + tests/index.test.ts | 722 ++++ tests/path.test.ts | 462 +++ tests/stringifyQuery.test.ts | 29 + tests/uploads.test.ts | 107 + tsc-multi.json | 15 + tsconfig.build.json | 18 + tsconfig.deno.json | 15 + tsconfig.dist-src.json | 11 + tsconfig.json | 38 + yarn.lock | 3500 +++++++++++++++++ 116 files changed, 11006 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 .stats.yml create mode 100644 Brewfile create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 api.md create mode 100644 bin/publish-npm create mode 100644 eslint.config.mjs create mode 100644 examples/.keep create mode 100644 jest.config.ts create mode 100644 package.json create mode 100755 scripts/bootstrap create mode 100755 scripts/build create mode 100755 scripts/format create mode 100755 scripts/lint create mode 100755 scripts/mock create mode 100755 scripts/test create mode 100644 scripts/utils/attw-report.cjs create mode 100755 scripts/utils/check-is-in-git-install.sh create mode 100644 scripts/utils/check-version.cjs create mode 100644 scripts/utils/fix-index-exports.cjs create mode 100755 scripts/utils/git-swap.sh create mode 100644 scripts/utils/make-dist-package-json.cjs create mode 100644 scripts/utils/postprocess-files.cjs create mode 100755 scripts/utils/upload-artifact.sh create mode 100644 src/api-promise.ts create mode 100644 src/client.ts create mode 100644 src/core/README.md create mode 100644 src/core/api-promise.ts create mode 100644 src/core/error.ts create mode 100644 src/core/resource.ts create mode 100644 src/core/uploads.ts create mode 100644 src/error.ts create mode 100644 src/index.ts create mode 100644 src/internal/README.md create mode 100644 src/internal/builtin-types.ts create mode 100644 src/internal/detect-platform.ts create mode 100644 src/internal/errors.ts create mode 100644 src/internal/headers.ts create mode 100644 src/internal/parse.ts create mode 100644 src/internal/request-options.ts create mode 100644 src/internal/shim-types.ts create mode 100644 src/internal/shims.ts create mode 100644 src/internal/to-file.ts create mode 100644 src/internal/types.ts create mode 100644 src/internal/uploads.ts create mode 100644 src/internal/utils.ts create mode 100644 src/internal/utils/base64.ts create mode 100644 src/internal/utils/bytes.ts create mode 100644 src/internal/utils/env.ts create mode 100644 src/internal/utils/log.ts create mode 100644 src/internal/utils/path.ts create mode 100644 src/internal/utils/sleep.ts create mode 100644 src/internal/utils/uuid.ts create mode 100644 src/internal/utils/values.ts create mode 100644 src/lib/.keep create mode 100644 src/resource.ts create mode 100644 src/resources.ts create mode 100644 src/resources/documents.ts create mode 100644 src/resources/documents/documents.ts create mode 100644 src/resources/documents/index.ts create mode 100644 src/resources/documents/v1.ts create mode 100644 src/resources/documents/v1/generate.ts create mode 100644 src/resources/documents/v1/index.ts create mode 100644 src/resources/documents/v1/v1.ts create mode 100644 src/resources/emails.ts create mode 100644 src/resources/emails/emails.ts create mode 100644 src/resources/emails/index.ts create mode 100644 src/resources/emails/v1.ts create mode 100644 src/resources/emails/v1/index.ts create mode 100644 src/resources/emails/v1/send.ts create mode 100644 src/resources/emails/v1/v1.ts create mode 100644 src/resources/index.ts create mode 100644 src/resources/pages.ts create mode 100644 src/resources/pages/index.ts create mode 100644 src/resources/pages/pages.ts create mode 100644 src/resources/pages/v1.ts create mode 100644 src/resources/project.ts create mode 100644 src/resources/project/index.ts create mode 100644 src/resources/project/project.ts create mode 100644 src/resources/project/v1.ts create mode 100644 src/resources/project/v1/api-keys.ts create mode 100644 src/resources/project/v1/domains.ts create mode 100644 src/resources/project/v1/index.ts create mode 100644 src/resources/project/v1/templates.ts create mode 100644 src/resources/project/v1/v1.ts create mode 100644 src/uploads.ts create mode 100644 src/version.ts create mode 100644 tests/api-resources/documents/v1/generate.test.ts create mode 100644 tests/api-resources/documents/v1/v1.test.ts create mode 100644 tests/api-resources/emails/v1/send.test.ts create mode 100644 tests/api-resources/emails/v1/v1.test.ts create mode 100644 tests/api-resources/pages/v1.test.ts create mode 100644 tests/api-resources/project/v1/api-keys.test.ts create mode 100644 tests/api-resources/project/v1/domains.test.ts create mode 100644 tests/api-resources/project/v1/templates.test.ts create mode 100644 tests/api-resources/project/v1/v1.test.ts create mode 100644 tests/base64.test.ts create mode 100644 tests/buildHeaders.test.ts create mode 100644 tests/form.test.ts create mode 100644 tests/index.test.ts create mode 100644 tests/path.test.ts create mode 100644 tests/stringifyQuery.test.ts create mode 100644 tests/uploads.test.ts create mode 100644 tsc-multi.json create mode 100644 tsconfig.build.json create mode 100644 tsconfig.deno.json create mode 100644 tsconfig.dist-src.json create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..43fd5a7 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,15 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Development", + "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", + "features": { + "ghcr.io/devcontainers/features/node:1": {} + }, + "postCreateCommand": "yarn install", + "customizations": { + "vscode": { + "extensions": ["esbenp.prettier-vscode"] + } + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d9718f6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,88 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 10 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Check types + run: ./scripts/lint + + build: + timeout-minutes: 5 + name: build + runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Check build + run: ./scripts/build + + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/unlayer-typescript' + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + if: github.repository == 'stainless-sdks/unlayer-typescript' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh + test: + timeout-minutes: 10 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Run tests + run: ./scripts/test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d98d51a --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.prism.log +node_modules +yarn-error.log +codegen.log +Brewfile.lock.json +dist +dist-deno +/*.tgz +.idea/ + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3548c5a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +CHANGELOG.md +/ecosystem-tests/*/** +/node_modules +/deno + +# don't format tsc output, will break source maps +/dist diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..af75ada --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "arrowParens": "always", + "experimentalTernaries": true, + "printWidth": 110, + "singleQuote": true, + "trailingComma": "all" +} diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 0000000..c591c51 --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 24 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4183a0cf62e19c37b104df3fdc7bdc44ddbb9cb35e2886e2b9877c056107c8a2.yml +openapi_spec_hash: 34076f7e9e1bc890db0b5b6aa8affd79 +config_hash: d8e1c89a13d504eed8a5a07186ba17ea diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..e4feee6 --- /dev/null +++ b/Brewfile @@ -0,0 +1 @@ +brew "node" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c466c26 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +## Setting up the environment + +This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install). +Other package managers may work but are not officially supported for development. + +To set up the repository, run: + +```sh +$ yarn +$ yarn build +``` + +This will install all the required dependencies and build output files to `dist/`. + +## Modifying/Adding code + +Most of the SDK is generated code. Modifications to code will be persisted between generations, but may +result in merge conflicts between manual patches and changes from the generator. The generator will never +modify the contents of the `src/lib/` and `examples/` directories. + +## Adding and running examples + +All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. + +```ts +// add an example to examples/.ts + +#!/usr/bin/env -S npm run tsn -T +… +``` + +```sh +$ chmod +x examples/.ts +# run the example against your api +$ yarn tsn -T examples/.ts +``` + +## Using the repository from source + +If you’d like to use the repository from source, you can either install from git or link to a cloned repository: + +To install via git: + +```sh +$ npm install git+ssh://git@github.com:stainless-sdks/unlayer-typescript.git +``` + +Alternatively, to link a local copy of the repo: + +```sh +# Clone +$ git clone https://www.github.com/stainless-sdks/unlayer-typescript +$ cd unlayer-typescript + +# With yarn +$ yarn link +$ cd ../my-package +$ yarn link unlayer + +# With pnpm +$ pnpm link --global +$ cd ../my-package +$ pnpm link -—global unlayer +``` + +## Running tests + +Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. + +```sh +$ npx prism mock path/to/your/openapi.yml +``` + +```sh +$ yarn run test +``` + +## Linting and formatting + +This repository uses [prettier](https://www.npmjs.com/package/prettier) and +[eslint](https://www.npmjs.com/package/eslint) to format the code in the repository. + +To lint: + +```sh +$ yarn lint +``` + +To format and fix all lint issues automatically: + +```sh +$ yarn fix +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..42d0669 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 Unlayer + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 2ecc170..804ca7f 100644 --- a/README.md +++ b/README.md @@ -1 +1,361 @@ -# unlayer-typescript \ No newline at end of file +# Unlayer TypeScript API Library + +[![NPM version]()](https://npmjs.org/package/unlayer) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/unlayer) + +This library provides convenient access to the Unlayer REST API from server-side TypeScript or JavaScript. + +The full API of this library can be found in [api.md](api.md). + +It is generated with [Stainless](https://www.stainless.com/). + +## Installation + +```sh +npm install git+ssh://git@github.com:stainless-sdks/unlayer-typescript.git +``` + +> [!NOTE] +> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npm install unlayer` + +## Usage + +The full API of this library can be found in [api.md](api.md). + + +```js +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted +}); + +const apiKeys = await client.project.v1.apiKeys.list(); + +console.log(apiKeys.data); +``` + +### Request & Response types + +This library includes TypeScript definitions for all request params and response fields. You may import and use them like so: + + +```ts +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted +}); + +const apiKeys: Unlayer.Project.V1.APIKeyListResponse = await client.project.v1.apiKeys.list(); +``` + +Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. + +## Handling errors + +When the library is unable to connect to the API, +or if the API returns a non-success status code (i.e., 4xx or 5xx response), +a subclass of `APIError` will be thrown: + + +```ts +const apiKeys = await client.project.v1.apiKeys.list().catch(async (err) => { + if (err instanceof Unlayer.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } +}); +``` + +Error codes are as follows: + +| Status Code | Error Type | +| ----------- | -------------------------- | +| 400 | `BadRequestError` | +| 401 | `AuthenticationError` | +| 403 | `PermissionDeniedError` | +| 404 | `NotFoundError` | +| 422 | `UnprocessableEntityError` | +| 429 | `RateLimitError` | +| >=500 | `InternalServerError` | +| N/A | `APIConnectionError` | + +### Retries + +Certain errors will be automatically retried 2 times by default, with a short exponential backoff. +Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, +429 Rate Limit, and >=500 Internal errors will all be retried by default. + +You can use the `maxRetries` option to configure or disable this: + + +```js +// Configure the default for all requests: +const client = new Unlayer({ + maxRetries: 0, // default is 2 +}); + +// Or, configure per-request: +await client.project.v1.apiKeys.list({ + maxRetries: 5, +}); +``` + +### Timeouts + +Requests time out after 1 minute by default. You can configure this with a `timeout` option: + + +```ts +// Configure the default for all requests: +const client = new Unlayer({ + timeout: 20 * 1000, // 20 seconds (default is 1 minute) +}); + +// Override per-request: +await client.project.v1.apiKeys.list({ + timeout: 5 * 1000, +}); +``` + +On timeout, an `APIConnectionTimeoutError` is thrown. + +Note that requests which time out will be [retried twice by default](#retries). + +## Advanced Usage + +### Accessing raw Response data (e.g., headers) + +The "raw" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return. +This method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic. + +You can also use the `.withResponse()` method to get the raw `Response` along with the parsed data. +Unlike `.asResponse()` this method consumes the body, returning once it is parsed. + + +```ts +const client = new Unlayer(); + +const response = await client.project.v1.apiKeys.list().asResponse(); +console.log(response.headers.get('X-My-Header')); +console.log(response.statusText); // access the underlying Response object + +const { data: apiKeys, response: raw } = await client.project.v1.apiKeys.list().withResponse(); +console.log(raw.headers.get('X-My-Header')); +console.log(apiKeys.data); +``` + +### Logging + +> [!IMPORTANT] +> All log messages are intended for debugging only. The format and content of log messages +> may change between releases. + +#### Log levels + +The log level can be configured in two ways: + +1. Via the `UNLAYER_LOG` environment variable +2. Using the `logLevel` client option (overrides the environment variable if set) + +```ts +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + logLevel: 'debug', // Show all log messages +}); +``` + +Available log levels, from most to least verbose: + +- `'debug'` - Show debug messages, info, warnings, and errors +- `'info'` - Show info messages, warnings, and errors +- `'warn'` - Show warnings and errors (default) +- `'error'` - Show only errors +- `'off'` - Disable all logging + +At the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies. +Some authentication-related headers are redacted, but sensitive data in request and response bodies +may still be visible. + +#### Custom logger + +By default, this library logs to `globalThis.console`. You can also provide a custom logger. +Most logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue. + +When providing a custom logger, the `logLevel` option still controls which messages are emitted, messages +below the configured level will not be sent to your logger. + +```ts +import Unlayer from 'unlayer'; +import pino from 'pino'; + +const logger = pino(); + +const client = new Unlayer({ + logger: logger.child({ name: 'Unlayer' }), + logLevel: 'debug', // Send all messages to pino, allowing it to filter +}); +``` + +### Making custom/undocumented requests + +This library is typed for convenient access to the documented API. If you need to access undocumented +endpoints, params, or response properties, the library can still be used. + +#### Undocumented endpoints + +To make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs. +Options on the client, such as retries, will be respected when making these requests. + +```ts +await client.post('/some/path', { + body: { some_prop: 'foo' }, + query: { some_query_arg: 'bar' }, +}); +``` + +#### Undocumented request params + +To make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented +parameter. This library doesn't validate at runtime that the request matches the type, so any extra values you +send will be sent as-is. + +```ts +client.project.v1.apiKeys.list({ + // ... + // @ts-expect-error baz is not yet public + baz: 'undocumented option', +}); +``` + +For requests with the `GET` verb, any extra params will be in the query, all other requests will send the +extra param in the body. + +If you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request +options. + +#### Undocumented response properties + +To access undocumented response properties, you may access the response object with `// @ts-expect-error` on +the response object, or cast the response object to the requisite type. Like the request params, we do not +validate or strip extra properties from the response from the API. + +### Customizing the fetch client + +By default, this library expects a global `fetch` function is defined. + +If you want to use a different `fetch` function, you can either polyfill the global: + +```ts +import fetch from 'my-fetch'; + +globalThis.fetch = fetch; +``` + +Or pass it to the client: + +```ts +import Unlayer from 'unlayer'; +import fetch from 'my-fetch'; + +const client = new Unlayer({ fetch }); +``` + +### Fetch options + +If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) + +```ts +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + fetchOptions: { + // `RequestInit` options + }, +}); +``` + +#### Configuring proxies + +To modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy +options to requests: + + **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] + +```ts +import Unlayer from 'unlayer'; +import * as undici from 'undici'; + +const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); +const client = new Unlayer({ + fetchOptions: { + dispatcher: proxyAgent, + }, +}); +``` + + **Bun** [[docs](https://bun.sh/guides/http/proxy)] + +```ts +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + fetchOptions: { + proxy: 'http://localhost:8888', + }, +}); +``` + + **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] + +```ts +import Unlayer from 'npm:unlayer'; + +const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); +const client = new Unlayer({ + fetchOptions: { + client: httpClient, + }, +}); +``` + +## Frequently Asked Questions + +## Semantic versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: + +1. Changes that only affect static types, without breaking runtime behavior. +2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +3. Changes that we do not expect to impact the vast majority of users in practice. + +We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. + +We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/unlayer-typescript/issues) with questions, bugs, or suggestions. + +## Requirements + +TypeScript >= 4.9 is supported. + +The following runtimes are supported: + +- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more) +- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions. +- Deno v1.28.0 or higher. +- Bun 1.0 or later. +- Cloudflare Workers. +- Vercel Edge Runtime. +- Jest 28 or greater with the `"node"` environment (`"jsdom"` is not supported at this time). +- Nitro v2.6 or greater. + +Note that React Native is not supported at this time. + +If you are interested in other runtime environments, please open or upvote an issue on GitHub. + +## Contributing + +See [the contributing documentation](./CONTRIBUTING.md). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..d4bb777 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Unlayer, please follow the respective company's security reporting guidelines. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/api.md b/api.md new file mode 100644 index 0000000..b51b2e4 --- /dev/null +++ b/api.md @@ -0,0 +1,124 @@ +# Project + +## V1 + +Types: + +- V1GetCurrentResponse + +Methods: + +- client.project.v1.getCurrent() -> V1GetCurrentResponse + +### APIKeys + +Types: + +- APIKeyCreateResponse +- APIKeyRetrieveResponse +- APIKeyUpdateResponse +- APIKeyListResponse + +Methods: + +- client.project.v1.apiKeys.create({ ...params }) -> APIKeyCreateResponse +- client.project.v1.apiKeys.retrieve(id) -> APIKeyRetrieveResponse +- client.project.v1.apiKeys.update(id, { ...params }) -> APIKeyUpdateResponse +- client.project.v1.apiKeys.list() -> APIKeyListResponse +- client.project.v1.apiKeys.delete(id) -> void + +### Domains + +Types: + +- DomainCreateResponse +- DomainRetrieveResponse +- DomainUpdateResponse +- DomainListResponse + +Methods: + +- client.project.v1.domains.create({ ...params }) -> DomainCreateResponse +- client.project.v1.domains.retrieve(id) -> DomainRetrieveResponse +- client.project.v1.domains.update(id, { ...params }) -> DomainUpdateResponse +- client.project.v1.domains.list() -> DomainListResponse +- client.project.v1.domains.delete(id) -> void + +### Templates + +Types: + +- TemplateCreateResponse +- TemplateRetrieveResponse +- TemplateUpdateResponse +- TemplateListResponse + +Methods: + +- client.project.v1.templates.create({ ...params }) -> TemplateCreateResponse +- client.project.v1.templates.retrieve(id) -> TemplateRetrieveResponse +- client.project.v1.templates.update(id, { ...params }) -> TemplateUpdateResponse +- client.project.v1.templates.list() -> TemplateListResponse +- client.project.v1.templates.delete(id) -> void + +# Documents + +## V1 + +Types: + +- V1RetrieveResponse + +Methods: + +- client.documents.v1.retrieve(id) -> V1RetrieveResponse + +### Generate + +Types: + +- GenerateCreateResponse +- GenerateCreateFromTemplateResponse + +Methods: + +- client.documents.v1.generate.create({ ...params }) -> GenerateCreateResponse +- client.documents.v1.generate.createFromTemplate({ ...params }) -> GenerateCreateFromTemplateResponse + +# Emails + +## V1 + +Types: + +- V1RetrieveResponse +- V1RenderResponse + +Methods: + +- client.emails.v1.retrieve(id) -> V1RetrieveResponse +- client.emails.v1.render({ ...params }) -> V1RenderResponse + +### Send + +Types: + +- SendSendResponse +- SendSendFromTemplateResponse + +Methods: + +- client.emails.v1.send.send({ ...params }) -> SendSendResponse +- client.emails.v1.send.sendFromTemplate({ ...params }) -> SendSendFromTemplateResponse + +# Pages + +## V1 + +Types: + +- V1RenderResponse + +Methods: + +- client.pages.v1.render({ ...params }) -> V1RenderResponse diff --git a/bin/publish-npm b/bin/publish-npm new file mode 100644 index 0000000..45e8aa8 --- /dev/null +++ b/bin/publish-npm @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -eux + +npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" + +yarn build +cd dist + +# Get package name and version from package.json +PACKAGE_NAME="$(jq -r -e '.name' ./package.json)" +VERSION="$(jq -r -e '.version' ./package.json)" + +# Get latest version from npm +# +# If the package doesn't exist, npm will return: +# { +# "error": { +# "code": "E404", +# "summary": "Unpublished on 2025-06-05T09:54:53.528Z", +# "detail": "'the_package' is not in this registry..." +# } +# } +NPM_INFO="$(npm view "$PACKAGE_NAME" version --json 2>/dev/null || true)" + +# Check if we got an E404 error +if echo "$NPM_INFO" | jq -e '.error.code == "E404"' > /dev/null 2>&1; then + # Package doesn't exist yet, no last version + LAST_VERSION="" +elif echo "$NPM_INFO" | jq -e '.error' > /dev/null 2>&1; then + # Report other errors + echo "ERROR: npm returned unexpected data:" + echo "$NPM_INFO" + exit 1 +else + # Success - get the version + LAST_VERSION=$(echo "$NPM_INFO" | jq -r '.') # strip quotes +fi + +# Check if current version is pre-release (e.g. alpha / beta / rc) +CURRENT_IS_PRERELEASE=false +if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then + CURRENT_IS_PRERELEASE=true + CURRENT_TAG="${BASH_REMATCH[1]}" +fi + +# Check if last version is a stable release +LAST_IS_STABLE_RELEASE=true +if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then + LAST_IS_STABLE_RELEASE=false +fi + +# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. +if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then + TAG="$CURRENT_TAG" +else + TAG="latest" +fi + +# Publish with the appropriate tag +yarn publish --tag "$TAG" diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..be1e121 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,42 @@ +// @ts-check +import tseslint from 'typescript-eslint'; +import unusedImports from 'eslint-plugin-unused-imports'; +import prettier from 'eslint-plugin-prettier'; + +export default tseslint.config( + { + languageOptions: { + parser: tseslint.parser, + parserOptions: { sourceType: 'module' }, + }, + files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.js', '**/*.mjs', '**/*.cjs'], + ignores: ['dist/'], + plugins: { + '@typescript-eslint': tseslint.plugin, + 'unused-imports': unusedImports, + prettier, + }, + rules: { + 'no-unused-vars': 'off', + 'prettier/prettier': 'error', + 'unused-imports/no-unused-imports': 'error', + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + regex: '^unlayer(/.*)?', + message: 'Use a relative import, not a package import.', + }, + ], + }, + ], + }, + }, + { + files: ['tests/**', 'examples/**'], + rules: { + 'no-restricted-imports': 'off', + }, + }, +); diff --git a/examples/.keep b/examples/.keep new file mode 100644 index 0000000..0651c89 --- /dev/null +++ b/examples/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store example files demonstrating usage of this SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..0f5ccc3 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,23 @@ +import type { JestConfigWithTsJest } from 'ts-jest'; + +const config: JestConfigWithTsJest = { + preset: 'ts-jest/presets/default-esm', + testEnvironment: 'node', + transform: { + '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], + }, + moduleNameMapper: { + '^unlayer$': '/src/index.ts', + '^unlayer/(.*)$': '/src/$1', + }, + modulePathIgnorePatterns: [ + '/ecosystem-tests/', + '/dist/', + '/deno/', + '/deno_tests/', + '/packages/', + ], + testPathIgnorePatterns: ['scripts'], +}; + +export default config; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ae5d4b1 --- /dev/null +++ b/package.json @@ -0,0 +1,69 @@ +{ + "name": "unlayer", + "version": "0.0.1", + "description": "The official TypeScript library for the Unlayer API", + "author": "Unlayer <>", + "types": "dist/index.d.ts", + "main": "dist/index.js", + "type": "commonjs", + "repository": "github:stainless-sdks/unlayer-typescript", + "license": "Apache-2.0", + "packageManager": "yarn@1.22.22", + "files": [ + "**/*" + ], + "private": false, + "publishConfig": { + "access": "public" + }, + "scripts": { + "test": "./scripts/test", + "build": "./scripts/build", + "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", + "format": "./scripts/format", + "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", + "tsn": "ts-node -r tsconfig-paths/register", + "lint": "./scripts/lint", + "fix": "./scripts/format" + }, + "dependencies": {}, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.0", + "@swc/core": "^1.3.102", + "@swc/jest": "^0.2.29", + "@types/jest": "^29.4.0", + "@types/node": "^20.17.6", + "@typescript-eslint/eslint-plugin": "8.31.1", + "@typescript-eslint/parser": "8.31.1", + "eslint": "^9.20.1", + "eslint-plugin-prettier": "^5.4.1", + "eslint-plugin-unused-imports": "^4.1.4", + "iconv-lite": "^0.6.3", + "jest": "^29.4.0", + "prettier": "^3.0.0", + "publint": "^0.2.12", + "ts-jest": "^29.1.0", + "ts-node": "^10.5.0", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsconfig-paths": "^4.0.0", + "tslib": "^2.8.1", + "typescript": "5.8.3", + "typescript-eslint": "8.31.1" + }, + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js" + }, + "./*.mjs": { + "default": "./dist/*.mjs" + }, + "./*.js": { + "default": "./dist/*.js" + }, + "./*": { + "import": "./dist/*.mjs", + "require": "./dist/*.js" + } + } +} diff --git a/scripts/bootstrap b/scripts/bootstrap new file mode 100755 index 0000000..062a034 --- /dev/null +++ b/scripts/bootstrap @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then + brew bundle check >/dev/null 2>&1 || { + echo "==> Installing Homebrew dependencies…" + brew bundle + } +fi + +echo "==> Installing Node dependencies…" + +PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") + +$PACKAGE_MANAGER install "$@" diff --git a/scripts/build b/scripts/build new file mode 100755 index 0000000..24c3b0d --- /dev/null +++ b/scripts/build @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -exuo pipefail + +cd "$(dirname "$0")/.." + +node scripts/utils/check-version.cjs + +# Build into dist and will publish the package from there, +# so that src/resources/foo.ts becomes /resources/foo.js +# This way importing from `"unlayer/resources/foo"` works +# even with `"moduleResolution": "node"` + +rm -rf dist; mkdir dist +# Copy src to dist/src and build from dist/src into dist, so that +# the source map for index.js.map will refer to ./src/index.ts etc +cp -rp src README.md dist +for file in LICENSE CHANGELOG.md; do + if [ -e "${file}" ]; then cp "${file}" dist; fi +done +if [ -e "bin/cli" ]; then + mkdir -p dist/bin + cp -p "bin/cli" dist/bin/; +fi +if [ -e "bin/migration-config.json" ]; then + mkdir -p dist/bin + cp -p "bin/migration-config.json" dist/bin/; +fi +# this converts the export map paths for the dist directory +# and does a few other minor things +node scripts/utils/make-dist-package-json.cjs > dist/package.json + +# build to .js/.mjs/.d.ts files +./node_modules/.bin/tsc-multi +# we need to patch index.js so that `new module.exports()` works for cjs backwards +# compat. No way to get that from index.ts because it would cause compile errors +# when building .mjs +node scripts/utils/fix-index-exports.cjs +cp tsconfig.dist-src.json dist/src/tsconfig.json + +node scripts/utils/postprocess-files.cjs + +# make sure that nothing crashes when we require the output CJS or +# import the output ESM +(cd dist && node -e 'require("unlayer")') +(cd dist && node -e 'import("unlayer")' --input-type=module) + +if [ -e ./scripts/build-deno ] +then + ./scripts/build-deno +fi diff --git a/scripts/format b/scripts/format new file mode 100755 index 0000000..7a75640 --- /dev/null +++ b/scripts/format @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running eslint --fix" +./node_modules/.bin/eslint --fix . + +echo "==> Running prettier --write" +# format things eslint didn't +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 0000000..3ffb78a --- /dev/null +++ b/scripts/lint @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running eslint" +./node_modules/.bin/eslint . + +echo "==> Building" +./scripts/build + +echo "==> Checking types" +./node_modules/typescript/bin/tsc + +echo "==> Running Are The Types Wrong?" +./node_modules/.bin/attw --pack dist -f json >.attw.json || true +node scripts/utils/attw-report.cjs + +echo "==> Running publint" +./node_modules/.bin/publint dist diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 0000000..0b28f6e --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + echo -n "." + sleep 0.1 + done + + if grep -q "✖ fatal" ".prism.log"; then + cat .prism.log + exit 1 + fi + + echo +else + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 0000000..7bce051 --- /dev/null +++ b/scripts/test @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +function prism_is_running() { + curl --silent "http://localhost:4010" >/dev/null 2>&1 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +fi + +if is_overriding_api_base_url ; then + echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" + echo +elif ! prism_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" + echo -e "running against your OpenAPI spec." + echo + echo -e "To run the server, pass in the path or url of your OpenAPI" + echo -e "spec to the prism command:" + echo + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +echo "==> Running tests" +./node_modules/.bin/jest "$@" diff --git a/scripts/utils/attw-report.cjs b/scripts/utils/attw-report.cjs new file mode 100644 index 0000000..b3477c0 --- /dev/null +++ b/scripts/utils/attw-report.cjs @@ -0,0 +1,24 @@ +const fs = require('fs'); +const problems = Object.values(JSON.parse(fs.readFileSync('.attw.json', 'utf-8')).problems) + .flat() + .filter( + (problem) => + !( + // This is intentional, if the user specifies .mjs they get ESM. + ( + (problem.kind === 'CJSResolvesToESM' && problem.entrypoint.endsWith('.mjs')) || + // This is intentional for backwards compat reasons. + (problem.kind === 'MissingExportEquals' && problem.implementationFileName.endsWith('/index.js')) || + // this is intentional, we deliberately attempt to import types that may not exist from parent node_modules + // folders to better support various runtimes without triggering automatic type acquisition. + (problem.kind === 'InternalResolutionError' && problem.moduleSpecifier.includes('node_modules')) + ) + ), + ); +fs.unlinkSync('.attw.json'); +if (problems.length) { + process.stdout.write('The types are wrong!\n' + JSON.stringify(problems, null, 2) + '\n'); + process.exitCode = 1; +} else { + process.stdout.write('Types ok!\n'); +} diff --git a/scripts/utils/check-is-in-git-install.sh b/scripts/utils/check-is-in-git-install.sh new file mode 100755 index 0000000..1354eb4 --- /dev/null +++ b/scripts/utils/check-is-in-git-install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Check if you happen to call prepare for a repository that's already in node_modules. +[ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] || +# The name of the containing directory that 'npm` uses, which looks like +# $HOME/.npm/_cacache/git-cloneXXXXXX +[ "$(basename "$(dirname "$PWD")")" = 'tmp' ] || +# The name of the containing directory that 'yarn` uses, which looks like +# $(yarn cache dir)/.tmp/XXXXX +[ "$(basename "$(dirname "$PWD")")" = '.tmp' ] diff --git a/scripts/utils/check-version.cjs b/scripts/utils/check-version.cjs new file mode 100644 index 0000000..86c56df --- /dev/null +++ b/scripts/utils/check-version.cjs @@ -0,0 +1,20 @@ +const fs = require('fs'); +const path = require('path'); + +const main = () => { + const pkg = require('../../package.json'); + const version = pkg['version']; + if (!version) throw 'The version property is not set in the package.json file'; + if (typeof version !== 'string') { + throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`; + } + + const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts'); + const contents = fs.readFileSync(versionFile, 'utf8'); + const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`); + fs.writeFileSync(versionFile, output); +}; + +if (require.main === module) { + main(); +} diff --git a/scripts/utils/fix-index-exports.cjs b/scripts/utils/fix-index-exports.cjs new file mode 100644 index 0000000..e5e10b3 --- /dev/null +++ b/scripts/utils/fix-index-exports.cjs @@ -0,0 +1,17 @@ +const fs = require('fs'); +const path = require('path'); + +const indexJs = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH'], 'index.js') + : path.resolve(__dirname, '..', '..', 'dist', 'index.js'); + +let before = fs.readFileSync(indexJs, 'utf8'); +let after = before.replace( + /^(\s*Object\.defineProperty\s*\(exports,\s*["']__esModule["'].+)$/m, + `exports = module.exports = function (...args) { + return new exports.default(...args) + } + $1`.replace(/^ /gm, ''), +); +fs.writeFileSync(indexJs, after, 'utf8'); diff --git a/scripts/utils/git-swap.sh b/scripts/utils/git-swap.sh new file mode 100755 index 0000000..79d1888 --- /dev/null +++ b/scripts/utils/git-swap.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -exuo pipefail +# the package is published to NPM from ./dist +# we want the final file structure for git installs to match the npm installs, so we + +# delete everything except ./dist and ./node_modules +find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' + + +# move everything from ./dist to . +mv dist/* . + +# delete the now-empty ./dist +rmdir dist diff --git a/scripts/utils/make-dist-package-json.cjs b/scripts/utils/make-dist-package-json.cjs new file mode 100644 index 0000000..7c24f56 --- /dev/null +++ b/scripts/utils/make-dist-package-json.cjs @@ -0,0 +1,21 @@ +const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json'); + +function processExportMap(m) { + for (const key in m) { + const value = m[key]; + if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './'); + else processExportMap(value); + } +} +processExportMap(pkgJson.exports); + +for (const key of ['types', 'main', 'module']) { + if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './'); +} + +delete pkgJson.devDependencies; +delete pkgJson.scripts.prepack; +delete pkgJson.scripts.prepublishOnly; +delete pkgJson.scripts.prepare; + +console.log(JSON.stringify(pkgJson, null, 2)); diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs new file mode 100644 index 0000000..deae575 --- /dev/null +++ b/scripts/utils/postprocess-files.cjs @@ -0,0 +1,94 @@ +// @ts-check +const fs = require('fs'); +const path = require('path'); + +const distDir = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH']) + : path.resolve(__dirname, '..', '..', 'dist'); + +async function* walk(dir) { + for await (const d of await fs.promises.opendir(dir)) { + const entry = path.join(dir, d.name); + if (d.isDirectory()) yield* walk(entry); + else if (d.isFile()) yield entry; + } +} + +async function postprocess() { + for await (const file of walk(distDir)) { + if (!/(\.d)?[cm]?ts$/.test(file)) continue; + + const code = await fs.promises.readFile(file, 'utf8'); + + // strip out lib="dom", types="node", and types="react" references; these + // are needed at build time, but would pollute the user's TS environment + const transformed = code.replace( + /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', + ); + + if (transformed !== code) { + console.error(`wrote ${path.relative(process.cwd(), file)}`); + await fs.promises.writeFile(file, transformed, 'utf8'); + } + } + + const newExports = { + '.': { + require: { + types: './index.d.ts', + default: './index.js', + }, + types: './index.d.mts', + default: './index.mjs', + }, + }; + + for (const entry of await fs.promises.readdir(distDir, { withFileTypes: true })) { + if (entry.isDirectory() && entry.name !== 'src' && entry.name !== 'internal' && entry.name !== 'bin') { + const subpath = './' + entry.name; + newExports[subpath + '/*.mjs'] = { + default: subpath + '/*.mjs', + }; + newExports[subpath + '/*.js'] = { + default: subpath + '/*.js', + }; + newExports[subpath + '/*'] = { + import: subpath + '/*.mjs', + require: subpath + '/*.js', + }; + } else if (entry.isFile() && /\.[cm]?js$/.test(entry.name)) { + const { name, ext } = path.parse(entry.name); + const subpathWithoutExt = './' + name; + const subpath = './' + entry.name; + newExports[subpathWithoutExt] ||= { import: undefined, require: undefined }; + const isModule = ext[1] === 'm'; + if (isModule) { + newExports[subpathWithoutExt].import = subpath; + } else { + newExports[subpathWithoutExt].require = subpath; + } + newExports[subpath] = { + default: subpath, + }; + } + } + await fs.promises.writeFile( + 'dist/package.json', + JSON.stringify( + Object.assign( + /** @type {Record} */ ( + JSON.parse(await fs.promises.readFile('dist/package.json', 'utf-8')) + ), + { + exports: newExports, + }, + ), + null, + 2, + ), + ); +} +postprocess(); diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 0000000..98b1a12 --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -exuo pipefail + +RESPONSE=$(curl -X POST "$URL" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ + -H "Content-Type: application/gzip" \ + --data-binary @- "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/unlayer-typescript/$SHA'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi diff --git a/src/api-promise.ts b/src/api-promise.ts new file mode 100644 index 0000000..8c775ee --- /dev/null +++ b/src/api-promise.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/api-promise instead */ +export * from './core/api-promise'; diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..36c1ee8 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,741 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types'; +import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types'; +import { uuid4 } from './internal/utils/uuid'; +import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values'; +import { sleep } from './internal/utils/sleep'; +export type { Logger, LogLevel } from './internal/utils/log'; +import { castToError, isAbortError } from './internal/errors'; +import type { APIResponseProps } from './internal/parse'; +import { getPlatformHeaders } from './internal/detect-platform'; +import * as Shims from './internal/shims'; +import * as Opts from './internal/request-options'; +import { VERSION } from './version'; +import * as Errors from './core/error'; +import * as Uploads from './core/uploads'; +import * as API from './resources/index'; +import { APIPromise } from './core/api-promise'; +import { Documents } from './resources/documents/documents'; +import { Emails } from './resources/emails/emails'; +import { Pages } from './resources/pages/pages'; +import { Project } from './resources/project/project'; +import { type Fetch } from './internal/builtin-types'; +import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; +import { FinalRequestOptions, RequestOptions } from './internal/request-options'; +import { readEnv } from './internal/utils/env'; +import { + type LogLevel, + type Logger, + formatRequestDetails, + loggerFor, + parseLogLevel, +} from './internal/utils/log'; +import { isEmptyObj } from './internal/utils/values'; + +export interface ClientOptions { + /** + * Defaults to process.env['UNLAYER_API_KEY']. + */ + apiKey?: string | undefined; + + /** + * Override the default base URL for the API, e.g., "https://api.example.com/v2/" + * + * Defaults to process.env['UNLAYER_BASE_URL']. + */ + baseURL?: string | null | undefined; + + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * Note that request timeouts are retried by default, so in a worst-case scenario you may wait + * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds + */ + timeout?: number | undefined; + /** + * Additional `RequestInit` options to be passed to `fetch` calls. + * Properties will be overridden by per-request `fetchOptions`. + */ + fetchOptions?: MergedRequestInit | undefined; + + /** + * Specify a custom `fetch` function implementation. + * + * If not provided, we expect that `fetch` is defined globally. + */ + fetch?: Fetch | undefined; + + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number | undefined; + + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `null` in request options. + */ + defaultHeaders?: HeadersLike | undefined; + + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: Record | undefined; + + /** + * Set the log level. + * + * Defaults to process.env['UNLAYER_LOG'] or 'warn' if it isn't set. + */ + logLevel?: LogLevel | undefined; + + /** + * Set the logger. + * + * Defaults to globalThis.console. + */ + logger?: Logger | undefined; +} + +/** + * API Client for interfacing with the Unlayer API. + */ +export class Unlayer { + apiKey: string; + + baseURL: string; + maxRetries: number; + timeout: number; + logger: Logger | undefined; + logLevel: LogLevel | undefined; + fetchOptions: MergedRequestInit | undefined; + + private fetch: Fetch; + #encoder: Opts.RequestEncoder; + protected idempotencyHeader?: string; + private _options: ClientOptions; + + /** + * API Client for interfacing with the Unlayer API. + * + * @param {string | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? undefined] + * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor({ + baseURL = readEnv('UNLAYER_BASE_URL'), + apiKey = readEnv('UNLAYER_API_KEY'), + ...opts + }: ClientOptions = {}) { + if (apiKey === undefined) { + throw new Errors.UnlayerError( + "The UNLAYER_API_KEY environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an apiKey option, like new Unlayer({ apiKey: 'My API Key' }).", + ); + } + + const options: ClientOptions = { + apiKey, + ...opts, + baseURL: baseURL || `https://api.unlayer.com`, + }; + + this.baseURL = options.baseURL!; + this.timeout = options.timeout ?? Unlayer.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = options.logger ?? console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? + parseLogLevel(readEnv('UNLAYER_LOG'), "process.env['UNLAYER_LOG']", this) ?? + defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = options.maxRetries ?? 2; + this.fetch = options.fetch ?? Shims.getDefaultFetch(); + this.#encoder = Opts.FallbackEncoder; + + this._options = options; + + this.apiKey = apiKey; + } + + /** + * Create a new client instance re-using the same options given to the current client with optional overriding. + */ + withOptions(options: Partial): this { + const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({ + ...this._options, + baseURL: this.baseURL, + maxRetries: this.maxRetries, + timeout: this.timeout, + logger: this.logger, + logLevel: this.logLevel, + fetch: this.fetch, + fetchOptions: this.fetchOptions, + apiKey: this.apiKey, + ...options, + }); + return client; + } + + /** + * Check whether the base URL is set to its default. + */ + #baseURLOverridden(): boolean { + return this.baseURL !== 'https://api.unlayer.com'; + } + + protected defaultQuery(): Record | undefined { + return this._options.defaultQuery; + } + + protected validateHeaders({ values, nulls }: NullableHeaders) { + return; + } + + protected async authHeaders(opts: FinalRequestOptions): Promise { + return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); + } + + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + protected stringifyQuery(query: Record): string { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new Errors.UnlayerError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); + } + + private getUserAgent(): string { + return `${this.constructor.name}/JS ${VERSION}`; + } + + protected defaultIdempotencyKey(): string { + return `stainless-node-retry-${uuid4()}`; + } + + protected makeStatusError( + status: number, + error: Object, + message: string | undefined, + headers: Headers, + ): Errors.APIError { + return Errors.APIError.generate(status, error, message, headers); + } + + buildURL( + path: string, + query: Record | null | undefined, + defaultBaseURL?: string | undefined, + ): string { + const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL; + const url = + isAbsoluteURL(path) ? + new URL(path) + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = { ...defaultQuery, ...query }; + } + + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query as Record); + } + + return url.toString(); + } + + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + */ + protected async prepareOptions(options: FinalRequestOptions): Promise {} + + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + protected async prepareRequest( + request: RequestInit, + { url, options }: { url: string; options: FinalRequestOptions }, + ): Promise {} + + get(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('get', path, opts); + } + + post(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('post', path, opts); + } + + patch(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('patch', path, opts); + } + + put(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('put', path, opts); + } + + delete(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('delete', path, opts); + } + + private methodRequest( + method: HTTPMethod, + path: string, + opts?: PromiseOrValue, + ): APIPromise { + return this.request( + Promise.resolve(opts).then((opts) => { + return { method, path, ...opts }; + }), + ); + } + + request( + options: PromiseOrValue, + remainingRetries: number | null = null, + ): APIPromise { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + + private async makeRequest( + optionsInput: PromiseOrValue, + retriesRemaining: number | null, + retryOfRequestLogID: string | undefined, + ): Promise { + const options = await optionsInput; + const maxRetries = options.maxRetries ?? this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + + await this.prepareOptions(options); + + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); + + await this.prepareRequest(req, { url, options }); + + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + + loggerFor(this).debug( + `[${requestLogID}] sending request`, + formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + }), + ); + + if (options.signal?.aborted) { + throw new Errors.APIUserAbortError(); + } + + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + + if (response instanceof globalThis.Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if (options.signal?.aborted) { + throw new Errors.APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = + isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID); + } + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); + if (isTimeout) { + throw new Errors.APIConnectionTimeoutError(); + } + throw new Errors.APIConnectionError({ cause: response }); + } + + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${ + response.ok ? 'succeeded' : 'failed' + } with status ${response.status} in ${headersTime - startTime}ms`; + + if (!response.ok) { + const shouldRetry = await this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + + // We don't need the body of this response. + await Shims.CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); + return this.retryRequest( + options, + retriesRemaining, + retryOfRequestLogID ?? requestLogID, + response.headers, + ); + } + + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + + const errText = await response.text().catch((err: any) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + }), + ); + + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + + loggerFor(this).info(responseInfo); + loggerFor(this).debug( + `[${requestLogID}] response start`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); + + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + + async fetchWithTimeout( + url: RequestInfo, + init: RequestInit | undefined, + ms: number, + controller: AbortController, + ): Promise { + const { signal, method, ...options } = init || {}; + if (signal) signal.addEventListener('abort', () => controller.abort()); + + const timeout = setTimeout(() => controller.abort(), ms); + + const isReadableBody = + ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + + const fetchOptions: RequestInit = { + signal: controller.signal as any, + ...(isReadableBody ? { duplex: 'half' } : {}), + method: 'GET', + ...options, + }; + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } finally { + clearTimeout(timeout); + } + } + + private async shouldRetry(response: Response): Promise { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') return true; + if (shouldRetryHeader === 'false') return false; + + // Retry on request timeouts. + if (response.status === 408) return true; + + // Retry on lock timeouts. + if (response.status === 409) return true; + + // Retry on rate limits. + if (response.status === 429) return true; + + // Retry internal errors. + if (response.status >= 500) return true; + + return false; + } + + private async retryRequest( + options: FinalRequestOptions, + retriesRemaining: number, + requestLogID: string, + responseHeaders?: Headers | undefined, + ): Promise { + let timeoutMillis: number | undefined; + + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders?.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = options.maxRetries ?? this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep(timeoutMillis); + + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + + private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + + const numRetries = maxRetries - retriesRemaining; + + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + + return sleepSeconds * jitter * 1000; + } + + async buildRequest( + inputOptions: FinalRequestOptions, + { retryCount = 0 }: { retryCount?: number } = {}, + ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> { + const options = { ...inputOptions }; + const { method, path, query, defaultBaseURL } = options; + + const url = this.buildURL(path!, query as Record, defaultBaseURL); + if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); + options.timeout = options.timeout ?? this.timeout; + const { bodyHeaders, body } = this.buildBody({ options }); + const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount }); + + const req: FinalizedRequestInit = { + method, + headers: reqHeaders, + ...(options.signal && { signal: options.signal }), + ...((globalThis as any).ReadableStream && + body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }), + ...(body && { body }), + ...((this.fetchOptions as any) ?? {}), + ...((options.fetchOptions as any) ?? {}), + }; + + return { req, url, timeout: options.timeout }; + } + + private async buildHeaders({ + options, + method, + bodyHeaders, + retryCount, + }: { + options: FinalRequestOptions; + method: HTTPMethod; + bodyHeaders: HeadersLike; + retryCount: number; + }): Promise { + let idempotencyHeaders: HeadersLike = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + + const headers = buildHeaders([ + idempotencyHeaders, + { + Accept: 'application/json', + 'User-Agent': this.getUserAgent(), + 'X-Stainless-Retry-Count': String(retryCount), + ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), + ...getPlatformHeaders(), + }, + await this.authHeaders(options), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + ]); + + this.validateHeaders(headers); + + return headers.values; + } + + private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + bodyHeaders: HeadersLike; + body: BodyInit | undefined; + } { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream) + ) { + return { bodyHeaders: undefined, body: body as BodyInit }; + } else if ( + typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')) + ) { + return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable) }; + } else { + return this.#encoder({ body, headers }); + } + } + + static Unlayer = this; + static DEFAULT_TIMEOUT = 60000; // 1 minute + + static UnlayerError = Errors.UnlayerError; + static APIError = Errors.APIError; + static APIConnectionError = Errors.APIConnectionError; + static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError; + static APIUserAbortError = Errors.APIUserAbortError; + static NotFoundError = Errors.NotFoundError; + static ConflictError = Errors.ConflictError; + static RateLimitError = Errors.RateLimitError; + static BadRequestError = Errors.BadRequestError; + static AuthenticationError = Errors.AuthenticationError; + static InternalServerError = Errors.InternalServerError; + static PermissionDeniedError = Errors.PermissionDeniedError; + static UnprocessableEntityError = Errors.UnprocessableEntityError; + + static toFile = Uploads.toFile; + + project: API.Project = new API.Project(this); + documents: API.Documents = new API.Documents(this); + emails: API.Emails = new API.Emails(this); + pages: API.Pages = new API.Pages(this); +} + +Unlayer.Project = Project; +Unlayer.Documents = Documents; +Unlayer.Emails = Emails; +Unlayer.Pages = Pages; + +export declare namespace Unlayer { + export type RequestOptions = Opts.RequestOptions; + + export { Project as Project }; + + export { Documents as Documents }; + + export { Emails as Emails }; + + export { Pages as Pages }; +} diff --git a/src/core/README.md b/src/core/README.md new file mode 100644 index 0000000..485fce8 --- /dev/null +++ b/src/core/README.md @@ -0,0 +1,3 @@ +# `core` + +This directory holds public modules implementing non-resource-specific SDK functionality. diff --git a/src/core/api-promise.ts b/src/core/api-promise.ts new file mode 100644 index 0000000..31b6b94 --- /dev/null +++ b/src/core/api-promise.ts @@ -0,0 +1,92 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { type Unlayer } from '../client'; + +import { type PromiseOrValue } from '../internal/types'; +import { APIResponseProps, defaultParseResponse } from '../internal/parse'; + +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +export class APIPromise extends Promise { + private parsedPromise: Promise | undefined; + #client: Unlayer; + + constructor( + client: Unlayer, + private responsePromise: Promise, + private parseResponse: ( + client: Unlayer, + props: APIResponseProps, + ) => PromiseOrValue = defaultParseResponse, + ) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null as any); + }); + this.#client = client; + } + + _thenUnwrap(transform: (data: T, props: APIResponseProps) => U): APIPromise { + return new APIPromise(this.#client, this.responsePromise, async (client, props) => + transform(await this.parseResponse(client, props), props), + ); + } + + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse(): Promise { + return this.responsePromise.then((p) => p.response); + } + + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse(): Promise<{ data: T; response: Response }> { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + + private parse(): Promise { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.#client, data)); + } + return this.parsedPromise; + } + + override then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this.parse().then(onfulfilled, onrejected); + } + + override catch( + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, + ): Promise { + return this.parse().catch(onrejected); + } + + override finally(onfinally?: (() => void) | undefined | null): Promise { + return this.parse().finally(onfinally); + } +} diff --git a/src/core/error.ts b/src/core/error.ts new file mode 100644 index 0000000..b06c4dd --- /dev/null +++ b/src/core/error.ts @@ -0,0 +1,130 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { castToError } from '../internal/errors'; + +export class UnlayerError extends Error {} + +export class APIError< + TStatus extends number | undefined = number | undefined, + THeaders extends Headers | undefined = Headers | undefined, + TError extends Object | undefined = Object | undefined, +> extends UnlayerError { + /** HTTP status for the response that caused the error */ + readonly status: TStatus; + /** HTTP headers for the response that caused the error */ + readonly headers: THeaders; + /** JSON body of the response that caused the error */ + readonly error: TError; + + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + + private static makeMessage(status: number | undefined, error: any, message: string | undefined) { + const msg = + error?.message ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + + static generate( + status: number | undefined, + errorResponse: Object | undefined, + message: string | undefined, + headers: Headers | undefined, + ): APIError { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + + const error = errorResponse as Record; + + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + + return new APIError(status, error, message, headers); + } +} + +export class APIUserAbortError extends APIError { + constructor({ message }: { message?: string } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} + +export class APIConnectionError extends APIError { + constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) this.cause = cause; + } +} + +export class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message }: { message?: string } = {}) { + super({ message: message ?? 'Request timed out.' }); + } +} + +export class BadRequestError extends APIError<400, Headers> {} + +export class AuthenticationError extends APIError<401, Headers> {} + +export class PermissionDeniedError extends APIError<403, Headers> {} + +export class NotFoundError extends APIError<404, Headers> {} + +export class ConflictError extends APIError<409, Headers> {} + +export class UnprocessableEntityError extends APIError<422, Headers> {} + +export class RateLimitError extends APIError<429, Headers> {} + +export class InternalServerError extends APIError {} diff --git a/src/core/resource.ts b/src/core/resource.ts new file mode 100644 index 0000000..5f2ee60 --- /dev/null +++ b/src/core/resource.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { Unlayer } from '../client'; + +export abstract class APIResource { + protected _client: Unlayer; + + constructor(client: Unlayer) { + this._client = client; + } +} diff --git a/src/core/uploads.ts b/src/core/uploads.ts new file mode 100644 index 0000000..2882ca6 --- /dev/null +++ b/src/core/uploads.ts @@ -0,0 +1,2 @@ +export { type Uploadable } from '../internal/uploads'; +export { toFile, type ToFileInput } from '../internal/to-file'; diff --git a/src/error.ts b/src/error.ts new file mode 100644 index 0000000..fc55f46 --- /dev/null +++ b/src/error.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/error instead */ +export * from './core/error'; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..e635759 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Unlayer as default } from './client'; + +export { type Uploadable, toFile } from './core/uploads'; +export { APIPromise } from './core/api-promise'; +export { Unlayer, type ClientOptions } from './client'; +export { + UnlayerError, + APIError, + APIConnectionError, + APIConnectionTimeoutError, + APIUserAbortError, + NotFoundError, + ConflictError, + RateLimitError, + BadRequestError, + AuthenticationError, + InternalServerError, + PermissionDeniedError, + UnprocessableEntityError, +} from './core/error'; diff --git a/src/internal/README.md b/src/internal/README.md new file mode 100644 index 0000000..3ef5a25 --- /dev/null +++ b/src/internal/README.md @@ -0,0 +1,3 @@ +# `internal` + +The modules in this directory are not importable outside this package and will change between releases. diff --git a/src/internal/builtin-types.ts b/src/internal/builtin-types.ts new file mode 100644 index 0000000..c23d3bd --- /dev/null +++ b/src/internal/builtin-types.ts @@ -0,0 +1,93 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise; + +/** + * An alias to the builtin `RequestInit` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit + */ +type _RequestInit = RequestInit; + +/** + * An alias to the builtin `Response` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/Response + */ +type _Response = Response; + +/** + * The type for the first argument to `fetch`. + * + * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource + */ +type _RequestInfo = Request | URL | string; + +/** + * The type for constructing `RequestInit` Headers. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit#setting_headers + */ +type _HeadersInit = RequestInit['headers']; + +/** + * The type for constructing `RequestInit` body. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit#body + */ +type _BodyInit = RequestInit['body']; + +/** + * An alias to the builtin `Array` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Array = Array; + +/** + * An alias to the builtin `Record` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Record = Record; + +export type { + _Array as Array, + _BodyInit as BodyInit, + _HeadersInit as HeadersInit, + _Record as Record, + _RequestInfo as RequestInfo, + _RequestInit as RequestInit, + _Response as Response, +}; + +/** + * A copy of the builtin `EndingType` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L27941 + */ +type EndingType = 'native' | 'transparent'; + +/** + * A copy of the builtin `BlobPropertyBag` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L154 + * https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#options + */ +export interface BlobPropertyBag { + endings?: EndingType; + type?: string; +} + +/** + * A copy of the builtin `FilePropertyBag` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L503 + * https://developer.mozilla.org/en-US/docs/Web/API/File/File#options + */ +export interface FilePropertyBag extends BlobPropertyBag { + lastModified?: number; +} diff --git a/src/internal/detect-platform.ts b/src/internal/detect-platform.ts new file mode 100644 index 0000000..e82d95c --- /dev/null +++ b/src/internal/detect-platform.ts @@ -0,0 +1,196 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { VERSION } from '../version'; + +export const isRunningInBrowser = () => { + return ( + // @ts-ignore + typeof window !== 'undefined' && + // @ts-ignore + typeof window.document !== 'undefined' && + // @ts-ignore + typeof navigator !== 'undefined' + ); +}; + +type DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown'; + +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform(): DetectedPlatform { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if ( + Object.prototype.toString.call( + typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0, + ) === '[object process]' + ) { + return 'node'; + } + return 'unknown'; +} + +declare const Deno: any; +declare const EdgeRuntime: any; +type Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown'; +type PlatformName = + | 'MacOS' + | 'Linux' + | 'Windows' + | 'FreeBSD' + | 'OpenBSD' + | 'iOS' + | 'Android' + | `Other:${string}` + | 'Unknown'; +type Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari'; +type PlatformProperties = { + 'X-Stainless-Lang': 'js'; + 'X-Stainless-Package-Version': string; + 'X-Stainless-OS': PlatformName; + 'X-Stainless-Arch': Arch; + 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown'; + 'X-Stainless-Runtime-Version': string; +}; +const getPlatformProperties = (): PlatformProperties => { + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': + typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': (globalThis as any).process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'), + 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown', + }; + } + + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; + +type BrowserInfo = { + browser: Browser; + version: string; +}; + +declare const navigator: { userAgent: string } | undefined; + +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo(): BrowserInfo | null { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge' as const, pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie' as const, pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie' as const, pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome' as const, pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox' as const, pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari' as const, pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + + return null; +} + +const normalizeArch = (arch: string): Arch => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') return 'x32'; + if (arch === 'x86_64' || arch === 'x64') return 'x64'; + if (arch === 'arm') return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') return 'arm64'; + if (arch) return `other:${arch}`; + return 'unknown'; +}; + +const normalizePlatform = (platform: string): PlatformName => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + + platform = platform.toLowerCase(); + + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) return 'iOS'; + if (platform === 'android') return 'Android'; + if (platform === 'darwin') return 'MacOS'; + if (platform === 'win32') return 'Windows'; + if (platform === 'freebsd') return 'FreeBSD'; + if (platform === 'openbsd') return 'OpenBSD'; + if (platform === 'linux') return 'Linux'; + if (platform) return `Other:${platform}`; + return 'Unknown'; +}; + +let _platformHeaders: PlatformProperties; +export const getPlatformHeaders = () => { + return (_platformHeaders ??= getPlatformProperties()); +}; diff --git a/src/internal/errors.ts b/src/internal/errors.ts new file mode 100644 index 0000000..82c7b14 --- /dev/null +++ b/src/internal/errors.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export function isAbortError(err: unknown) { + return ( + typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && (err as any).name === 'AbortError') || + // Expo fetch + ('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))) + ); +} + +export const castToError = (err: any): Error => { + if (err instanceof Error) return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) error.cause = err.cause; + if (err.name) error.name = err.name; + return error; + } + } catch {} + try { + return new Error(JSON.stringify(err)); + } catch {} + } + return new Error(err); +}; diff --git a/src/internal/headers.ts b/src/internal/headers.ts new file mode 100644 index 0000000..c724a9d --- /dev/null +++ b/src/internal/headers.ts @@ -0,0 +1,97 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { isReadonlyArray } from './utils/values'; + +type HeaderValue = string | undefined | null; +export type HeadersLike = + | Headers + | readonly HeaderValue[][] + | Record + | undefined + | null + | NullableHeaders; + +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); + +/** + * @internal + * Users can pass explicit nulls to unset default headers. When we parse them + * into a standard headers type we need to preserve that information. + */ +export type NullableHeaders = { + /** Brand check, prevent users from creating a NullableHeaders. */ + [brand_privateNullableHeaders]: true; + /** Parsed headers. */ + values: Headers; + /** Set of lowercase header names explicitly set to null. */ + nulls: Set; +}; + +function* iterateHeaders(headers: HeadersLike): IterableIterator { + if (!headers) return; + + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + + let shouldClear = false; + let iter: Iterable; + if (headers instanceof Headers) { + iter = headers.entries(); + } else if (isReadonlyArray(headers)) { + iter = headers; + } else { + shouldClear = true; + iter = Object.entries(headers ?? {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') throw new TypeError('expected header name to be a string'); + const values = isReadonlyArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) continue; + + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} + +export const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + for (const headers of newHeaders) { + const seenHeaders = new Set(); + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +export const isEmptyHeaders = (headers: HeadersLike) => { + for (const _ of iterateHeaders(headers)) return false; + return true; +}; diff --git a/src/internal/parse.ts b/src/internal/parse.ts new file mode 100644 index 0000000..a2edd58 --- /dev/null +++ b/src/internal/parse.ts @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { FinalRequestOptions } from './request-options'; +import { type Unlayer } from '../client'; +import { formatRequestDetails, loggerFor } from './utils/log'; + +export type APIResponseProps = { + response: Response; + options: FinalRequestOptions; + controller: AbortController; + requestLogID: string; + retryOfRequestLogID: string | undefined; + startTime: number; +}; + +export async function defaultParseResponse(client: Unlayer, props: APIResponseProps): Promise { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null as T; + } + + if (props.options.__binaryResponse) { + return response as unknown as T; + } + + const contentType = response.headers.get('content-type'); + const mediaType = contentType?.split(';')[0]?.trim(); + const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); + if (isJSON) { + const json = await response.json(); + return json as T; + } + + const text = await response.text(); + return text as unknown as T; + })(); + loggerFor(client).debug( + `[${requestLogID}] response parsed`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + }), + ); + return body; +} diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts new file mode 100644 index 0000000..2aabf9a --- /dev/null +++ b/src/internal/request-options.ts @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { NullableHeaders } from './headers'; + +import type { BodyInit } from './builtin-types'; +import type { HTTPMethod, MergedRequestInit } from './types'; +import { type HeadersLike } from './headers'; + +export type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string }; + +export type RequestOptions = { + /** + * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). + */ + method?: HTTPMethod; + + /** + * The URL path for the request. + * + * @example "/v1/foo" + */ + path?: string; + + /** + * Query parameters to include in the request URL. + */ + query?: object | undefined | null; + + /** + * The request body. Can be a string, JSON object, FormData, or other supported types. + */ + body?: unknown; + + /** + * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. + */ + headers?: HeadersLike; + + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ + maxRetries?: number; + + stream?: boolean | undefined; + + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * @unit milliseconds + */ + timeout?: number; + + /** + * Additional `RequestInit` options to be passed to the underlying `fetch` call. + * These options will be merged with the client's default fetch options. + */ + fetchOptions?: MergedRequestInit; + + /** + * An AbortSignal that can be used to cancel the request. + */ + signal?: AbortSignal | undefined | null; + + /** + * A unique key for this request to enable idempotency. + */ + idempotencyKey?: string; + + /** + * Override the default base URL for this specific request. + */ + defaultBaseURL?: string | undefined; + + __binaryResponse?: boolean | undefined; +}; + +export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; +export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent; + +export const FallbackEncoder: RequestEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; diff --git a/src/internal/shim-types.ts b/src/internal/shim-types.ts new file mode 100644 index 0000000..8ddf7b0 --- /dev/null +++ b/src/internal/shim-types.ts @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ + +type NeverToAny = T extends never ? any : T; + +/** @ts-ignore */ +type _DOMReadableStream = globalThis.ReadableStream; + +/** @ts-ignore */ +type _NodeReadableStream = import('stream/web').ReadableStream; + +type _ConditionalNodeReadableStream = + typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream; + +type _ReadableStream = NeverToAny< + | ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) + | ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) +>; + +export type { _ReadableStream as ReadableStream }; diff --git a/src/internal/shims.ts b/src/internal/shims.ts new file mode 100644 index 0000000..6a2681a --- /dev/null +++ b/src/internal/shims.ts @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available. + * + * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error + * messages in cases where an environment isn't fully supported. + */ + +import type { Fetch } from './builtin-types'; +import type { ReadableStream } from './shim-types'; + +export function getDefaultFetch(): Fetch { + if (typeof fetch !== 'undefined') { + return fetch as any; + } + + throw new Error( + '`fetch` is not defined as a global; Either pass `fetch` to the client, `new Unlayer({ fetch })` or polyfill the global, `globalThis.fetch = fetch`', + ); +} + +type ReadableStreamArgs = ConstructorParameters; + +export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream { + const ReadableStream = (globalThis as any).ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error( + '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`', + ); + } + + return new ReadableStream(...args); +} + +export function ReadableStreamFrom(iterable: Iterable | AsyncIterable): ReadableStream { + let iter: AsyncIterator | Iterator = + Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + + return makeReadableStream({ + start() {}, + async pull(controller: any) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } else { + controller.enqueue(value); + } + }, + async cancel() { + await iter.return?.(); + }, + }); +} + +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +export function ReadableStreamToAsyncIterable(stream: any): AsyncIterableIterator { + if (stream[Symbol.asyncIterator]) return stream; + + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result?.done) reader.releaseLock(); // release lock when stream becomes closed + return result; + } catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} + +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +export async function CancelReadableStream(stream: any): Promise { + if (stream === null || typeof stream !== 'object') return; + + if (stream[Symbol.asyncIterator]) { + await stream[Symbol.asyncIterator]().return?.(); + return; + } + + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts new file mode 100644 index 0000000..245e849 --- /dev/null +++ b/src/internal/to-file.ts @@ -0,0 +1,154 @@ +import { BlobPart, getName, makeFile, isAsyncIterable } from './uploads'; +import type { FilePropertyBag } from './builtin-types'; +import { checkFileSupport } from './uploads'; + +type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView; + +/** + * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc. + * Don't add arrayBuffer here, node-fetch doesn't have it + */ +interface BlobLike { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */ + readonly size: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */ + readonly type: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */ + text(): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */ + slice(start?: number, end?: number): BlobLike; +} + +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise } => + value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; + +/** + * Intended to match DOM File, node:buffer File, undici File, etc. + */ +interface FileLike extends BlobLike { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */ + readonly lastModified: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */ + readonly name?: string | undefined; +} + +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise } => + value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); + +/** + * Intended to match DOM Response, node-fetch Response, undici Response, etc. + */ +export interface ResponseLike { + url: string; + blob(): Promise; +} + +const isResponseLike = (value: any): value is ResponseLike => + value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; + +export type ToFileInput = + | FileLike + | ResponseLike + | Exclude + | AsyncIterable; + +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +export async function toFile( + value: ToFileInput | PromiseLike, + name?: string | null | undefined, + options?: FilePropertyBag | undefined, +): Promise { + checkFileSupport(); + + // If it's a promise, resolve it. + value = await value; + + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + + if (isResponseLike(value)) { + const blob = await value.blob(); + name ||= new URL(value.url).pathname.split(/[\\/]/).pop(); + + return makeFile(await getBytes(blob), name, options); + } + + const parts = await getBytes(value); + + name ||= getName(value); + + if (!options?.type) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = { ...options, type }; + } + } + + return makeFile(parts, name, options); +} + +async function getBytes(value: BlobLikePart | AsyncIterable): Promise> { + let parts: Array = []; + if ( + typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer + ) { + parts.push(value); + } else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } else if ( + isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + for await (const chunk of value) { + parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating? + } + } else { + const constructor = value?.constructor?.name; + throw new Error( + `Unexpected data type: ${typeof value}${ + constructor ? `; constructor: ${constructor}` : '' + }${propsForError(value)}`, + ); + } + + return parts; +} + +function propsForError(value: unknown): string { + if (typeof value !== 'object' || value === null) return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} diff --git a/src/internal/types.ts b/src/internal/types.ts new file mode 100644 index 0000000..b668dfc --- /dev/null +++ b/src/internal/types.ts @@ -0,0 +1,95 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export type PromiseOrValue = T | Promise; +export type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; + +export type KeysEnum = { [P in keyof Required]: true }; + +export type FinalizedRequestInit = RequestInit & { headers: Headers }; + +type NotAny = [0] extends [1 & T] ? never : T; + +/** + * Some environments overload the global fetch function, and Parameters only gets the last signature. + */ +type OverloadedParameters = + T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; + } + ) ? + A | B | C | D + : T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + } + ) ? + A | B | C + : T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + } + ) ? + A | B + : T extends (...args: infer A) => unknown ? A + : never; + +/* eslint-disable */ +/** + * These imports attempt to get types from a parent package's dependencies. + * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which + * would cause typescript to show types not present at runtime. To avoid this, we import + * directly from parent node_modules folders. + * + * We need to check multiple levels because we don't know what directory structure we'll be in. + * For example, pnpm generates directories like this: + * ``` + * node_modules + * ├── .pnpm + * │ └── pkg@1.0.0 + * │ └── node_modules + * │ └── pkg + * │ └── internal + * │ └── types.d.ts + * ├── pkg -> .pnpm/pkg@1.0.0/node_modules/pkg + * └── undici + * ``` + * + * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition + */ +/** @ts-ignore For users with \@types/node */ +type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with undici */ +type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with \@types/bun */ +type BunRequestInit = globalThis.FetchRequestInit; +/** @ts-ignore For users with node-fetch@2 */ +type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users who use Deno */ +type FetchRequestInit = NonNullable[1]>; +/* eslint-enable */ + +type RequestInits = + | NotAny + | NotAny + | NotAny + | NotAny + | NotAny + | NotAny + | NotAny; + +/** + * This type contains `RequestInit` options that may be available on the current runtime, + * including per-platform extensions like `dispatcher`, `agent`, `client`, etc. + */ +export type MergedRequestInit = RequestInits & + /** We don't include these in the types as they'll be overridden for every request. */ + Partial>; diff --git a/src/internal/uploads.ts b/src/internal/uploads.ts new file mode 100644 index 0000000..bce6d51 --- /dev/null +++ b/src/internal/uploads.ts @@ -0,0 +1,187 @@ +import { type RequestOptions } from './request-options'; +import type { FilePropertyBag, Fetch } from './builtin-types'; +import type { Unlayer } from '../client'; +import { ReadableStreamFrom } from './shims'; + +export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView; +type FsReadStream = AsyncIterable & { path: string | { toString(): string } }; + +// https://github.com/oven-sh/bun/issues/5980 +interface BunFile extends Blob { + readonly name?: string | undefined; +} + +export const checkFileSupport = () => { + if (typeof File === 'undefined') { + const { process } = globalThis as any; + const isOldNode = + typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error( + '`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : ''), + ); + } +}; + +/** + * Typically, this is a native "File" class. + * + * We provide the {@link toFile} utility to convert a variety of objects + * into the File class. + * + * For convenience, you can also pass a fetch Response, or in Node, + * the result of fs.createReadStream(). + */ +export type Uploadable = File | Response | FsReadStream | BunFile; + +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +export function makeFile( + fileBits: BlobPart[], + fileName: string | undefined, + options?: FilePropertyBag, +): File { + checkFileSupport(); + return new File(fileBits as any, fileName ?? 'unknown_file', options); +} + +export function getName(value: any): string | undefined { + return ( + ( + (typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '' + ) + .split(/[\\/]/) + .pop() || undefined + ); +} + +export const isAsyncIterable = (value: any): value is AsyncIterable => + value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value. + * Otherwise returns the request as is. + */ +export const maybeMultipartFormRequestOptions = async ( + opts: RequestOptions, + fetch: Unlayer | Fetch, +): Promise => { + if (!hasUploadableValue(opts.body)) return opts; + + return { ...opts, body: await createForm(opts.body, fetch) }; +}; + +type MultipartFormRequestOptions = Omit & { body: unknown }; + +export const multipartFormRequestOptions = async ( + opts: MultipartFormRequestOptions, + fetch: Unlayer | Fetch, +): Promise => { + return { ...opts, body: await createForm(opts.body, fetch) }; +}; + +const supportsFormDataMap = /* @__PURE__ */ new WeakMap>(); + +/** + * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending + * properly-encoded form data, it just stringifies the object, resulting in a request body of "[object FormData]". + * This function detects if the fetch function provided supports the global FormData object to avoid + * confusing error messages later on. + */ +function supportsFormData(fetchObject: Unlayer | Fetch): Promise { + const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch; + const cached = supportsFormDataMap.get(fetch); + if (cached) return cached; + const promise = (async () => { + try { + const FetchResponse = ( + 'Response' in fetch ? + fetch.Response + : (await fetch('data:,')).constructor) as typeof Response; + const data = new FormData(); + if (data.toString() === (await new FetchResponse(data).text())) { + return false; + } + return true; + } catch { + // avoid false negatives + return true; + } + })(); + supportsFormDataMap.set(fetch, promise); + return promise; +} + +export const createForm = async >( + body: T | undefined, + fetch: Unlayer | Fetch, +): Promise => { + if (!(await supportsFormData(fetch))) { + throw new TypeError( + 'The provided fetch function does not support file uploads with the current global FormData class.', + ); + } + const form = new FormData(); + await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value))); + return form; +}; + +// We check for Blob not File because Bun.File doesn't inherit from File, +// but they both inherit from Blob and have a `name` property at runtime. +const isNamedBlob = (value: unknown) => value instanceof Blob && 'name' in value; + +const isUploadable = (value: unknown) => + typeof value === 'object' && + value !== null && + (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value)); + +const hasUploadableValue = (value: unknown): boolean => { + if (isUploadable(value)) return true; + if (Array.isArray(value)) return value.some(hasUploadableValue); + if (value && typeof value === 'object') { + for (const k in value) { + if (hasUploadableValue((value as any)[k])) return true; + } + } + return false; +}; + +const addFormValue = async (form: FormData, key: string, value: unknown): Promise => { + if (value === undefined) return; + if (value == null) { + throw new TypeError( + `Received null for "${key}"; to pass null in FormData, you must use the string 'null'`, + ); + } + + // TODO: make nested formats configurable + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + form.append(key, String(value)); + } else if (value instanceof Response) { + form.append(key, makeFile([await value.blob()], getName(value))); + } else if (isAsyncIterable(value)) { + form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value))); + } else if (isNamedBlob(value)) { + form.append(key, value, getName(value)); + } else if (Array.isArray(value)) { + await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry))); + } else if (typeof value === 'object') { + await Promise.all( + Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)), + ); + } else { + throw new TypeError( + `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`, + ); + } +}; diff --git a/src/internal/utils.ts b/src/internal/utils.ts new file mode 100644 index 0000000..3cbfacc --- /dev/null +++ b/src/internal/utils.ts @@ -0,0 +1,8 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './utils/values'; +export * from './utils/base64'; +export * from './utils/env'; +export * from './utils/log'; +export * from './utils/uuid'; +export * from './utils/sleep'; diff --git a/src/internal/utils/base64.ts b/src/internal/utils/base64.ts new file mode 100644 index 0000000..d4d32fb --- /dev/null +++ b/src/internal/utils/base64.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { UnlayerError } from '../../core/error'; +import { encodeUTF8 } from './bytes'; + +export const toBase64 = (data: string | Uint8Array | null | undefined): string => { + if (!data) return ''; + + if (typeof (globalThis as any).Buffer !== 'undefined') { + return (globalThis as any).Buffer.from(data).toString('base64'); + } + + if (typeof data === 'string') { + data = encodeUTF8(data); + } + + if (typeof btoa !== 'undefined') { + return btoa(String.fromCharCode.apply(null, data as any)); + } + + throw new UnlayerError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); +}; + +export const fromBase64 = (str: string): Uint8Array => { + if (typeof (globalThis as any).Buffer !== 'undefined') { + const buf = (globalThis as any).Buffer.from(str, 'base64'); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); + } + + if (typeof atob !== 'undefined') { + const bstr = atob(str); + const buf = new Uint8Array(bstr.length); + for (let i = 0; i < bstr.length; i++) { + buf[i] = bstr.charCodeAt(i); + } + return buf; + } + + throw new UnlayerError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined'); +}; diff --git a/src/internal/utils/bytes.ts b/src/internal/utils/bytes.ts new file mode 100644 index 0000000..8da627a --- /dev/null +++ b/src/internal/utils/bytes.ts @@ -0,0 +1,32 @@ +export function concatBytes(buffers: Uint8Array[]): Uint8Array { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + + return output; +} + +let encodeUTF8_: (str: string) => Uint8Array; +export function encodeUTF8(str: string) { + let encoder; + return ( + encodeUTF8_ ?? + ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))) + )(str); +} + +let decodeUTF8_: (bytes: Uint8Array) => string; +export function decodeUTF8(bytes: Uint8Array) { + let decoder; + return ( + decodeUTF8_ ?? + ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))) + )(bytes); +} diff --git a/src/internal/utils/env.ts b/src/internal/utils/env.ts new file mode 100644 index 0000000..2d84800 --- /dev/null +++ b/src/internal/utils/env.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +export const readEnv = (env: string): string | undefined => { + if (typeof (globalThis as any).process !== 'undefined') { + return (globalThis as any).process.env?.[env]?.trim() ?? undefined; + } + if (typeof (globalThis as any).Deno !== 'undefined') { + return (globalThis as any).Deno.env?.get?.(env)?.trim(); + } + return undefined; +}; diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts new file mode 100644 index 0000000..1726922 --- /dev/null +++ b/src/internal/utils/log.ts @@ -0,0 +1,126 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { hasOwn } from './values'; +import { type Unlayer } from '../../client'; +import { RequestOptions } from '../request-options'; + +type LogFn = (message: string, ...rest: unknown[]) => void; +export type Logger = { + error: LogFn; + warn: LogFn; + info: LogFn; + debug: LogFn; +}; +export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug'; + +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; + +export const parseLogLevel = ( + maybeLevel: string | undefined, + sourceName: string, + client: Unlayer, +): LogLevel | undefined => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn( + `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify( + Object.keys(levelNumbers), + )}`, + ); + return undefined; +}; + +function noop() {} + +function makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} + +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; + +let cachedLoggers = /* @__PURE__ */ new WeakMap(); + +export function loggerFor(client: Unlayer): Logger { + const logger = client.logger; + const logLevel = client.logLevel ?? 'off'; + if (!logger) { + return noopLogger; + } + + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + + cachedLoggers.set(logger, [logLevel, levelLogger]); + + return levelLogger; +} + +export const formatRequestDetails = (details: { + options?: RequestOptions | undefined; + headers?: Headers | Record | undefined; + retryOfRequestLogID?: string | undefined; + retryOf?: string | undefined; + url?: string | undefined; + status?: number | undefined; + method?: string | undefined; + durationMs?: number | undefined; + message?: unknown; + body?: unknown; +}) => { + if (details.options) { + details.options = { ...details.options }; + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries( + (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map( + ([name, value]) => [ + name, + ( + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie' + ) ? + '***' + : value, + ], + ), + ); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; diff --git a/src/internal/utils/path.ts b/src/internal/utils/path.ts new file mode 100644 index 0000000..213ddcb --- /dev/null +++ b/src/internal/utils/path.ts @@ -0,0 +1,88 @@ +import { UnlayerError } from '../../core/error'; + +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +export function encodeURIPath(str: string) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} + +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); + +export const createPathTagFunction = (pathEncoder = encodeURIPath) => + function path(statics: readonly string[], ...params: readonly unknown[]): string { + // If there are no params, no processing is needed. + if (statics.length === 1) return statics[0]!; + + let postPath = false; + const invalidSegments = []; + const path = statics.reduce((previousValue, currentValue, index) => { + if (/[?#]/.test(currentValue)) { + postPath = true; + } + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if ( + index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY) + ?.toString)) + ) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); + }, ''); + + const pathOnly = path.split(/[?#]/, 1)[0]!; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, + }); + } + + invalidSegments.sort((a, b) => a.start - b.start); + + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + + throw new UnlayerError( + `Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`, + ); + } + + return path; + }; + +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); diff --git a/src/internal/utils/sleep.ts b/src/internal/utils/sleep.ts new file mode 100644 index 0000000..65e5296 --- /dev/null +++ b/src/internal/utils/sleep.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/src/internal/utils/uuid.ts b/src/internal/utils/uuid.ts new file mode 100644 index 0000000..b0e53aa --- /dev/null +++ b/src/internal/utils/uuid.ts @@ -0,0 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * https://stackoverflow.com/a/2117523 + */ +export let uuid4 = function () { + const { crypto } = globalThis as any; + if (crypto?.randomUUID) { + uuid4 = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => + (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16), + ); +}; diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts new file mode 100644 index 0000000..0fcd830 --- /dev/null +++ b/src/internal/utils/values.ts @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { UnlayerError } from '../../core/error'; + +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; + +export const isAbsoluteURL = (url: string): boolean => { + return startsWithSchemeRegexp.test(url); +}; + +export let isArray = (val: unknown): val is unknown[] => ((isArray = Array.isArray), isArray(val)); +export let isReadonlyArray = isArray as (val: unknown) => val is readonly unknown[]; + +/** Returns an object if the given value isn't an object, otherwise returns as-is */ +export function maybeObj(x: unknown): object { + if (typeof x !== 'object') { + return {}; + } + + return x ?? {}; +} + +// https://stackoverflow.com/a/34491287 +export function isEmptyObj(obj: Object | null | undefined): boolean { + if (!obj) return true; + for (const _k in obj) return false; + return true; +} + +// https://eslint.org/docs/latest/rules/no-prototype-builtins +export function hasOwn(obj: T, key: PropertyKey): key is keyof T { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +export function isObj(obj: unknown): obj is Record { + return obj != null && typeof obj === 'object' && !Array.isArray(obj); +} + +export const ensurePresent = (value: T | null | undefined): T => { + if (value == null) { + throw new UnlayerError(`Expected a value to be given but received ${value} instead.`); + } + + return value; +}; + +export const validatePositiveInteger = (name: string, n: unknown): number => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new UnlayerError(`${name} must be an integer`); + } + if (n < 0) { + throw new UnlayerError(`${name} must be a positive integer`); + } + return n; +}; + +export const coerceInteger = (value: unknown): number => { + if (typeof value === 'number') return Math.round(value); + if (typeof value === 'string') return parseInt(value, 10); + + throw new UnlayerError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; + +export const coerceFloat = (value: unknown): number => { + if (typeof value === 'number') return value; + if (typeof value === 'string') return parseFloat(value); + + throw new UnlayerError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; + +export const coerceBoolean = (value: unknown): boolean => { + if (typeof value === 'boolean') return value; + if (typeof value === 'string') return value === 'true'; + return Boolean(value); +}; + +export const maybeCoerceInteger = (value: unknown): number | undefined => { + if (value == null) { + return undefined; + } + return coerceInteger(value); +}; + +export const maybeCoerceFloat = (value: unknown): number | undefined => { + if (value == null) { + return undefined; + } + return coerceFloat(value); +}; + +export const maybeCoerceBoolean = (value: unknown): boolean | undefined => { + if (value == null) { + return undefined; + } + return coerceBoolean(value); +}; + +export const safeJSON = (text: string) => { + try { + return JSON.parse(text); + } catch (err) { + return undefined; + } +}; diff --git a/src/lib/.keep b/src/lib/.keep new file mode 100644 index 0000000..7554f8b --- /dev/null +++ b/src/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. diff --git a/src/resource.ts b/src/resource.ts new file mode 100644 index 0000000..363e351 --- /dev/null +++ b/src/resource.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/resource instead */ +export * from './core/resource'; diff --git a/src/resources.ts b/src/resources.ts new file mode 100644 index 0000000..b283d57 --- /dev/null +++ b/src/resources.ts @@ -0,0 +1 @@ +export * from './resources/index'; diff --git a/src/resources/documents.ts b/src/resources/documents.ts new file mode 100644 index 0000000..6dcfade --- /dev/null +++ b/src/resources/documents.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './documents/index'; diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts new file mode 100644 index 0000000..991d6bd --- /dev/null +++ b/src/resources/documents/documents.ts @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1/v1'; +import { V1, V1RetrieveResponse } from './v1/v1'; + +export class Documents extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); +} + +Documents.V1 = V1; + +export declare namespace Documents { + export { V1 as V1, type V1RetrieveResponse as V1RetrieveResponse }; +} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts new file mode 100644 index 0000000..2703c77 --- /dev/null +++ b/src/resources/documents/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Documents } from './documents'; +export { V1, type V1RetrieveResponse } from './v1/index'; diff --git a/src/resources/documents/v1.ts b/src/resources/documents/v1.ts new file mode 100644 index 0000000..d02995c --- /dev/null +++ b/src/resources/documents/v1.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './v1/index'; diff --git a/src/resources/documents/v1/generate.ts b/src/resources/documents/v1/generate.ts new file mode 100644 index 0000000..64126bf --- /dev/null +++ b/src/resources/documents/v1/generate.ts @@ -0,0 +1,118 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class Generate extends APIResource { + /** + * Generate PDF document from JSON design, HTML content, or URL. + */ + create( + body: GenerateCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/', { body, ...options }); + } + + /** + * Generate PDF document from an existing template with merge tags. + */ + createFromTemplate( + body: GenerateCreateFromTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/template/', { body, ...options }); + } +} + +export interface GenerateCreateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface GenerateCreateFromTemplateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface GenerateCreateParams { + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * HTML content to convert to PDF + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * URL to convert to PDF + */ + url?: string; +} + +export interface GenerateCreateFromTemplateParams { + /** + * ID of the template to use for generation + */ + templateId: string; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Generate { + export { + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateFromTemplateResponse as GenerateCreateFromTemplateResponse, + type GenerateCreateParams as GenerateCreateParams, + type GenerateCreateFromTemplateParams as GenerateCreateFromTemplateParams, + }; +} diff --git a/src/resources/documents/v1/index.ts b/src/resources/documents/v1/index.ts new file mode 100644 index 0000000..2aa59e3 --- /dev/null +++ b/src/resources/documents/v1/index.ts @@ -0,0 +1,10 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Generate, + type GenerateCreateResponse, + type GenerateCreateFromTemplateResponse, + type GenerateCreateParams, + type GenerateCreateFromTemplateParams, +} from './generate'; +export { V1, type V1RetrieveResponse } from './v1'; diff --git a/src/resources/documents/v1/v1.ts b/src/resources/documents/v1/v1.ts new file mode 100644 index 0000000..0571c5b --- /dev/null +++ b/src/resources/documents/v1/v1.ts @@ -0,0 +1,81 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as GenerateAPI from './generate'; +import { + Generate, + GenerateCreateFromTemplateParams, + GenerateCreateFromTemplateResponse, + GenerateCreateParams, + GenerateCreateResponse, +} from './generate'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class V1 extends APIResource { + generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); + + /** + * Retrieve details of a previously generated document. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}/`, options); + } +} + +export interface V1RetrieveResponse { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; +} + +V1.Generate = Generate; + +export declare namespace V1 { + export { type V1RetrieveResponse as V1RetrieveResponse }; + + export { + Generate as Generate, + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateFromTemplateResponse as GenerateCreateFromTemplateResponse, + type GenerateCreateParams as GenerateCreateParams, + type GenerateCreateFromTemplateParams as GenerateCreateFromTemplateParams, + }; +} diff --git a/src/resources/emails.ts b/src/resources/emails.ts new file mode 100644 index 0000000..bd0ec59 --- /dev/null +++ b/src/resources/emails.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './emails/index'; diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts new file mode 100644 index 0000000..b324159 --- /dev/null +++ b/src/resources/emails/emails.ts @@ -0,0 +1,20 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1/v1'; +import { V1, V1RenderParams, V1RenderResponse, V1RetrieveResponse } from './v1/v1'; + +export class Emails extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); +} + +Emails.V1 = V1; + +export declare namespace Emails { + export { + V1 as V1, + type V1RetrieveResponse as V1RetrieveResponse, + type V1RenderResponse as V1RenderResponse, + type V1RenderParams as V1RenderParams, + }; +} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts new file mode 100644 index 0000000..dc35058 --- /dev/null +++ b/src/resources/emails/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Emails } from './emails'; +export { V1, type V1RetrieveResponse, type V1RenderResponse, type V1RenderParams } from './v1/index'; diff --git a/src/resources/emails/v1.ts b/src/resources/emails/v1.ts new file mode 100644 index 0000000..d02995c --- /dev/null +++ b/src/resources/emails/v1.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './v1/index'; diff --git a/src/resources/emails/v1/index.ts b/src/resources/emails/v1/index.ts new file mode 100644 index 0000000..e28438b --- /dev/null +++ b/src/resources/emails/v1/index.ts @@ -0,0 +1,10 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Send, + type SendSendResponse, + type SendSendFromTemplateResponse, + type SendSendParams, + type SendSendFromTemplateParams, +} from './send'; +export { V1, type V1RetrieveResponse, type V1RenderResponse, type V1RenderParams } from './v1'; diff --git a/src/resources/emails/v1/send.ts b/src/resources/emails/v1/send.ts new file mode 100644 index 0000000..aba8ff6 --- /dev/null +++ b/src/resources/emails/v1/send.ts @@ -0,0 +1,100 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class Send extends APIResource { + /** + * Send email with design JSON or HTML content. + */ + send(body: SendSendParams, options?: RequestOptions): APIPromise { + return this._client.post('/emails/v1/send/', { body, ...options }); + } + + /** + * Send email using an existing template with merge tags. + */ + sendFromTemplate( + body: SendSendFromTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send/template/', { body, ...options }); + } +} + +export interface SendSendResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface SendSendFromTemplateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface SendSendParams { + /** + * Recipient email address + */ + to: string; + + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * HTML content to send + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line + */ + subject?: string; +} + +export interface SendSendFromTemplateParams { + /** + * ID of the template to use + */ + templateId: string; + + /** + * Recipient email address + */ + to: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +export declare namespace Send { + export { + type SendSendResponse as SendSendResponse, + type SendSendFromTemplateResponse as SendSendFromTemplateResponse, + type SendSendParams as SendSendParams, + type SendSendFromTemplateParams as SendSendFromTemplateParams, + }; +} diff --git a/src/resources/emails/v1/v1.ts b/src/resources/emails/v1/v1.ts new file mode 100644 index 0000000..40daab2 --- /dev/null +++ b/src/resources/emails/v1/v1.ts @@ -0,0 +1,101 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as SendAPI from './send'; +import { + Send, + SendSendFromTemplateParams, + SendSendFromTemplateResponse, + SendSendParams, + SendSendResponse, +} from './send'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class V1 extends APIResource { + send: SendAPI.Send = new SendAPI.Send(this._client); + + /** + * Retrieve details of a previously sent email. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}/`, options); + } + + /** + * Convert design JSON to HTML with optional merge tags. + */ + render(body: V1RenderParams, options?: RequestOptions): APIPromise { + return this._client.post('/emails/v1/render/', { body, ...options }); + } +} + +export interface V1RetrieveResponse { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; +} + +export interface V1RenderResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface V1RenderParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +V1.Send = Send; + +export declare namespace V1 { + export { + type V1RetrieveResponse as V1RetrieveResponse, + type V1RenderResponse as V1RenderResponse, + type V1RenderParams as V1RenderParams, + }; + + export { + Send as Send, + type SendSendResponse as SendSendResponse, + type SendSendFromTemplateResponse as SendSendFromTemplateResponse, + type SendSendParams as SendSendParams, + type SendSendFromTemplateParams as SendSendFromTemplateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts new file mode 100644 index 0000000..5a6059e --- /dev/null +++ b/src/resources/index.ts @@ -0,0 +1,6 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Documents } from './documents/documents'; +export { Emails } from './emails/emails'; +export { Pages } from './pages/pages'; +export { Project } from './project/project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts new file mode 100644 index 0000000..c218cbe --- /dev/null +++ b/src/resources/pages.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './pages/index'; diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts new file mode 100644 index 0000000..3ec0047 --- /dev/null +++ b/src/resources/pages/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Pages } from './pages'; +export { V1, type V1RenderResponse, type V1RenderParams } from './v1'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts new file mode 100644 index 0000000..d93f869 --- /dev/null +++ b/src/resources/pages/pages.ts @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1'; +import { V1, V1RenderParams, V1RenderResponse } from './v1'; + +export class Pages extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); +} + +Pages.V1 = V1; + +export declare namespace Pages { + export { V1 as V1, type V1RenderResponse as V1RenderResponse, type V1RenderParams as V1RenderParams }; +} diff --git a/src/resources/pages/v1.ts b/src/resources/pages/v1.ts new file mode 100644 index 0000000..d2ccfe8 --- /dev/null +++ b/src/resources/pages/v1.ts @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class V1 extends APIResource { + /** + * Convert page design JSON to HTML with optional merge tags. + */ + render(body: V1RenderParams, options?: RequestOptions): APIPromise { + return this._client.post('/pages/v1/render/', { body, ...options }); + } +} + +export interface V1RenderResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface V1RenderParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace V1 { + export { type V1RenderResponse as V1RenderResponse, type V1RenderParams as V1RenderParams }; +} diff --git a/src/resources/project.ts b/src/resources/project.ts new file mode 100644 index 0000000..60fc38d --- /dev/null +++ b/src/resources/project.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './project/index'; diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts new file mode 100644 index 0000000..ee7bdc4 --- /dev/null +++ b/src/resources/project/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Project } from './project'; +export { V1, type V1GetCurrentResponse } from './v1/index'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts new file mode 100644 index 0000000..568bb2a --- /dev/null +++ b/src/resources/project/project.ts @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1/v1'; +import { V1, V1GetCurrentResponse } from './v1/v1'; + +export class Project extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); +} + +Project.V1 = V1; + +export declare namespace Project { + export { V1 as V1, type V1GetCurrentResponse as V1GetCurrentResponse }; +} diff --git a/src/resources/project/v1.ts b/src/resources/project/v1.ts new file mode 100644 index 0000000..d02995c --- /dev/null +++ b/src/resources/project/v1.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './v1/index'; diff --git a/src/resources/project/v1/api-keys.ts b/src/resources/project/v1/api-keys.ts new file mode 100644 index 0000000..5b8388e --- /dev/null +++ b/src/resources/project/v1/api-keys.ts @@ -0,0 +1,177 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { buildHeaders } from '../../../internal/headers'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class APIKeys extends APIResource { + /** + * Create a new API key for the project. + */ + create(body: APIKeyCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/project/v1/api-keys/', { body, ...options }); + } + + /** + * Get API key details by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/api-keys/${id}/`, options); + } + + /** + * Update API key settings. + */ + update( + id: string, + body: APIKeyUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/api-keys/${id}/`, { body, ...options }); + } + + /** + * List all API keys for the project. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/api-keys/', options); + } + + /** + * Revoke API key. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/api-keys/${id}/`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface APIKeyCreateResponse { + data?: APIKeyCreateResponse.Data; +} + +export namespace APIKeyCreateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + name?: string; + } +} + +export interface APIKeyRetrieveResponse { + data?: APIKeyRetrieveResponse.Data; +} + +export namespace APIKeyRetrieveResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface APIKeyUpdateResponse { + data?: APIKeyUpdateResponse.Data; +} + +export namespace APIKeyUpdateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface APIKeyListResponse { + data?: Array; +} + +export namespace APIKeyListResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface APIKeyCreateParams { + /** + * Name for the API key + */ + name: string; + + /** + * Allowed domains for this API key + */ + domains?: Array; +} + +export interface APIKeyUpdateParams { + /** + * Whether the API key is active + */ + active?: boolean; + + /** + * Updated allowed domains + */ + domains?: Array; + + /** + * Updated name for the API key + */ + name?: string; +} + +export declare namespace APIKeys { + export { + type APIKeyCreateResponse as APIKeyCreateResponse, + type APIKeyRetrieveResponse as APIKeyRetrieveResponse, + type APIKeyUpdateResponse as APIKeyUpdateResponse, + type APIKeyListResponse as APIKeyListResponse, + type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyUpdateParams as APIKeyUpdateParams, + }; +} diff --git a/src/resources/project/v1/domains.ts b/src/resources/project/v1/domains.ts new file mode 100644 index 0000000..38dc6c2 --- /dev/null +++ b/src/resources/project/v1/domains.ts @@ -0,0 +1,148 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { buildHeaders } from '../../../internal/headers'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Domains extends APIResource { + /** + * Add a new domain to the project. + */ + create(body: DomainCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/project/v1/domains/', { body, ...options }); + } + + /** + * Get domain details by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}/`, options); + } + + /** + * Update domain settings. + */ + update( + id: string, + body: DomainUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}/`, { body, ...options }); + } + + /** + * List all domains for the project. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains/', options); + } + + /** + * Remove domain from project. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}/`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface DomainCreateResponse { + data?: DomainCreateResponse.Data; +} + +export namespace DomainCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainRetrieveResponse { + data?: DomainRetrieveResponse.Data; +} + +export namespace DomainRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainUpdateResponse { + data?: DomainUpdateResponse.Data; +} + +export namespace DomainUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainListResponse { + data?: Array; +} + +export namespace DomainListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface DomainCreateParams { + /** + * Domain name to add + */ + domain: string; +} + +export interface DomainUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export declare namespace Domains { + export { + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainUpdateResponse as DomainUpdateResponse, + type DomainListResponse as DomainListResponse, + type DomainCreateParams as DomainCreateParams, + type DomainUpdateParams as DomainUpdateParams, + }; +} diff --git a/src/resources/project/v1/index.ts b/src/resources/project/v1/index.ts new file mode 100644 index 0000000..3677d68 --- /dev/null +++ b/src/resources/project/v1/index.ts @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + APIKeys, + type APIKeyCreateResponse, + type APIKeyRetrieveResponse, + type APIKeyUpdateResponse, + type APIKeyListResponse, + type APIKeyCreateParams, + type APIKeyUpdateParams, +} from './api-keys'; +export { + Domains, + type DomainCreateResponse, + type DomainRetrieveResponse, + type DomainUpdateResponse, + type DomainListResponse, + type DomainCreateParams, + type DomainUpdateParams, +} from './domains'; +export { + Templates, + type TemplateCreateResponse, + type TemplateRetrieveResponse, + type TemplateUpdateResponse, + type TemplateListResponse, + type TemplateCreateParams, + type TemplateUpdateParams, +} from './templates'; +export { V1, type V1GetCurrentResponse } from './v1'; diff --git a/src/resources/project/v1/templates.ts b/src/resources/project/v1/templates.ts new file mode 100644 index 0000000..b8e29a3 --- /dev/null +++ b/src/resources/project/v1/templates.ts @@ -0,0 +1,176 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { buildHeaders } from '../../../internal/headers'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Templates extends APIResource { + /** + * Create a new project template. + */ + create(body: TemplateCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/project/v1/templates/', { body, ...options }); + } + + /** + * Get project template by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}/`, options); + } + + /** + * Update project template. + */ + update( + id: string, + body: TemplateUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}/`, { body, ...options }); + } + + /** + * Get all project templates. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates/', options); + } + + /** + * Delete project template. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}/`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface TemplateCreateResponse { + data?: TemplateCreateResponse.Data; +} + +export namespace TemplateCreateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateRetrieveResponse { + data?: TemplateRetrieveResponse.Data; +} + +export namespace TemplateRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateUpdateResponse { + data?: TemplateUpdateResponse.Data; +} + +export namespace TemplateUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateListResponse { + data?: Array; +} + +export namespace TemplateListResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateCreateParams { + /** + * Template name + */ + name: string; + + /** + * Email body content + */ + body?: string; + + /** + * Email subject line + */ + subject?: string; +} + +export interface TemplateUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +export declare namespace Templates { + export { + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateUpdateResponse as TemplateUpdateResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateCreateParams as TemplateCreateParams, + type TemplateUpdateParams as TemplateUpdateParams, + }; +} diff --git a/src/resources/project/v1/v1.ts b/src/resources/project/v1/v1.ts new file mode 100644 index 0000000..03405f8 --- /dev/null +++ b/src/resources/project/v1/v1.ts @@ -0,0 +1,112 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as APIKeysAPI from './api-keys'; +import { + APIKeyCreateParams, + APIKeyCreateResponse, + APIKeyListResponse, + APIKeyRetrieveResponse, + APIKeyUpdateParams, + APIKeyUpdateResponse, + APIKeys, +} from './api-keys'; +import * as DomainsAPI from './domains'; +import { + DomainCreateParams, + DomainCreateResponse, + DomainListResponse, + DomainRetrieveResponse, + DomainUpdateParams, + DomainUpdateResponse, + Domains, +} from './domains'; +import * as TemplatesAPI from './templates'; +import { + TemplateCreateParams, + TemplateCreateResponse, + TemplateListResponse, + TemplateRetrieveResponse, + TemplateUpdateParams, + TemplateUpdateResponse, + Templates, +} from './templates'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class V1 extends APIResource { + apiKeys: APIKeysAPI.APIKeys = new APIKeysAPI.APIKeys(this._client); + domains: DomainsAPI.Domains = new DomainsAPI.Domains(this._client); + templates: TemplatesAPI.Templates = new TemplatesAPI.Templates(this._client); + + /** + * Get project details for the authenticated project. + */ + getCurrent(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current/', options); + } +} + +export interface V1GetCurrentResponse { + data?: V1GetCurrentResponse.Data; +} + +export namespace V1GetCurrentResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +V1.APIKeys = APIKeys; +V1.Domains = Domains; +V1.Templates = Templates; + +export declare namespace V1 { + export { type V1GetCurrentResponse as V1GetCurrentResponse }; + + export { + APIKeys as APIKeys, + type APIKeyCreateResponse as APIKeyCreateResponse, + type APIKeyRetrieveResponse as APIKeyRetrieveResponse, + type APIKeyUpdateResponse as APIKeyUpdateResponse, + type APIKeyListResponse as APIKeyListResponse, + type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyUpdateParams as APIKeyUpdateParams, + }; + + export { + Domains as Domains, + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainUpdateResponse as DomainUpdateResponse, + type DomainListResponse as DomainListResponse, + type DomainCreateParams as DomainCreateParams, + type DomainUpdateParams as DomainUpdateParams, + }; + + export { + Templates as Templates, + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateUpdateResponse as TemplateUpdateResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateCreateParams as TemplateCreateParams, + type TemplateUpdateParams as TemplateUpdateParams, + }; +} diff --git a/src/uploads.ts b/src/uploads.ts new file mode 100644 index 0000000..b2ef647 --- /dev/null +++ b/src/uploads.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/uploads instead */ +export * from './core/uploads'; diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 0000000..ecebcdd --- /dev/null +++ b/src/version.ts @@ -0,0 +1 @@ +export const VERSION = '0.0.1'; diff --git a/tests/api-resources/documents/v1/generate.test.ts b/tests/api-resources/documents/v1/generate.test.ts new file mode 100644 index 0000000..affc37f --- /dev/null +++ b/tests/api-resources/documents/v1/generate.test.ts @@ -0,0 +1,60 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource generate', () => { + // Prism tests are disabled + test.skip('create', async () => { + const responsePromise = client.documents.v1.generate.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.documents.v1.generate.create( + { + design: {}, + filename: 'filename', + html: 'html', + mergeTags: { foo: 'string' }, + url: 'https://example.com', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + // Prism tests are disabled + test.skip('createFromTemplate: only required params', async () => { + const responsePromise = client.documents.v1.generate.createFromTemplate({ templateId: 'templateId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('createFromTemplate: required and optional params', async () => { + const response = await client.documents.v1.generate.createFromTemplate({ + templateId: 'templateId', + filename: 'filename', + mergeTags: { foo: 'string' }, + }); + }); +}); diff --git a/tests/api-resources/documents/v1/v1.test.ts b/tests/api-resources/documents/v1/v1.test.ts new file mode 100644 index 0000000..538a6ed --- /dev/null +++ b/tests/api-resources/documents/v1/v1.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource v1', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.documents.v1.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/emails/v1/send.test.ts b/tests/api-resources/emails/v1/send.test.ts new file mode 100644 index 0000000..26872d8 --- /dev/null +++ b/tests/api-resources/emails/v1/send.test.ts @@ -0,0 +1,58 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource send', () => { + // Prism tests are disabled + test.skip('send: only required params', async () => { + const responsePromise = client.emails.v1.send.send({ to: 'dev@stainless.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('send: required and optional params', async () => { + const response = await client.emails.v1.send.send({ + to: 'dev@stainless.com', + design: {}, + html: 'html', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); + + // Prism tests are disabled + test.skip('sendFromTemplate: only required params', async () => { + const responsePromise = client.emails.v1.send.sendFromTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('sendFromTemplate: required and optional params', async () => { + const response = await client.emails.v1.send.sendFromTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); +}); diff --git a/tests/api-resources/emails/v1/v1.test.ts b/tests/api-resources/emails/v1/v1.test.ts new file mode 100644 index 0000000..2296fd8 --- /dev/null +++ b/tests/api-resources/emails/v1/v1.test.ts @@ -0,0 +1,39 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource v1', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.emails.v1.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('render: only required params', async () => { + const responsePromise = client.emails.v1.render({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('render: required and optional params', async () => { + const response = await client.emails.v1.render({ design: {}, mergeTags: { foo: 'string' } }); + }); +}); diff --git a/tests/api-resources/pages/v1.test.ts b/tests/api-resources/pages/v1.test.ts new file mode 100644 index 0000000..3dbe14f --- /dev/null +++ b/tests/api-resources/pages/v1.test.ts @@ -0,0 +1,27 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource v1', () => { + // Prism tests are disabled + test.skip('render: only required params', async () => { + const responsePromise = client.pages.v1.render({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('render: required and optional params', async () => { + const response = await client.pages.v1.render({ design: {}, mergeTags: { foo: 'string' } }); + }); +}); diff --git a/tests/api-resources/project/v1/api-keys.test.ts b/tests/api-resources/project/v1/api-keys.test.ts new file mode 100644 index 0000000..007ac27 --- /dev/null +++ b/tests/api-resources/project/v1/api-keys.test.ts @@ -0,0 +1,87 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource apiKeys', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.project.v1.apiKeys.create({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.project.v1.apiKeys.create({ name: 'name', domains: ['string'] }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.project.v1.apiKeys.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.project.v1.apiKeys.update('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.v1.apiKeys.update( + 'id', + { active: true, domains: ['string'], name: 'name' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.project.v1.apiKeys.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.project.v1.apiKeys.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/project/v1/domains.test.ts b/tests/api-resources/project/v1/domains.test.ts new file mode 100644 index 0000000..1e0e635 --- /dev/null +++ b/tests/api-resources/project/v1/domains.test.ts @@ -0,0 +1,83 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource domains', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.project.v1.domains.create({ domain: 'domain' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.project.v1.domains.create({ domain: 'domain' }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.project.v1.domains.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.project.v1.domains.update('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.v1.domains.update('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.project.v1.domains.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.project.v1.domains.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/project/v1/templates.test.ts b/tests/api-resources/project/v1/templates.test.ts new file mode 100644 index 0000000..b8f0682 --- /dev/null +++ b/tests/api-resources/project/v1/templates.test.ts @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource templates', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.project.v1.templates.create({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.project.v1.templates.create({ + name: 'name', + body: 'body', + subject: 'subject', + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.project.v1.templates.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.project.v1.templates.update('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.v1.templates.update( + 'id', + { body: 'body', name: 'name', subject: 'subject' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.project.v1.templates.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.project.v1.templates.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/project/v1/v1.test.ts b/tests/api-resources/project/v1/v1.test.ts new file mode 100644 index 0000000..76cb40c --- /dev/null +++ b/tests/api-resources/project/v1/v1.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from 'unlayer'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource v1', () => { + // Prism tests are disabled + test.skip('getCurrent', async () => { + const responsePromise = client.project.v1.getCurrent(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/base64.test.ts b/tests/base64.test.ts new file mode 100644 index 0000000..5566771 --- /dev/null +++ b/tests/base64.test.ts @@ -0,0 +1,80 @@ +import { fromBase64, toBase64 } from 'unlayer/internal/utils/base64'; + +describe.each(['Buffer', 'atob'])('with %s', (mode) => { + let originalBuffer: BufferConstructor; + beforeAll(() => { + if (mode === 'atob') { + originalBuffer = globalThis.Buffer; + // @ts-expect-error Can't assign undefined to BufferConstructor + delete globalThis.Buffer; + } + }); + afterAll(() => { + if (mode === 'atob') { + globalThis.Buffer = originalBuffer; + } + }); + test('toBase64', () => { + const testCases = [ + { + input: 'hello world', + expected: 'aGVsbG8gd29ybGQ=', + }, + { + input: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), + expected: 'aGVsbG8gd29ybGQ=', + }, + { + input: undefined, + expected: '', + }, + { + input: new Uint8Array([ + 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, + 193, 71, + ]), + expected: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', + }, + { + input: '✓', + expected: '4pyT', + }, + { + input: new Uint8Array([226, 156, 147]), + expected: '4pyT', + }, + ]; + + testCases.forEach(({ input, expected }) => { + expect(toBase64(input)).toBe(expected); + }); + }); + + test('fromBase64', () => { + const testCases = [ + { + input: 'aGVsbG8gd29ybGQ=', + expected: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), + }, + { + input: '', + expected: new Uint8Array([]), + }, + { + input: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', + expected: new Uint8Array([ + 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, + 193, 71, + ]), + }, + { + input: '4pyT', + expected: new Uint8Array([226, 156, 147]), + }, + ]; + + testCases.forEach(({ input, expected }) => { + expect(fromBase64(input)).toEqual(expected); + }); + }); +}); diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts new file mode 100644 index 0000000..385421a --- /dev/null +++ b/tests/buildHeaders.test.ts @@ -0,0 +1,88 @@ +import { inspect } from 'node:util'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from 'unlayer/internal/headers'; + +function inspectNullableHeaders(headers: NullableHeaders) { + return `NullableHeaders {${[ + ...[...headers.values.entries()].map(([name, value]) => ` ${inspect(name)}: ${inspect(value)}`), + ...[...headers.nulls].map((name) => ` ${inspect(name)}: null`), + ].join(', ')} }`; +} + +describe('buildHeaders', () => { + const cases: [HeadersLike[], string][] = [ + [[new Headers({ 'content-type': 'text/plain' })], `NullableHeaders { 'content-type': 'text/plain' }`], + [ + [ + { + 'content-type': 'text/plain', + }, + { + 'Content-Type': undefined, + }, + ], + `NullableHeaders { 'content-type': 'text/plain' }`, + ], + [ + [ + { + 'content-type': 'text/plain', + }, + { + 'Content-Type': null, + }, + ], + `NullableHeaders { 'content-type': null }`, + ], + [ + [ + { + cookie: 'name1=value1', + Cookie: 'name2=value2', + }, + ], + `NullableHeaders { 'cookie': 'name2=value2' }`, + ], + [ + [ + { + cookie: 'name1=value1', + Cookie: undefined, + }, + ], + `NullableHeaders { 'cookie': 'name1=value1' }`, + ], + [ + [ + { + cookie: ['name1=value1', 'name2=value2'], + }, + ], + `NullableHeaders { 'cookie': 'name1=value1; name2=value2' }`, + ], + [ + [ + { + 'x-foo': ['name1=value1', 'name2=value2'], + }, + ], + `NullableHeaders { 'x-foo': 'name1=value1, name2=value2' }`, + ], + [ + [ + [ + ['cookie', 'name1=value1'], + ['cookie', 'name2=value2'], + ['Cookie', 'name3=value3'], + ], + ], + `NullableHeaders { 'cookie': 'name1=value1; name2=value2; name3=value3' }`, + ], + [[undefined], `NullableHeaders { }`], + [[null], `NullableHeaders { }`], + ]; + for (const [input, expected] of cases) { + test(expected, () => { + expect(inspectNullableHeaders(buildHeaders(input))).toEqual(expected); + }); + } +}); diff --git a/tests/form.test.ts b/tests/form.test.ts new file mode 100644 index 0000000..59ce14f --- /dev/null +++ b/tests/form.test.ts @@ -0,0 +1,85 @@ +import { multipartFormRequestOptions, createForm } from 'unlayer/internal/uploads'; +import { toFile } from 'unlayer/core/uploads'; + +describe('form data validation', () => { + test('valid values do not error', async () => { + await multipartFormRequestOptions( + { + body: { + foo: 'foo', + string: 1, + bool: true, + file: await toFile(Buffer.from('some-content')), + blob: new Blob(['Some content'], { type: 'text/plain' }), + }, + }, + fetch, + ); + }); + + test('null', async () => { + await expect(() => + multipartFormRequestOptions( + { + body: { + null: null, + }, + }, + fetch, + ), + ).rejects.toThrow(TypeError); + }); + + test('undefined is stripped', async () => { + const form = await createForm( + { + foo: undefined, + bar: 'baz', + }, + fetch, + ); + expect(form.has('foo')).toBe(false); + expect(form.get('bar')).toBe('baz'); + }); + + test('nested undefined property is stripped', async () => { + const form = await createForm( + { + bar: { + baz: undefined, + }, + }, + fetch, + ); + expect(Array.from(form.entries())).toEqual([]); + + const form2 = await createForm( + { + bar: { + foo: 'string', + baz: undefined, + }, + }, + fetch, + ); + expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]); + }); + + test('nested undefined array item is stripped', async () => { + const form = await createForm( + { + bar: [undefined, undefined], + }, + fetch, + ); + expect(Array.from(form.entries())).toEqual([]); + + const form2 = await createForm( + { + bar: [undefined, 'foo'], + }, + fetch, + ); + expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]); + }); +}); diff --git a/tests/index.test.ts b/tests/index.test.ts new file mode 100644 index 0000000..1165c4d --- /dev/null +++ b/tests/index.test.ts @@ -0,0 +1,722 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIPromise } from 'unlayer/core/api-promise'; + +import util from 'node:util'; +import Unlayer from 'unlayer'; +import { APIUserAbortError } from 'unlayer'; +const defaultFetch = fetch; + +describe('instantiate client', () => { + const env = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...env }; + }); + + afterEach(() => { + process.env = env; + }); + + describe('defaultHeaders', () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-My-Default-Header': '2' }, + apiKey: 'My API Key', + }); + + test('they are used in the request', async () => { + const { req } = await client.buildRequest({ path: '/foo', method: 'post' }); + expect(req.headers.get('x-my-default-header')).toEqual('2'); + }); + + test('can ignore `undefined` and leave the default', async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + headers: { 'X-My-Default-Header': undefined }, + }); + expect(req.headers.get('x-my-default-header')).toEqual('2'); + }); + + test('can be removed with `null`', async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + headers: { 'X-My-Default-Header': null }, + }); + expect(req.headers.has('x-my-default-header')).toBe(false); + }); + }); + describe('logging', () => { + const env = process.env; + + beforeEach(() => { + process.env = { ...env }; + process.env['UNLAYER_LOG'] = undefined; + }); + + afterEach(() => { + process.env = env; + }); + + const forceAPIResponseForClient = async (client: Unlayer) => { + await new APIPromise( + client, + Promise.resolve({ + response: new Response(), + controller: new AbortController(), + requestLogID: 'log_000000', + retryOfRequestLogID: undefined, + startTime: Date.now(), + options: { + method: 'get', + path: '/', + }, + }), + ); + }; + + test('debug logs when log level is debug', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); + + test('default logLevel is warn', async () => { + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + }); + + test('debug logs are skipped when log level is info', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + const client = new Unlayer({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); + + test('debug logs happen with debug env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + process.env['UNLAYER_LOG'] = 'debug'; + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); + + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); + + test('warn when env var level is invalid', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; + + process.env['UNLAYER_LOG'] = 'not a log level'; + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + expect(warnMock).toHaveBeenCalledWith( + 'process.env[\'UNLAYER_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', + ); + }); + + test('client log level overrides env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + process.env['UNLAYER_LOG'] = 'debug'; + const client = new Unlayer({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); + + test('no warning logged for invalid env var level + valid client level', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; + + process.env['UNLAYER_LOG'] = 'not a log level'; + const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); + expect(warnMock).not.toHaveBeenCalled(); + }); + }); + + describe('defaultQuery', () => { + test('with null query params given', () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); + }); + + test('multiple default query params', () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo', hello: 'world' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); + }); + + test('overriding with `undefined`', () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultQuery: { hello: 'world' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); + }); + }); + + test('custom fetch', async () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: (url) => { + return Promise.resolve( + new Response(JSON.stringify({ url, custom: true }), { + headers: { 'Content-Type': 'application/json' }, + }), + ); + }, + }); + + const response = await client.get('/foo'); + expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true }); + }); + + test('explicit global fetch', async () => { + // make sure the global fetch type is assignable to our Fetch type + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, + }); + }); + + test('custom signal', async () => { + const client = new Unlayer({ + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', + fetch: (...args) => { + return new Promise((resolve, reject) => + setTimeout( + () => + defaultFetch(...args) + .then(resolve) + .catch(reject), + 300, + ), + ); + }, + }); + + const controller = new AbortController(); + setTimeout(() => controller.abort(), 200); + + const spy = jest.spyOn(client, 'request'); + + await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError); + expect(spy).toHaveBeenCalledTimes(1); + }); + + test('normalized method', async () => { + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + capturedRequest = init; + return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Unlayer({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + + await client.patch('/foo'); + expect(capturedRequest?.method).toEqual('PATCH'); + }); + + describe('baseUrl', () => { + test('trailing slash', () => { + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); + }); + + test('no trailing slash', () => { + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); + }); + + afterEach(() => { + process.env['UNLAYER_BASE_URL'] = undefined; + }); + + test('explicit option', () => { + const client = new Unlayer({ baseURL: 'https://example.com', apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://example.com'); + }); + + test('env variable', () => { + process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://example.com/from_env'); + }); + + test('empty env variable', () => { + process.env['UNLAYER_BASE_URL'] = ''; // empty + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://api.unlayer.com'); + }); + + test('blank env variable', () => { + process.env['UNLAYER_BASE_URL'] = ' '; // blank + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://api.unlayer.com'); + }); + + test('in request options', () => { + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/option/foo', + ); + }); + + test('in request options overridden by client options', () => { + const client = new Unlayer({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/client/foo', + ); + }); + + test('in request options overridden by env variable', () => { + process.env['UNLAYER_BASE_URL'] = 'http://localhost:5000/env'; + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/env/foo', + ); + }); + }); + + test('maxRetries option is correctly set', () => { + const client = new Unlayer({ maxRetries: 4, apiKey: 'My API Key' }); + expect(client.maxRetries).toEqual(4); + + // default + const client2 = new Unlayer({ apiKey: 'My API Key' }); + expect(client2.maxRetries).toEqual(2); + }); + + describe('withOptions', () => { + test('creates a new client with overridden options', async () => { + const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + + const newClient = client.withOptions({ + maxRetries: 5, + baseURL: 'http://localhost:5001/', + }); + + // Verify the new client has updated options + expect(newClient.maxRetries).toEqual(5); + expect(newClient.baseURL).toEqual('http://localhost:5001/'); + + // Verify the original client is unchanged + expect(client.maxRetries).toEqual(3); + expect(client.baseURL).toEqual('http://localhost:5000/'); + + // Verify it's a different instance + expect(newClient).not.toBe(client); + expect(newClient.constructor).toBe(client.constructor); + }); + + test('inherits options from the parent client', async () => { + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-Test-Header': 'test-value' }, + defaultQuery: { 'test-param': 'test-value' }, + apiKey: 'My API Key', + }); + + const newClient = client.withOptions({ + baseURL: 'http://localhost:5001/', + }); + + // Test inherited options remain the same + expect(newClient.buildURL('/foo', null)).toEqual('http://localhost:5001/foo?test-param=test-value'); + + const { req } = await newClient.buildRequest({ path: '/foo', method: 'get' }); + expect(req.headers.get('x-test-header')).toEqual('test-value'); + }); + + test('respects runtime property changes when creating new client', () => { + const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + + // Modify the client properties directly after creation + client.baseURL = 'http://localhost:6000/'; + client.timeout = 2000; + + // Create a new client with withOptions + const newClient = client.withOptions({ + maxRetries: 10, + }); + + // Verify the new client uses the updated properties, not the original ones + expect(newClient.baseURL).toEqual('http://localhost:6000/'); + expect(newClient.timeout).toEqual(2000); + expect(newClient.maxRetries).toEqual(10); + + // Original client should still have its modified properties + expect(client.baseURL).toEqual('http://localhost:6000/'); + expect(client.timeout).toEqual(2000); + expect(client.maxRetries).not.toEqual(10); + + // Verify URL building uses the updated baseURL + expect(newClient.buildURL('/bar', null)).toEqual('http://localhost:6000/bar'); + }); + }); + + test('with environment variable arguments', () => { + // set options via env var + process.env['UNLAYER_API_KEY'] = 'My API Key'; + const client = new Unlayer(); + expect(client.apiKey).toBe('My API Key'); + }); + + test('with overridden environment variable arguments', () => { + // set options via env var + process.env['UNLAYER_API_KEY'] = 'another My API Key'; + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.apiKey).toBe('My API Key'); + }); +}); + +describe('request building', () => { + const client = new Unlayer({ apiKey: 'My API Key' }); + + describe('custom headers', () => { + test('handles undefined', async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + body: { value: 'hello' }, + headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null }, + }); + expect(req.headers.get('x-foo')).toEqual('bar'); + expect(req.headers.get('x-Foo')).toEqual('bar'); + expect(req.headers.get('X-Foo')).toEqual('bar'); + expect(req.headers.get('x-baz')).toEqual(null); + }); + }); +}); + +describe('default encoder', () => { + const client = new Unlayer({ apiKey: 'My API Key' }); + + class Serializable { + toJSON() { + return { $type: 'Serializable' }; + } + } + class Collection { + #things: T[]; + constructor(things: T[]) { + this.#things = Array.from(things); + } + toJSON() { + return Array.from(this.#things); + } + [Symbol.iterator]() { + return this.#things[Symbol.iterator]; + } + } + for (const jsonValue of [{}, [], { __proto__: null }, new Serializable(), new Collection(['item'])]) { + test(`serializes ${util.inspect(jsonValue)} as json`, async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + body: jsonValue, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual('application/json'); + expect(req.body).toBe(JSON.stringify(jsonValue)); + }); + } + + const encoder = new TextEncoder(); + const asyncIterable = (async function* () { + yield encoder.encode('a\n'); + yield encoder.encode('b\n'); + yield encoder.encode('c\n'); + })(); + for (const streamValue of [ + [encoder.encode('a\nb\nc\n')][Symbol.iterator](), + new Response('a\nb\nc\n').body, + asyncIterable, + ]) { + test(`converts ${util.inspect(streamValue)} to ReadableStream`, async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + body: streamValue, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual(null); + expect(req.body).toBeInstanceOf(ReadableStream); + expect(await new Response(req.body).text()).toBe('a\nb\nc\n'); + }); + } + + test(`can set content-type for ReadableStream`, async () => { + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + body: new Response('a\nb\nc\n').body, + headers: { 'Content-Type': 'text/plain' }, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual('text/plain'); + expect(req.body).toBeInstanceOf(ReadableStream); + expect(await new Response(req.body).text()).toBe('a\nb\nc\n'); + }); +}); + +describe('retries', () => { + test('retry on timeout', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Promise( + (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))), + ); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Unlayer({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + + test('retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('2'); + expect(count).toEqual(3); + }); + + test('omit retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + headers: { 'X-Stainless-Retry-Count': null }, + }), + ).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).has('x-stainless-retry-count')).toBe(false); + }); + + test('omit retry count header by default', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Unlayer({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + defaultHeaders: { 'X-Stainless-Retry-Count': null }, + }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + }), + ).toEqual({ a: 1 }); + + expect(capturedRequest!.headers as Headers).not.toHaveProperty('x-stainless-retry-count'); + }); + + test('overwrite retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + headers: { 'X-Stainless-Retry-Count': '42' }, + }), + ).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('42'); + }); + + test('retry on 429 with retry-after', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + + test('retry on 429 with retry-after-ms', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After-Ms': '10', + }, + }); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); +}); diff --git a/tests/path.test.ts b/tests/path.test.ts new file mode 100644 index 0000000..9f8f4b6 --- /dev/null +++ b/tests/path.test.ts @@ -0,0 +1,462 @@ +import { createPathTagFunction, encodeURIPath } from 'unlayer/internal/utils/path'; +import { inspect } from 'node:util'; +import { runInNewContext } from 'node:vm'; + +describe('path template tag function', () => { + test('validates input', () => { + const testParams = ['', '.', '..', 'x', '%2e', '%2E', '%2e%2e', '%2E%2e', '%2e%2E', '%2E%2E']; + const testCases = [ + ['/path_params/', '/a'], + ['/path_params/', '/'], + ['/path_params/', ''], + ['', '/a'], + ['', '/'], + ['', ''], + ['a'], + [''], + ['/path_params/', ':initiate'], + ['/path_params/', '.json'], + ['/path_params/', '?beta=true'], + ['/path_params/', '.?beta=true'], + ['/path_params/', '/', '/download'], + ['/path_params/', '-', '/download'], + ['/path_params/', '', '/download'], + ['/path_params/', '.', '/download'], + ['/path_params/', '..', '/download'], + ['/plain/path'], + ]; + + function paramPermutations(len: number): string[][] { + if (len === 0) return []; + if (len === 1) return testParams.map((e) => [e]); + const rest = paramPermutations(len - 1); + return testParams.flatMap((e) => rest.map((r) => [e, ...r])); + } + + // We need to test how %2E is handled, so we use a custom encoder that does no escaping. + const rawPath = createPathTagFunction((s) => s); + + const emptyObject = {}; + const mathObject = Math; + const numberObject = new Number(); + const stringObject = new String(); + const basicClass = new (class {})(); + const classWithToString = new (class { + toString() { + return 'ok'; + } + })(); + + // Invalid values + expect(() => rawPath`/a/${null}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Null is not a valid path parameter\n' + + '/a/null/b\n' + + ' ^^^^', + ); + expect(() => rawPath`/a/${undefined}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Undefined is not a valid path parameter\n' + + '/a/undefined/b\n' + + ' ^^^^^^^^^', + ); + expect(() => rawPath`/a/${emptyObject}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/a/[object Object]/b\n' + + ' ^^^^^^^^^^^^^^^', + ); + expect(() => rawPath`?${mathObject}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Math is not a valid path parameter\n' + + '?[object Math]\n' + + ' ^^^^^^^^^^^^^', + ); + expect(() => rawPath`/${basicClass}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/[object Object]\n' + + ' ^^^^^^^^^^^^^^', + ); + expect(() => rawPath`/../${''}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '/../\n' + + ' ^^', + ); + expect(() => rawPath`/../${{}}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + 'Value of type Object is not a valid path parameter\n' + + '/../[object Object]\n' + + ' ^^ ^^^^^^^^^^^^^^', + ); + + // Valid values + expect(rawPath`/${0}`).toBe('/0'); + expect(rawPath`/${''}`).toBe('/'); + expect(rawPath`/${numberObject}`).toBe('/0'); + expect(rawPath`${stringObject}/`).toBe('/'); + expect(rawPath`/${classWithToString}`).toBe('/ok'); + + // We need to check what happens with cross-realm values, which we might get from + // Jest or other frames in a browser. + + const newRealm = runInNewContext('globalThis'); + expect(newRealm.Object).not.toBe(Object); + + const crossRealmObject = newRealm.Object(); + const crossRealmMathObject = newRealm.Math; + const crossRealmNumber = new newRealm.Number(); + const crossRealmString = new newRealm.String(); + const crossRealmClass = new (class extends newRealm.Object {})(); + const crossRealmClassWithToString = new (class extends newRealm.Object { + toString() { + return 'ok'; + } + })(); + + // Invalid cross-realm values + expect(() => rawPath`/a/${crossRealmObject}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/a/[object Object]/b\n' + + ' ^^^^^^^^^^^^^^^', + ); + expect(() => rawPath`?${crossRealmMathObject}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Math is not a valid path parameter\n' + + '?[object Math]\n' + + ' ^^^^^^^^^^^^^', + ); + expect(() => rawPath`/${crossRealmClass}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/[object Object]\n' + + ' ^^^^^^^^^^^^^^^', + ); + + // Valid cross-realm values + expect(rawPath`/${crossRealmNumber}`).toBe('/0'); + expect(rawPath`${crossRealmString}/`).toBe('/'); + expect(rawPath`/${crossRealmClassWithToString}`).toBe('/ok'); + + const results: { + [pathParts: string]: { + [params: string]: { valid: boolean; result?: string; error?: string }; + }; + } = {}; + + for (const pathParts of testCases) { + const pathResults: Record = {}; + results[JSON.stringify(pathParts)] = pathResults; + for (const params of paramPermutations(pathParts.length - 1)) { + const stringRaw = String.raw({ raw: pathParts }, ...params); + const plainString = String.raw( + { raw: pathParts.map((e) => e.replace(/\./g, 'x')) }, + ...params.map((e) => 'X'.repeat(e.length)), + ); + const normalizedStringRaw = new URL(stringRaw, 'https://example.com').href; + const normalizedPlainString = new URL(plainString, 'https://example.com').href; + const pathResultsKey = JSON.stringify(params); + try { + const result = rawPath(pathParts, ...params); + expect(result).toBe(stringRaw); + // there are no special segments, so the length of the normalized path is + // equal to the length of the normalized plain path. + expect(normalizedStringRaw.length).toBe(normalizedPlainString.length); + pathResults[pathResultsKey] = { + valid: true, + result, + }; + } catch (e) { + const error = String(e); + expect(error).toMatch(/Path parameters result in path with invalid segment/); + // there are special segments, so the length of the normalized path is + // different than the length of the normalized plain path. + expect(normalizedStringRaw.length).not.toBe(normalizedPlainString.length); + pathResults[pathResultsKey] = { + valid: false, + error, + }; + } + } + } + + expect(results).toMatchObject({ + '["/path_params/","/a"]': { + '["x"]': { valid: true, result: '/path_params/x/a' }, + '[""]': { valid: true, result: '/path_params//a' }, + '["%2E%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E%2e/a\n' + + ' ^^^^^^', + }, + '["%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E/a\n' + + ' ^^^', + }, + }, + '["/path_params/","/"]': { + '["x"]': { valid: true, result: '/path_params/x/' }, + '[""]': { valid: true, result: '/path_params//' }, + '["%2e%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2e%2E/\n' + + ' ^^^^^^', + }, + '["%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + + '/path_params/%2e/\n' + + ' ^^^', + }, + }, + '["/path_params/",""]': { + '[""]': { valid: true, result: '/path_params/' }, + '["x"]': { valid: true, result: '/path_params/x' }, + '["%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E\n' + + ' ^^^', + }, + '["%2E%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E%2e\n' + + ' ^^^^^^', + }, + }, + '["","/a"]': { + '[""]': { valid: true, result: '/a' }, + '["x"]': { valid: true, result: 'x/a' }, + '["%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n%2E/a\n^^^', + }, + '["%2e%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + + '%2e%2E/a\n' + + '^^^^^^', + }, + }, + '["","/"]': { + '["x"]': { valid: true, result: 'x/' }, + '[""]': { valid: true, result: '/' }, + '["%2E%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + '%2E%2e/\n' + + '^^^^^^', + }, + '["."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + './\n^', + }, + }, + '["",""]': { + '[""]': { valid: true, result: '' }, + '["x"]': { valid: true, result: 'x' }, + '[".."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '..\n^^', + }, + '["."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + '.\n^', + }, + }, + '["a"]': {}, + '[""]': {}, + '["/path_params/",":initiate"]': { + '[""]': { valid: true, result: '/path_params/:initiate' }, + '["."]': { valid: true, result: '/path_params/.:initiate' }, + }, + '["/path_params/",".json"]': { + '["x"]': { valid: true, result: '/path_params/x.json' }, + '["."]': { valid: true, result: '/path_params/..json' }, + }, + '["/path_params/","?beta=true"]': { + '["x"]': { valid: true, result: '/path_params/x?beta=true' }, + '[""]': { valid: true, result: '/path_params/?beta=true' }, + '["%2E%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E%2E?beta=true\n' + + ' ^^^^^^', + }, + '["%2e%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2e%2E?beta=true\n' + + ' ^^^^^^', + }, + }, + '["/path_params/",".?beta=true"]': { + '[".."]': { valid: true, result: '/path_params/...?beta=true' }, + '["x"]': { valid: true, result: '/path_params/x.?beta=true' }, + '[""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + '/path_params/.?beta=true\n' + + ' ^', + }, + '["%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e." can\'t be safely passed as a path parameter\n' + + '/path_params/%2e.?beta=true\n' + + ' ^^^^', + }, + }, + '["/path_params/","/","/download"]': { + '["",""]': { valid: true, result: '/path_params///download' }, + '["","x"]': { valid: true, result: '/path_params//x/download' }, + '[".","%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + + '/path_params/./%2e/download\n' + + ' ^ ^^^', + }, + '["%2E%2e","%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E%2e/%2e/download\n' + + ' ^^^^^^ ^^^', + }, + }, + '["/path_params/","-","/download"]': { + '["","%2e"]': { valid: true, result: '/path_params/-%2e/download' }, + '["%2E",".."]': { valid: true, result: '/path_params/%2E-../download' }, + }, + '["/path_params/","","/download"]': { + '["%2E%2e","%2e%2E"]': { valid: true, result: '/path_params/%2E%2e%2e%2E/download' }, + '["%2E",".."]': { valid: true, result: '/path_params/%2E../download' }, + '["","%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + + '/path_params/%2E/download\n' + + ' ^^^', + }, + '["%2E","."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E." can\'t be safely passed as a path parameter\n' + + '/path_params/%2E./download\n' + + ' ^^^^', + }, + }, + '["/path_params/",".","/download"]': { + '["%2e%2e",""]': { valid: true, result: '/path_params/%2e%2e./download' }, + '["","%2e%2e"]': { valid: true, result: '/path_params/.%2e%2e/download' }, + '["",""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + '/path_params/./download\n' + + ' ^', + }, + '["","."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '/path_params/../download\n' + + ' ^^', + }, + }, + '["/path_params/","..","/download"]': { + '["","%2E"]': { valid: true, result: '/path_params/..%2E/download' }, + '["","x"]': { valid: true, result: '/path_params/..x/download' }, + '["",""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '/path_params/../download\n' + + ' ^^', + }, + }, + }); + }); +}); + +describe('encodeURIPath', () => { + const testCases: string[] = [ + '', + // Every ASCII character + ...Array.from({ length: 0x7f }, (_, i) => String.fromCharCode(i)), + // Unicode BMP codepoint + 'å', + // Unicode supplementary codepoint + '😃', + ]; + + for (const param of testCases) { + test('properly encodes ' + inspect(param), () => { + const encoded = encodeURIPath(param); + const naiveEncoded = encodeURIComponent(param); + // we should never encode more characters than encodeURIComponent + expect(naiveEncoded.length).toBeGreaterThanOrEqual(encoded.length); + expect(decodeURIComponent(encoded)).toBe(param); + }); + } + + test("leaves ':' intact", () => { + expect(encodeURIPath(':')).toBe(':'); + }); + + test("leaves '@' intact", () => { + expect(encodeURIPath('@')).toBe('@'); + }); +}); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts new file mode 100644 index 0000000..53bba53 --- /dev/null +++ b/tests/stringifyQuery.test.ts @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Unlayer } from 'unlayer'; + +const { stringifyQuery } = Unlayer.prototype as any; + +describe(stringifyQuery, () => { + for (const [input, expected] of [ + [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], + [{ a: null, b: false, c: undefined }, 'a=&b=false'], + [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], + [ + { 'a/b': 'c/d', 'e=f': 'g&h' }, + `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( + 'e=f', + )}=${encodeURIComponent('g&h')}`, + ], + ]) { + it(`${JSON.stringify(input)} -> ${expected}`, () => { + expect(stringifyQuery(input)).toEqual(expected); + }); + } + + for (const value of [[], {}, new Date()]) { + it(`${JSON.stringify(value)} -> `, () => { + expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); + }); + } +}); diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts new file mode 100644 index 0000000..b4686ca --- /dev/null +++ b/tests/uploads.test.ts @@ -0,0 +1,107 @@ +import fs from 'fs'; +import type { ResponseLike } from 'unlayer/internal/to-file'; +import { toFile } from 'unlayer/core/uploads'; +import { File } from 'node:buffer'; + +class MyClass { + name: string = 'foo'; +} + +function mockResponse({ url, content }: { url: string; content?: Blob }): ResponseLike { + return { + url, + blob: async () => content || new Blob([]), + }; +} + +describe('toFile', () => { + it('throws a helpful error for mismatched types', async () => { + await expect( + // @ts-expect-error intentionally mismatched type + toFile({ foo: 'string' }), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected data type: object; constructor: Object; props: ["foo"]"`, + ); + + await expect( + // @ts-expect-error intentionally mismatched type + toFile(new MyClass()), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected data type: object; constructor: MyClass; props: ["name"]"`, + ); + }); + + it('disallows string at the type-level', async () => { + // @ts-expect-error we intentionally do not type support for `string` + // to help people avoid passing a file path + const file = await toFile('contents'); + expect(file.text()).resolves.toEqual('contents'); + }); + + it('extracts a file name from a Response', async () => { + const response = mockResponse({ url: 'https://example.com/my/audio.mp3' }); + const file = await toFile(response); + expect(file.name).toEqual('audio.mp3'); + }); + + it('extracts a file name from a File', async () => { + const input = new File(['foo'], 'input.jsonl'); + const file = await toFile(input); + expect(file.name).toEqual('input.jsonl'); + }); + + it('extracts a file name from a ReadStream', async () => { + const input = fs.createReadStream('tests/uploads.test.ts'); + const file = await toFile(input); + expect(file.name).toEqual('uploads.test.ts'); + }); + + it('does not copy File objects', async () => { + const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); + const file = await toFile(input); + expect(file).toBe(input); + expect(file.name).toEqual('input.jsonl'); + expect(file.type).toBe('jsonl'); + }); + + it('is assignable to File and Blob', async () => { + const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); + const result = await toFile(input); + const file: File = result; + const blob: Blob = result; + void file, blob; + }); +}); + +describe('missing File error message', () => { + let prevGlobalFile: unknown; + let prevNodeFile: unknown; + beforeEach(() => { + // The file shim captures the global File object when it's first imported. + // Reset modules before each test so we can test the error thrown when it's undefined. + jest.resetModules(); + const buffer = require('node:buffer'); + // @ts-ignore + prevGlobalFile = globalThis.File; + prevNodeFile = buffer.File; + // @ts-ignore + globalThis.File = undefined; + buffer.File = undefined; + }); + afterEach(() => { + // Clean up + // @ts-ignore + globalThis.File = prevGlobalFile; + require('node:buffer').File = prevNodeFile; + jest.resetModules(); + }); + + test('is thrown', async () => { + const uploads = await import('unlayer/core/uploads'); + await expect( + uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), + ).rejects.toMatchInlineSnapshot( + `[Error: \`File\` is not defined as a global, which is required for file uploads.]`, + ); + }); +}); diff --git a/tsc-multi.json b/tsc-multi.json new file mode 100644 index 0000000..384ddac --- /dev/null +++ b/tsc-multi.json @@ -0,0 +1,15 @@ +{ + "targets": [ + { + "extname": ".js", + "module": "commonjs", + "shareHelpers": "internal/tslib.js" + }, + { + "extname": ".mjs", + "module": "esnext", + "shareHelpers": "internal/tslib.mjs" + } + ], + "projects": ["tsconfig.build.json"] +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..1fedc94 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "include": ["dist/src"], + "exclude": [], + "compilerOptions": { + "rootDir": "./dist/src", + "paths": { + "unlayer/*": ["dist/src/*"], + "unlayer": ["dist/src/index.ts"] + }, + "noEmit": false, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "pretty": true, + "sourceMap": true + } +} diff --git a/tsconfig.deno.json b/tsconfig.deno.json new file mode 100644 index 0000000..849e070 --- /dev/null +++ b/tsconfig.deno.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "include": ["dist-deno"], + "exclude": [], + "compilerOptions": { + "rootDir": "./dist-deno", + "lib": ["es2020", "DOM"], + "noEmit": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist-deno", + "pretty": true, + "sourceMap": true + } +} diff --git a/tsconfig.dist-src.json b/tsconfig.dist-src.json new file mode 100644 index 0000000..c550e29 --- /dev/null +++ b/tsconfig.dist-src.json @@ -0,0 +1,11 @@ +{ + // this config is included in the published src directory to prevent TS errors + // from appearing when users go to source, and VSCode opens the source .ts file + // via declaration maps + "include": ["index.ts"], + "compilerOptions": { + "target": "ES2015", + "lib": ["DOM", "DOM.Iterable", "ES2018"], + "moduleResolution": "node" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9286fc9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,38 @@ +{ + "include": ["src", "tests", "examples"], + "exclude": [], + "compilerOptions": { + "target": "es2020", + "lib": ["es2020"], + "module": "commonjs", + "moduleResolution": "node", + "esModuleInterop": true, + "baseUrl": "./", + "paths": { + "unlayer/*": ["src/*"], + "unlayer": ["src/index.ts"] + }, + "noEmit": true, + + "resolveJsonModule": true, + + "forceConsistentCasingInFileNames": true, + + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "alwaysStrict": true, + "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "isolatedModules": false, + + "skipLibCheck": true + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..8311caf --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3500 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@andrewbranch/untar.js@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" + integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== + +"@arethetypeswrong/cli@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" + integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== + dependencies: + "@arethetypeswrong/core" "0.17.0" + chalk "^4.1.2" + cli-table3 "^0.6.3" + commander "^10.0.1" + marked "^9.1.2" + marked-terminal "^7.1.0" + semver "^7.5.4" + +"@arethetypeswrong/core@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" + integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== + dependencies: + "@andrewbranch/untar.js" "^1.0.3" + cjs-module-lexer "^1.2.3" + fflate "^0.8.2" + lru-cache "^10.4.3" + semver "^7.5.4" + typescript "5.6.1-rc" + validate-npm-package-name "^5.0.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" + integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.6" + "@babel/parser" "^7.23.6" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.6" + "@babel/types" "^7.23.6" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helpers@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" + integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.6" + "@babel/types" "^7.23.6" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/template@^7.22.15", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" + integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.19.0": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" + integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" + integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" + integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.20.0": + version "9.20.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" + integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" + integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== + dependencies: + "@eslint/core" "^0.10.0" + levn "^0.4.1" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" + integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== + dependencies: + "@jest/types" "^29.6.3" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pkgr/core@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" + integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sindresorhus/is@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@swc/core-darwin-arm64@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.16.tgz#2cd45d709ce76d448d96bf8d0006849541436611" + integrity sha512-UOCcH1GvjRnnM/LWT6VCGpIk0OhHRq6v1U6QXuPt5wVsgXnXQwnf5k3sG5Cm56hQHDvhRPY6HCsHi/p0oek8oQ== + +"@swc/core-darwin-x64@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.16.tgz#a5bc7d8b1dd850adb0bb95c6b5c742b92201fd01" + integrity sha512-t3bgqFoYLWvyVtVL6KkFNCINEoOrIlyggT/kJRgi1y0aXSr0oVgcrQ4ezJpdeahZZ4N+Q6vT3ffM30yIunELNA== + +"@swc/core-linux-arm-gnueabihf@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.16.tgz#961744908ee5cbb79bc009dcf58cc8b831111f38" + integrity sha512-DvHuwvEF86YvSd0lwnzVcjOTZ0jcxewIbsN0vc/0fqm9qBdMMjr9ox6VCam1n3yYeRtj4VFgrjeNFksqbUejdQ== + +"@swc/core-linux-arm64-gnu@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.16.tgz#43713be3f26757d82d2745dc25f8b63400e0a3d0" + integrity sha512-9Uu5YlPbyCvbidjKtYEsPpyZlu16roOZ5c2tP1vHfnU9bgf5Tz5q5VovSduNxPHx+ed2iC1b1URODHvDzbbDuQ== + +"@swc/core-linux-arm64-musl@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.16.tgz#394a7d030f3a61902bd3947bb9d70d26d42f3c81" + integrity sha512-/YZq/qB1CHpeoL0eMzyqK5/tYZn/rzKoCYDviFU4uduSUIJsDJQuQA/skdqUzqbheOXKAd4mnJ1hT04RbJ8FPQ== + +"@swc/core-linux-x64-gnu@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz#71eb108b784f9d551ee8a35ebcdaed972f567981" + integrity sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ== + +"@swc/core-linux-x64-musl@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz#10dbaedb4e3dfc7268e3a9a66ad3431471ef035b" + integrity sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ== + +"@swc/core-win32-arm64-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.16.tgz#80247adff6c245ff32b44d773c1a148858cd655f" + integrity sha512-bTD43MbhIHL2s5QgCwyleaGwl96Gk/scF2TaVKdUe4QlJCDV/YK9h5oIBAp63ckHtE8GHlH4c8dZNBiAXn4Org== + +"@swc/core-win32-ia32-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.16.tgz#e540afc3ccf3224267b4ddfb408f9d9737984686" + integrity sha512-/lmZeAN/qV5XbK2SEvi8e2RkIg8FQNYiSA8y2/Zb4gTUMKVO5JMLH0BSWMiIKMstKDPDSxMWgwJaQHF8UMyPmQ== + +"@swc/core-win32-x64-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.16.tgz#f880939fca32c181adfe7e3abd2b6b7857bd3489" + integrity sha512-BPAfFfODWXtUu6SwaTTftDHvcbDyWBSI/oanUeRbQR5vVWkXoQ3cxLTsDluc3H74IqXS5z1Uyoe0vNo2hB1opA== + +"@swc/core@^1.3.102": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.16.tgz#d175bae2acfecd53bcbd4293f1fba5ec316634a0" + integrity sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA== + dependencies: + "@swc/counter" "^0.1.2" + "@swc/types" "^0.1.5" + optionalDependencies: + "@swc/core-darwin-arm64" "1.4.16" + "@swc/core-darwin-x64" "1.4.16" + "@swc/core-linux-arm-gnueabihf" "1.4.16" + "@swc/core-linux-arm64-gnu" "1.4.16" + "@swc/core-linux-arm64-musl" "1.4.16" + "@swc/core-linux-x64-gnu" "1.4.16" + "@swc/core-linux-x64-musl" "1.4.16" + "@swc/core-win32-arm64-msvc" "1.4.16" + "@swc/core-win32-ia32-msvc" "1.4.16" + "@swc/core-win32-x64-msvc" "1.4.16" + +"@swc/counter@^0.1.2", "@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/jest@^0.2.29": + version "0.2.36" + resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.36.tgz#2797450a30d28b471997a17e901ccad946fe693e" + integrity sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw== + dependencies: + "@jest/create-cache-key-function" "^29.7.0" + "@swc/counter" "^0.1.3" + jsonc-parser "^3.2.0" + +"@swc/types@^0.1.5": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba" + integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg== + dependencies: + "@swc/counter" "^0.1.3" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.4" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b" + integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA== + dependencies: + "@babel/types" "^7.20.7" + +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.4.0": + version "29.5.11" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" + integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== + dependencies: + undici-types "~5.26.4" + +"@types/node@^20.17.6": + version "20.19.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" + integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== + dependencies: + undici-types "~6.21.0" + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a" + integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/type-utils" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/parser@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b" + integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q== + dependencies: + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b" + integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + +"@typescript-eslint/type-utils@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c" + integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA== + dependencies: + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + debug "^4.3.4" + ts-api-utils "^2.0.1" + +"@typescript-eslint/types@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4" + integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ== + +"@typescript-eslint/typescript-estree@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf" + integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/utils@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14" + integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + +"@typescript-eslint/visitor-keys@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75" + integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw== + dependencies: + "@typescript-eslint/types" "8.31.1" + eslint-visitor-keys "^4.2.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.22.2: + version "4.22.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" + integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== + dependencies: + caniuse-lite "^1.0.30001565" + electron-to-chromium "^1.4.601" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001565: + version "1.0.30001570" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" + integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cjs-module-lexer@^1.2.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-highlight@^2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" + integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== + dependencies: + chalk "^4.0.0" + highlight.js "^10.7.1" + mz "^2.4.0" + parse5 "^5.1.1" + parse5-htmlparser2-tree-adapter "^6.0.0" + yargs "^16.0.0" + +cli-table3@^0.6.3, cli-table3@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.3.4, debug@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +electron-to-chromium@^1.4.601: + version "1.4.614" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" + integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojilib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" + integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== + +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-plugin-prettier@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" + integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.11.7" + +eslint-plugin-unused-imports@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" + integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== + +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + +eslint@^9.20.1: + version "9.20.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" + integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.11.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.20.0" + "@eslint/plugin-kit" "^0.2.5" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stdin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +highlight.js@^10.7.1: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ignore-walk@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" + integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw== + dependencies: + minimatch "^5.0.1" + +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.4.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +marked-terminal@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068" + integrity sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ== + dependencies: + ansi-escapes "^7.0.0" + ansi-regex "^6.1.0" + chalk "^5.3.0" + cli-highlight "^2.1.11" + cli-table3 "^0.6.5" + node-emoji "^2.1.3" + supports-hyperlinks "^3.1.0" + +marked@^9.1.2: + version "9.1.6" + resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" + integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mz@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-emoji@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" + integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== + dependencies: + "@sindresorhus/is" "^4.6.0" + char-regex "^1.0.2" + emojilib "^2.4.0" + skin-tone "^2.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4" + integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw== + dependencies: + npm-normalize-package-bin "^2.0.0" + +npm-normalize-package-bin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" + integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== + +npm-packlist@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" + integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg== + dependencies: + glob "^8.0.1" + ignore-walk "^5.0.1" + npm-bundled "^2.0.0" + npm-normalize-package-bin "^2.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-all@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" + integrity sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw== + dependencies: + p-map "^4.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5-htmlparser2-tree-adapter@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + +parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +publint@^0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059" + integrity sha512-YNeUtCVeM4j9nDiTT2OPczmlyzOkIXNtdDZnSuajAxS/nZ6j3t7Vs9SUB4euQNddiltIwu7Tdd3s+hr08fAsMw== + dependencies: + npm-packlist "^5.1.3" + picocolors "^1.1.1" + sade "^1.8.1" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sade@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@^7.6.0: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +skin-tone@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" + integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== + dependencies: + unicode-emoji-modifier-base "^1.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-to-stream@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42" + integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg== + dependencies: + readable-stream "^3.4.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +superstruct@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz#b56150ff0173baacc15f21956450b61f2b18d3ac" + integrity sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +synckit@^0.11.7: + version "0.11.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" + integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== + dependencies: + "@pkgr/core" "^0.2.4" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" + integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== + +ts-jest@^29.1.0: + version "29.1.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-node@^10.5.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": + version "1.1.9" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" + dependencies: + debug "^4.3.7" + fast-glob "^3.3.2" + get-stdin "^8.0.0" + p-all "^3.0.0" + picocolors "^1.1.1" + signal-exit "^3.0.7" + string-to-stream "^3.0.1" + superstruct "^1.0.4" + tslib "^2.8.1" + yargs "^17.7.2" + +tsconfig-paths@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typescript-eslint@8.31.1: + version "8.31.1" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b" + integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA== + dependencies: + "@typescript-eslint/eslint-plugin" "8.31.1" + "@typescript-eslint/parser" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + +typescript@5.6.1-rc: + version "5.6.1-rc" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.1-rc.tgz#d5e4d7d8170174fed607b74cc32aba3d77018e02" + integrity sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ== + +typescript@5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +unicode-emoji-modifier-base@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" + integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +validate-npm-package-name@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^16.0.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.3.1, yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From c643941cc98f1a62b4d86b50a1c737ed58d51b76 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:40:05 +0000 Subject: [PATCH 002/118] chore: do not install brew dependencies in ./scripts/bootstrap by default --- scripts/bootstrap | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index 062a034..a8b69ff 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi From edae28253c450307b29e54a926324ff2dbb8e6d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 02:20:38 +0000 Subject: [PATCH 003/118] perf: faster formatting --- scripts/fast-format | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 scripts/fast-format diff --git a/scripts/fast-format b/scripts/fast-format new file mode 100755 index 0000000..ef42df5 --- /dev/null +++ b/scripts/fast-format @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echo "Script started with $# arguments" +echo "Arguments: $*" +echo "Script location: $(dirname "$0")" + +cd "$(dirname "$0")/.." +echo "Changed to directory: $(pwd)" + +if [ $# -eq 0 ]; then + echo "Usage: $0 [additional-formatter-args...]" + echo "The file should contain one file path per line" + exit 1 +fi + +FILE_LIST="$1" + +echo "Looking for file: $FILE_LIST" + +if [ ! -f "$FILE_LIST" ]; then + echo "Error: File '$FILE_LIST' not found" + exit 1 +fi + +echo "==> Running eslint --fix" +ESLINT_FILES="$(grep '\.ts$' "$FILE_LIST" || true)" +if ! [ -z "$ESLINT_FILES" ]; then + echo "$ESLINT_FILES" | xargs ./node_modules/.bin/eslint --cache --fix +fi + +echo "==> Running prettier --write" +# format things eslint didn't +PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" +if ! [ -z "$PRETTIER_FILES" ]; then + echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata \ + '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +fi From 89fbb125b60de6bbdb64fd43e8b5f461662956d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 02:21:43 +0000 Subject: [PATCH 004/118] chore(internal): remove deprecated `compilerOptions.baseUrl` from tsconfig.json This allows sdks to be built using tsgo - see https://github.com/microsoft/typescript-go/issues/474 --- tsconfig.build.json | 4 ++-- tsconfig.json | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tsconfig.build.json b/tsconfig.build.json index 1fedc94..8fae373 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "unlayer/*": ["dist/src/*"], - "unlayer": ["dist/src/index.ts"] + "unlayer/*": ["./dist/src/*"], + "unlayer": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 9286fc9..284b45c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,10 +7,9 @@ "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, - "baseUrl": "./", "paths": { - "unlayer/*": ["src/*"], - "unlayer": ["src/index.ts"] + "unlayer/*": ["./src/*"], + "unlayer": ["./src/index.ts"] }, "noEmit": true, From 97a5d28ce54e0630c2eb88a5bc126a0e995493b2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:26:29 +0000 Subject: [PATCH 005/118] chore(internal): fix incremental formatting in some cases --- scripts/fast-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/fast-format b/scripts/fast-format index ef42df5..53721ac 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -35,6 +35,6 @@ echo "==> Running prettier --write" PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" if ! [ -z "$PRETTIER_FILES" ]; then echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' fi From 9c3c141a3546cca1a0d5cd42c022a9a5f1217fa4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:29:41 +0000 Subject: [PATCH 006/118] chore(internal): codegen related update --- .eslintcache | 1 + 1 file changed, 1 insertion(+) create mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 0000000..897f37c --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/jest.config.ts":"1","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/api-promise.ts":"2","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/client.ts":"3","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/api-promise.ts":"4","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/error.ts":"5","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/resource.ts":"6","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/uploads.ts":"7","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/error.ts":"8","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/index.ts":"9","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/builtin-types.ts":"10","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/detect-platform.ts":"11","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/errors.ts":"12","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/headers.ts":"13","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/parse.ts":"14","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/shims.ts":"15","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/shim-types.ts":"16","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/request-options.ts":"17","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/to-file.ts":"18","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/types.ts":"19","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/uploads.ts":"20","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/base64.ts":"21","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/bytes.ts":"22","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/env.ts":"23","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/log.ts":"24","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/path.ts":"25","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/sleep.ts":"26","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/uuid.ts":"27","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/values.ts":"28","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils.ts":"29","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resource.ts":"30","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/documents.ts":"31","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/index.ts":"32","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/generate.ts":"33","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/index.ts":"34","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/v1.ts":"35","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1.ts":"36","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents.ts":"37","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/emails.ts":"38","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/index.ts":"39","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/index.ts":"40","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/send.ts":"41","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/v1.ts":"42","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1.ts":"43","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails.ts":"44","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/index.ts":"45","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/index.ts":"46","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/pages.ts":"47","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/v1.ts":"48","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages.ts":"49","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/index.ts":"50","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/project.ts":"51","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/api-keys.ts":"52","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/domains.ts":"53","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/index.ts":"54","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/templates.ts":"55","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/v1.ts":"56","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1.ts":"57","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project.ts":"58","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources.ts":"59","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/uploads.ts":"60","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/version.ts":"61","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/documents/v1/generate.test.ts":"62","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/documents/v1/v1.test.ts":"63","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/emails/v1/send.test.ts":"64","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/emails/v1/v1.test.ts":"65","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/pages/v1.test.ts":"66","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/api-keys.test.ts":"67","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/domains.test.ts":"68","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/templates.test.ts":"69","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/v1.test.ts":"70","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/base64.test.ts":"71","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/buildHeaders.test.ts":"72","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/form.test.ts":"73","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/index.test.ts":"74","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/path.test.ts":"75","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/stringifyQuery.test.ts":"76","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/uploads.test.ts":"77"},{"size":594,"mtime":1758940162997,"results":"78","hashOfConfig":"79"},{"size":92,"mtime":1758940174813},{"size":25892,"mtime":1758940174813},{"size":3124,"mtime":1758940174813},{"size":3977,"mtime":1758940174813},{"size":264,"mtime":1758940163217,"results":"80","hashOfConfig":"79"},{"size":119,"mtime":1758940163049,"results":"81","hashOfConfig":"79"},{"size":80,"mtime":1758940174813},{"size":574,"mtime":1758940174813},{"size":2917,"mtime":1758940174813},{"size":6407,"mtime":1758940174813},{"size":1187,"mtime":1758940174813},{"size":3026,"mtime":1758940174813},{"size":1500,"mtime":1758940174813},{"size":3525,"mtime":1758940174813},{"size":929,"mtime":1758940174813},{"size":2473,"mtime":1758940174813},{"size":5211,"mtime":1758940174813},{"size":6352,"mtime":1758940174813},{"size":6741,"mtime":1758940163085,"results":"82","hashOfConfig":"79"},{"size":1272,"mtime":1758940163197,"results":"83","hashOfConfig":"79"},{"size":831,"mtime":1758940163085,"results":"84","hashOfConfig":"79"},{"size":612,"mtime":1758940163201,"results":"85","hashOfConfig":"79"},{"size":3107,"mtime":1758940174813},{"size":3209,"mtime":1758940163085,"results":"86","hashOfConfig":"79"},{"size":182,"mtime":1758940163205,"results":"87","hashOfConfig":"79"},{"size":601,"mtime":1758940174813},{"size":3134,"mtime":1758940163197,"results":"88","hashOfConfig":"79"},{"size":271,"mtime":1758940163193,"results":"89","hashOfConfig":"79"},{"size":86,"mtime":1758940174813},{"size":456,"mtime":1758940174817},{"size":189,"mtime":1758940174817},{"size":2605,"mtime":1758940174817},{"size":317,"mtime":1758940174817},{"size":1916,"mtime":1758940174817},{"size":116,"mtime":1758940163321,"results":"90","hashOfConfig":"79"},{"size":123,"mtime":1758940163317,"results":"91","hashOfConfig":"79"},{"size":571,"mtime":1758940174817},{"size":227,"mtime":1758940174817},{"size":329,"mtime":1758940174817},{"size":2181,"mtime":1758940174817},{"size":2284,"mtime":1758940174817},{"size":116,"mtime":1758940163365,"results":"92","hashOfConfig":"79"},{"size":120,"mtime":1758940163361,"results":"93","hashOfConfig":"79"},{"size":269,"mtime":1758940174817},{"size":194,"mtime":1758940174817},{"size":491,"mtime":1758940174817},{"size":1007,"mtime":1758940174817},{"size":119,"mtime":1758940163397,"results":"94","hashOfConfig":"79"},{"size":187,"mtime":1758940174817},{"size":456,"mtime":1758940174817},{"size":3620,"mtime":1758940174817},{"size":3257,"mtime":1758940174817},{"size":748,"mtime":1758940174817},{"size":3612,"mtime":1758940174817},{"size":3076,"mtime":1758940174817},{"size":116,"mtime":1758940163233,"results":"95","hashOfConfig":"79"},{"size":121,"mtime":1758940163225,"results":"96","hashOfConfig":"79"},{"size":35,"mtime":1758940163089,"results":"97","hashOfConfig":"79"},{"size":84,"mtime":1758940174817},{"size":32,"mtime":1758940163169,"results":"98","hashOfConfig":"79"},{"size":2177,"mtime":1758940174817},{"size":807,"mtime":1758940174817},{"size":1998,"mtime":1758940174817},{"size":1545,"mtime":1758940174817},{"size":1031,"mtime":1758940174817},{"size":3561,"mtime":1758940174817},{"size":3517,"mtime":1758940174817},{"size":3589,"mtime":1758940174817},{"size":805,"mtime":1758940174817},{"size":2061,"mtime":1758940163089,"results":"99","hashOfConfig":"100"},{"size":2181,"mtime":1758940163097,"results":"101","hashOfConfig":"100"},{"size":1886,"mtime":1758940163101,"results":"102","hashOfConfig":"100"},{"size":22796,"mtime":1758940174817},{"size":17589,"mtime":1758940163101,"results":"103","hashOfConfig":"100"},{"size":918,"mtime":1758940174817},{"size":3471,"mtime":1758940163105,"results":"104","hashOfConfig":"100"},{"filePath":"105","messages":"106","suppressedMessages":"107","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1pscg0s",{"filePath":"108","messages":"109","suppressedMessages":"110","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"111","messages":"112","suppressedMessages":"113","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"114","messages":"115","suppressedMessages":"116","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"117","messages":"118","suppressedMessages":"119","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"120","messages":"121","suppressedMessages":"122","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"123","messages":"124","suppressedMessages":"125","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"126","messages":"127","suppressedMessages":"128","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"129","messages":"130","suppressedMessages":"131","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"132","messages":"133","suppressedMessages":"134","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"135","messages":"136","suppressedMessages":"137","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"138","messages":"139","suppressedMessages":"140","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"141","messages":"142","suppressedMessages":"143","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"144","messages":"145","suppressedMessages":"146","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"147","messages":"148","suppressedMessages":"149","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"150","messages":"151","suppressedMessages":"152","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"153","messages":"154","suppressedMessages":"155","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","suppressedMessages":"158","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"159","messages":"160","suppressedMessages":"161","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"162","messages":"163","suppressedMessages":"164","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"165","messages":"166","suppressedMessages":"167","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1asqst8",{"filePath":"168","messages":"169","suppressedMessages":"170","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"171","messages":"172","suppressedMessages":"173","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"174","messages":"175","suppressedMessages":"176","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"177","messages":"178","suppressedMessages":"179","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/jest.config.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/resource.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/uploads.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/uploads.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/base64.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/bytes.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/env.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/path.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/sleep.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/values.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/version.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/base64.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/buildHeaders.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/form.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/path.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/uploads.test.ts",[],[]] \ No newline at end of file From 2294ed4b2c72d695d04ed34dc53ba010496fa877 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:31:34 +0000 Subject: [PATCH 007/118] chore(internal): ignore .eslintcache --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d98d51a..2412bb7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ dist dist-deno /*.tgz .idea/ +.eslintcache From fff956ca142c3c491d7fce26fa3afb21a14f35ba Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 02:14:01 +0000 Subject: [PATCH 008/118] chore(internal): codegen related update --- .eslintcache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache deleted file mode 100644 index 897f37c..0000000 --- a/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/jest.config.ts":"1","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/api-promise.ts":"2","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/client.ts":"3","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/api-promise.ts":"4","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/error.ts":"5","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/resource.ts":"6","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/uploads.ts":"7","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/error.ts":"8","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/index.ts":"9","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/builtin-types.ts":"10","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/detect-platform.ts":"11","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/errors.ts":"12","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/headers.ts":"13","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/parse.ts":"14","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/shims.ts":"15","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/shim-types.ts":"16","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/request-options.ts":"17","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/to-file.ts":"18","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/types.ts":"19","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/uploads.ts":"20","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/base64.ts":"21","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/bytes.ts":"22","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/env.ts":"23","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/log.ts":"24","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/path.ts":"25","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/sleep.ts":"26","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/uuid.ts":"27","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/values.ts":"28","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils.ts":"29","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resource.ts":"30","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/documents.ts":"31","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/index.ts":"32","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/generate.ts":"33","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/index.ts":"34","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1/v1.ts":"35","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1.ts":"36","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents.ts":"37","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/emails.ts":"38","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/index.ts":"39","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/index.ts":"40","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/send.ts":"41","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1/v1.ts":"42","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1.ts":"43","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails.ts":"44","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/index.ts":"45","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/index.ts":"46","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/pages.ts":"47","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages/v1.ts":"48","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages.ts":"49","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/index.ts":"50","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/project.ts":"51","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/api-keys.ts":"52","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/domains.ts":"53","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/index.ts":"54","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/templates.ts":"55","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1/v1.ts":"56","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1.ts":"57","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project.ts":"58","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources.ts":"59","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/uploads.ts":"60","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/version.ts":"61","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/documents/v1/generate.test.ts":"62","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/documents/v1/v1.test.ts":"63","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/emails/v1/send.test.ts":"64","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/emails/v1/v1.test.ts":"65","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/pages/v1.test.ts":"66","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/api-keys.test.ts":"67","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/domains.test.ts":"68","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/templates.test.ts":"69","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/api-resources/project/v1/v1.test.ts":"70","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/base64.test.ts":"71","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/buildHeaders.test.ts":"72","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/form.test.ts":"73","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/index.test.ts":"74","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/path.test.ts":"75","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/stringifyQuery.test.ts":"76","/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/uploads.test.ts":"77"},{"size":594,"mtime":1758940162997,"results":"78","hashOfConfig":"79"},{"size":92,"mtime":1758940174813},{"size":25892,"mtime":1758940174813},{"size":3124,"mtime":1758940174813},{"size":3977,"mtime":1758940174813},{"size":264,"mtime":1758940163217,"results":"80","hashOfConfig":"79"},{"size":119,"mtime":1758940163049,"results":"81","hashOfConfig":"79"},{"size":80,"mtime":1758940174813},{"size":574,"mtime":1758940174813},{"size":2917,"mtime":1758940174813},{"size":6407,"mtime":1758940174813},{"size":1187,"mtime":1758940174813},{"size":3026,"mtime":1758940174813},{"size":1500,"mtime":1758940174813},{"size":3525,"mtime":1758940174813},{"size":929,"mtime":1758940174813},{"size":2473,"mtime":1758940174813},{"size":5211,"mtime":1758940174813},{"size":6352,"mtime":1758940174813},{"size":6741,"mtime":1758940163085,"results":"82","hashOfConfig":"79"},{"size":1272,"mtime":1758940163197,"results":"83","hashOfConfig":"79"},{"size":831,"mtime":1758940163085,"results":"84","hashOfConfig":"79"},{"size":612,"mtime":1758940163201,"results":"85","hashOfConfig":"79"},{"size":3107,"mtime":1758940174813},{"size":3209,"mtime":1758940163085,"results":"86","hashOfConfig":"79"},{"size":182,"mtime":1758940163205,"results":"87","hashOfConfig":"79"},{"size":601,"mtime":1758940174813},{"size":3134,"mtime":1758940163197,"results":"88","hashOfConfig":"79"},{"size":271,"mtime":1758940163193,"results":"89","hashOfConfig":"79"},{"size":86,"mtime":1758940174813},{"size":456,"mtime":1758940174817},{"size":189,"mtime":1758940174817},{"size":2605,"mtime":1758940174817},{"size":317,"mtime":1758940174817},{"size":1916,"mtime":1758940174817},{"size":116,"mtime":1758940163321,"results":"90","hashOfConfig":"79"},{"size":123,"mtime":1758940163317,"results":"91","hashOfConfig":"79"},{"size":571,"mtime":1758940174817},{"size":227,"mtime":1758940174817},{"size":329,"mtime":1758940174817},{"size":2181,"mtime":1758940174817},{"size":2284,"mtime":1758940174817},{"size":116,"mtime":1758940163365,"results":"92","hashOfConfig":"79"},{"size":120,"mtime":1758940163361,"results":"93","hashOfConfig":"79"},{"size":269,"mtime":1758940174817},{"size":194,"mtime":1758940174817},{"size":491,"mtime":1758940174817},{"size":1007,"mtime":1758940174817},{"size":119,"mtime":1758940163397,"results":"94","hashOfConfig":"79"},{"size":187,"mtime":1758940174817},{"size":456,"mtime":1758940174817},{"size":3620,"mtime":1758940174817},{"size":3257,"mtime":1758940174817},{"size":748,"mtime":1758940174817},{"size":3612,"mtime":1758940174817},{"size":3076,"mtime":1758940174817},{"size":116,"mtime":1758940163233,"results":"95","hashOfConfig":"79"},{"size":121,"mtime":1758940163225,"results":"96","hashOfConfig":"79"},{"size":35,"mtime":1758940163089,"results":"97","hashOfConfig":"79"},{"size":84,"mtime":1758940174817},{"size":32,"mtime":1758940163169,"results":"98","hashOfConfig":"79"},{"size":2177,"mtime":1758940174817},{"size":807,"mtime":1758940174817},{"size":1998,"mtime":1758940174817},{"size":1545,"mtime":1758940174817},{"size":1031,"mtime":1758940174817},{"size":3561,"mtime":1758940174817},{"size":3517,"mtime":1758940174817},{"size":3589,"mtime":1758940174817},{"size":805,"mtime":1758940174817},{"size":2061,"mtime":1758940163089,"results":"99","hashOfConfig":"100"},{"size":2181,"mtime":1758940163097,"results":"101","hashOfConfig":"100"},{"size":1886,"mtime":1758940163101,"results":"102","hashOfConfig":"100"},{"size":22796,"mtime":1758940174817},{"size":17589,"mtime":1758940163101,"results":"103","hashOfConfig":"100"},{"size":918,"mtime":1758940174817},{"size":3471,"mtime":1758940163105,"results":"104","hashOfConfig":"100"},{"filePath":"105","messages":"106","suppressedMessages":"107","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1pscg0s",{"filePath":"108","messages":"109","suppressedMessages":"110","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"111","messages":"112","suppressedMessages":"113","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"114","messages":"115","suppressedMessages":"116","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"117","messages":"118","suppressedMessages":"119","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"120","messages":"121","suppressedMessages":"122","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"123","messages":"124","suppressedMessages":"125","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"126","messages":"127","suppressedMessages":"128","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"129","messages":"130","suppressedMessages":"131","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"132","messages":"133","suppressedMessages":"134","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"135","messages":"136","suppressedMessages":"137","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"138","messages":"139","suppressedMessages":"140","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"141","messages":"142","suppressedMessages":"143","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"144","messages":"145","suppressedMessages":"146","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"147","messages":"148","suppressedMessages":"149","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"150","messages":"151","suppressedMessages":"152","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"153","messages":"154","suppressedMessages":"155","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","suppressedMessages":"158","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"159","messages":"160","suppressedMessages":"161","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"162","messages":"163","suppressedMessages":"164","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"165","messages":"166","suppressedMessages":"167","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1asqst8",{"filePath":"168","messages":"169","suppressedMessages":"170","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"171","messages":"172","suppressedMessages":"173","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"174","messages":"175","suppressedMessages":"176","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"177","messages":"178","suppressedMessages":"179","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/jest.config.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/resource.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/core/uploads.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/uploads.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/base64.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/bytes.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/env.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/path.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/sleep.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils/values.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/internal/utils.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/documents.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/emails.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/pages.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project/v1.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources/project.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/resources.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/src/version.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/base64.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/buildHeaders.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/form.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/path.test.ts",[],[],"/home/tempuser-159djj/run/codegen-output/unlayer/unlayer-typescript/tests/uploads.test.ts",[],[]] \ No newline at end of file From 9c081a39058115863e02924b637233b10abade06 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 4 Oct 2025 02:12:24 +0000 Subject: [PATCH 009/118] =?UTF-8?q?chore(jsdoc):=20fix=20@link=20annotatio?= =?UTF-8?q?ns=20to=20refer=20only=20to=20parts=20of=20the=20package?= =?UTF-8?q?=E2=80=98s=20public=20interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/internal/to-file.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts index 245e849..30eada3 100644 --- a/src/internal/to-file.ts +++ b/src/internal/to-file.ts @@ -73,7 +73,7 @@ export type ToFileInput = /** * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats - * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible * @param {Object=} options additional properties * @param {string=} options.type the MIME type of the content From 0ee9d9c79890df30cb3cb4bd8b2ba996bcb17e98 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 02:26:00 +0000 Subject: [PATCH 010/118] chore(internal): use npm pack for build uploads --- scripts/utils/upload-artifact.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 98b1a12..f723e7a 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,9 +12,11 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ +TARBALL=$(cd dist && npm pack --silent) + +UPLOAD_RESPONSE=$(curl -v -X PUT \ -H "Content-Type: application/gzip" \ - --data-binary @- "$SIGNED_URL" 2>&1) + --data-binary "@dist/$TARBALL" "$SIGNED_URL" 2>&1) if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" From 21b81ff4d1861be19dc01316563c8935e448ddd5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:53:19 +0000 Subject: [PATCH 011/118] feat(api): api update --- .stats.yml | 4 +- package.json | 2 +- src/client.ts | 2 +- yarn.lock | 150 +++++++++++++++++++++++++++++--------------------- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/.stats.yml b/.stats.yml index c591c51..94d165f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4183a0cf62e19c37b104df3fdc7bdc44ddbb9cb35e2886e2b9877c056107c8a2.yml -openapi_spec_hash: 34076f7e9e1bc890db0b5b6aa8affd79 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-6bef9fa0591c8c3efedc713da71252a84a04ac8be7775210d5d89bb300edc931.yml +openapi_spec_hash: dc7626ac301f9e7a0f00009a2526493c config_hash: d8e1c89a13d504eed8a5a07186ba17ea diff --git a/package.json b/package.json index ae5d4b1..23feed2 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@types/node": "^20.17.6", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "eslint": "^9.20.1", + "eslint": "^9.39.1", "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", diff --git a/src/client.ts b/src/client.ts index 36c1ee8..81ba5bd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -117,7 +117,7 @@ export class Unlayer { baseURL: string; maxRetries: number; timeout: number; - logger: Logger | undefined; + logger: Logger; logLevel: LogLevel | undefined; fetchOptions: MergedRequestInit | undefined; diff --git a/yarn.lock b/yarn.lock index 8311caf..5f56a20 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,45 +350,52 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.0": - version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" - integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== dependencies: - "@eslint/object-schema" "^2.1.6" + "@eslint/object-schema" "^2.1.7" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/core@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" - integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== dependencies: - "@types/json-schema" "^7.0.15" + "@eslint/core" "^0.17.0" -"@eslint/core@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" - integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== dependencies: "@types/json-schema" "^7.0.15" -"@eslint/eslintrc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" - integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== +"@eslint/eslintrc@^3.3.1": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz#26393a0806501b5e2b6a43aa588a4d8df67880ac" + integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -396,26 +403,26 @@ globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" + js-yaml "^4.1.1" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.20.0": - version "9.20.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" - integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== +"@eslint/js@9.39.1": + version "9.39.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.1.tgz#0dd59c3a9f40e3f1882975c321470969243e0164" + integrity sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw== -"@eslint/object-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" - integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== -"@eslint/plugin-kit@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" - integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== dependencies: - "@eslint/core" "^0.10.0" + "@eslint/core" "^0.17.0" levn "^0.4.1" "@humanfs/core@^0.19.1": @@ -441,10 +448,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@humanwhocodes/retry@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" - integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1057,6 +1064,11 @@ acorn@^8.14.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + acorn@^8.4.1: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" @@ -1560,15 +1572,15 @@ eslint-plugin-unused-imports@^4.1.4: resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== -eslint-scope@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" - integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -1578,31 +1590,36 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.20.1: - version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" - integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.39.1: + version "9.39.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.1.tgz#be8bf7c6de77dcc4252b5a8dcb31c2efff74a6e5" + integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g== dependencies: - "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.0" - "@eslint/core" "^0.11.0" - "@eslint/eslintrc" "^3.2.0" - "@eslint/js" "9.20.0" - "@eslint/plugin-kit" "^0.2.5" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.1" + "@eslint/plugin-kit" "^0.4.1" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.1" + "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" - "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.6" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.2.0" - eslint-visitor-keys "^4.2.0" - espree "^10.3.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -1618,7 +1635,7 @@ eslint@^9.20.1: natural-compare "^1.4.0" optionator "^0.9.3" -espree@^10.0.1, espree@^10.3.0: +espree@^10.0.1: version "10.3.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== @@ -1627,6 +1644,15 @@ espree@^10.0.1, espree@^10.3.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^4.2.0" +espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2440,10 +2466,10 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" From e74437d6bfc35b77df941e54cddcea0d277cb6f9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 17:46:52 +0000 Subject: [PATCH 012/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 94d165f..d97ae5d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-6bef9fa0591c8c3efedc713da71252a84a04ac8be7775210d5d89bb300edc931.yml -openapi_spec_hash: dc7626ac301f9e7a0f00009a2526493c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-53ff0a03b2555e72ccf3f709839a1dc67375d8d7e862e35bc6dadbe177d48039.yml +openapi_spec_hash: 75db0f0d0e07677418e8362b400fe9ea config_hash: d8e1c89a13d504eed8a5a07186ba17ea From a793e4d592397c15eb2f954c06805a5ea2828978 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 18:23:57 +0000 Subject: [PATCH 013/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d97ae5d..1b87435 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-53ff0a03b2555e72ccf3f709839a1dc67375d8d7e862e35bc6dadbe177d48039.yml -openapi_spec_hash: 75db0f0d0e07677418e8362b400fe9ea +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-852141c09089e62a8575a67d549598cc62109486e564b4675b993ff5079e91b1.yml +openapi_spec_hash: ee3fe91b6ab6825ac99c9c15daca0797 config_hash: d8e1c89a13d504eed8a5a07186ba17ea From 8b5a225f814fd8085b72504e64569649f1e2d18f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 21:32:24 +0000 Subject: [PATCH 014/118] feat(api): api update --- .stats.yml | 6 +- CONTRIBUTING.md | 4 +- README.md | 50 +- api.md | 167 +++--- eslint.config.mjs | 2 +- jest.config.ts | 4 +- package.json | 4 +- scripts/build | 6 +- src/client.ts | 231 ++++++-- src/resources/documents-v1.ts | 169 ++++++ src/resources/documents.ts | 168 +++++- src/resources/documents/documents.ts | 15 - src/resources/documents/index.ts | 4 - src/resources/documents/v1.ts | 3 - src/resources/documents/v1/generate.ts | 118 ---- src/resources/documents/v1/index.ts | 10 - src/resources/documents/v1/v1.ts | 81 --- src/resources/emails-v1.ts | 175 ++++++ src/resources/emails.ts | 171 +++++- src/resources/emails/emails.ts | 20 - src/resources/emails/index.ts | 4 - src/resources/emails/v1.ts | 3 - src/resources/emails/v1/index.ts | 10 - src/resources/emails/v1/send.ts | 100 ---- src/resources/emails/v1/v1.ts | 101 ---- src/resources/index.ts | 86 ++- src/resources/pages-v1.ts | 43 ++ src/resources/pages.ts | 39 +- src/resources/pages/index.ts | 4 - src/resources/pages/pages.ts | 15 - src/resources/pages/v1.ts | 37 -- src/resources/project-v1.ts | 516 ++++++++++++++++++ src/resources/project.ts | 515 ++++++++++++++++- src/resources/project/index.ts | 4 - src/resources/project/project.ts | 15 - src/resources/project/v1.ts | 3 - src/resources/project/v1/api-keys.ts | 177 ------ src/resources/project/v1/domains.ts | 148 ----- src/resources/project/v1/index.ts | 30 - src/resources/project/v1/templates.ts | 176 ------ src/resources/project/v1/v1.ts | 112 ---- tests/api-resources/documents-v1.test.ts | 64 +++ .../v1/generate.test.ts => documents.test.ts} | 40 +- tests/api-resources/documents/v1/v1.test.ts | 22 - tests/api-resources/emails-v1.test.ts | 77 +++ tests/api-resources/emails.test.ts | 77 +++ tests/api-resources/emails/v1/send.test.ts | 58 -- tests/api-resources/emails/v1/v1.test.ts | 39 -- tests/api-resources/pages-v1.test.ts | 22 + tests/api-resources/pages.test.ts | 22 + tests/api-resources/pages/v1.test.ts | 27 - tests/api-resources/project-v1.test.ts | 228 ++++++++ tests/api-resources/project.test.ts | 224 ++++++++ .../api-resources/project/v1/api-keys.test.ts | 87 --- .../api-resources/project/v1/domains.test.ts | 83 --- .../project/v1/templates.test.ts | 91 --- tests/api-resources/project/v1/v1.test.ts | 22 - tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 +- tests/index.test.ts | 102 ++-- tests/path.test.ts | 2 +- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 +- tsconfig.build.json | 4 +- tsconfig.json | 4 +- 66 files changed, 2982 insertions(+), 1875 deletions(-) create mode 100644 src/resources/documents-v1.ts delete mode 100644 src/resources/documents/documents.ts delete mode 100644 src/resources/documents/index.ts delete mode 100644 src/resources/documents/v1.ts delete mode 100644 src/resources/documents/v1/generate.ts delete mode 100644 src/resources/documents/v1/index.ts delete mode 100644 src/resources/documents/v1/v1.ts create mode 100644 src/resources/emails-v1.ts delete mode 100644 src/resources/emails/emails.ts delete mode 100644 src/resources/emails/index.ts delete mode 100644 src/resources/emails/v1.ts delete mode 100644 src/resources/emails/v1/index.ts delete mode 100644 src/resources/emails/v1/send.ts delete mode 100644 src/resources/emails/v1/v1.ts create mode 100644 src/resources/pages-v1.ts delete mode 100644 src/resources/pages/index.ts delete mode 100644 src/resources/pages/pages.ts delete mode 100644 src/resources/pages/v1.ts create mode 100644 src/resources/project-v1.ts delete mode 100644 src/resources/project/index.ts delete mode 100644 src/resources/project/project.ts delete mode 100644 src/resources/project/v1.ts delete mode 100644 src/resources/project/v1/api-keys.ts delete mode 100644 src/resources/project/v1/domains.ts delete mode 100644 src/resources/project/v1/index.ts delete mode 100644 src/resources/project/v1/templates.ts delete mode 100644 src/resources/project/v1/v1.ts create mode 100644 tests/api-resources/documents-v1.test.ts rename tests/api-resources/{documents/v1/generate.test.ts => documents.test.ts} (53%) delete mode 100644 tests/api-resources/documents/v1/v1.test.ts create mode 100644 tests/api-resources/emails-v1.test.ts create mode 100644 tests/api-resources/emails.test.ts delete mode 100644 tests/api-resources/emails/v1/send.test.ts delete mode 100644 tests/api-resources/emails/v1/v1.test.ts create mode 100644 tests/api-resources/pages-v1.test.ts create mode 100644 tests/api-resources/pages.test.ts delete mode 100644 tests/api-resources/pages/v1.test.ts create mode 100644 tests/api-resources/project-v1.test.ts create mode 100644 tests/api-resources/project.test.ts delete mode 100644 tests/api-resources/project/v1/api-keys.test.ts delete mode 100644 tests/api-resources/project/v1/domains.test.ts delete mode 100644 tests/api-resources/project/v1/templates.test.ts delete mode 100644 tests/api-resources/project/v1/v1.test.ts diff --git a/.stats.yml b/.stats.yml index 1b87435..3f69762 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-852141c09089e62a8575a67d549598cc62109486e564b4675b993ff5079e91b1.yml -openapi_spec_hash: ee3fe91b6ab6825ac99c9c15daca0797 -config_hash: d8e1c89a13d504eed8a5a07186ba17ea +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-9c0284025bec8c18271ce41a95293d975923e9ef9b3e1ff38890a04163c1b3de.yml +openapi_spec_hash: f0bec2b2df750ce635ad4b2e4a05cde1 +config_hash: 1799607c695a40200c35bb8fa5685014 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c466c26..3d4637a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd unlayer-typescript # With yarn $ yarn link $ cd ../my-package -$ yarn link unlayer +$ yarn link @unlayer/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global unlayer +$ pnpm link -—global @unlayer/sdk ``` ## Running tests diff --git a/README.md b/README.md index 804ca7f..27b8a90 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Unlayer TypeScript API Library -[![NPM version]()](https://npmjs.org/package/unlayer) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/unlayer) +[![NPM version]()](https://npmjs.org/package/@unlayer/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@unlayer/sdk) This library provides convenient access to the Unlayer REST API from server-side TypeScript or JavaScript. @@ -15,7 +15,7 @@ npm install git+ssh://git@github.com:stainless-sdks/unlayer-typescript.git ``` > [!NOTE] -> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npm install unlayer` +> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npm install @unlayer/sdk` ## Usage @@ -23,15 +23,13 @@ The full API of this library can be found in [api.md](api.md). ```js -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ - apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted -}); +const client = new Unlayer(); -const apiKeys = await client.project.v1.apiKeys.list(); +const response = await client.projectV1.currentList(); -console.log(apiKeys.data); +console.log(response.data); ``` ### Request & Response types @@ -40,13 +38,11 @@ This library includes TypeScript definitions for all request params and response ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ - apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted -}); +const client = new Unlayer(); -const apiKeys: Unlayer.Project.V1.APIKeyListResponse = await client.project.v1.apiKeys.list(); +const response: Unlayer.ProjectV1CurrentListResponse = await client.projectV1.currentList(); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -59,7 +55,7 @@ a subclass of `APIError` will be thrown: ```ts -const apiKeys = await client.project.v1.apiKeys.list().catch(async (err) => { +const response = await client.projectV1.currentList().catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 console.log(err.name); // BadRequestError @@ -99,7 +95,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.project.v1.apiKeys.list({ +await client.projectV1.currentList({ maxRetries: 5, }); ``` @@ -116,7 +112,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.project.v1.apiKeys.list({ +await client.projectV1.currentList({ timeout: 5 * 1000, }); ``` @@ -139,13 +135,13 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.project.v1.apiKeys.list().asResponse(); +const response = await client.projectV1.currentList().asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: apiKeys, response: raw } = await client.project.v1.apiKeys.list().withResponse(); +const { data: response, response: raw } = await client.projectV1.currentList().withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(apiKeys.data); +console.log(response.data); ``` ### Logging @@ -162,7 +158,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ logLevel: 'debug', // Show all log messages @@ -190,7 +186,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; import pino from 'pino'; const logger = pino(); @@ -225,7 +221,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.project.v1.apiKeys.list({ +client.projectV1.currentList({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', @@ -259,7 +255,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; import fetch from 'my-fetch'; const client = new Unlayer({ fetch }); @@ -270,7 +266,7 @@ const client = new Unlayer({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ fetchOptions: { @@ -287,7 +283,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -301,7 +297,7 @@ const client = new Unlayer({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ fetchOptions: { @@ -313,7 +309,7 @@ const client = new Unlayer({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Unlayer from 'npm:unlayer'; +import Unlayer from 'npm:@unlayer/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Unlayer({ diff --git a/api.md b/api.md index b51b2e4..49167ca 100644 --- a/api.md +++ b/api.md @@ -1,124 +1,153 @@ -# Project - -## V1 - -Types: - -- V1GetCurrentResponse - -Methods: - -- client.project.v1.getCurrent() -> V1GetCurrentResponse - -### APIKeys +# EmailsV1 Types: -- APIKeyCreateResponse -- APIKeyRetrieveResponse -- APIKeyUpdateResponse -- APIKeyListResponse +- EmailsV1EmailsRetrieveResponse +- EmailsV1RenderCreateResponse +- EmailsV1SendCreateResponse +- EmailsV1SendTemplateTemplateResponse Methods: -- client.project.v1.apiKeys.create({ ...params }) -> APIKeyCreateResponse -- client.project.v1.apiKeys.retrieve(id) -> APIKeyRetrieveResponse -- client.project.v1.apiKeys.update(id, { ...params }) -> APIKeyUpdateResponse -- client.project.v1.apiKeys.list() -> APIKeyListResponse -- client.project.v1.apiKeys.delete(id) -> void +- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse +- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse +- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse +- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse -### Domains +# Emails Types: -- DomainCreateResponse -- DomainRetrieveResponse -- DomainUpdateResponse -- DomainListResponse +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.project.v1.domains.create({ ...params }) -> DomainCreateResponse -- client.project.v1.domains.retrieve(id) -> DomainRetrieveResponse -- client.project.v1.domains.update(id, { ...params }) -> DomainUpdateResponse -- client.project.v1.domains.list() -> DomainListResponse -- client.project.v1.domains.delete(id) -> void +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse -### Templates +# ProjectV1 Types: -- TemplateCreateResponse -- TemplateRetrieveResponse -- TemplateUpdateResponse -- TemplateListResponse +- ProjectV1APIKeysCreateResponse +- ProjectV1APIKeysListResponse +- ProjectV1APIKeysRetrieveResponse +- ProjectV1APIKeysUpdateResponse +- ProjectV1CurrentListResponse +- ProjectV1DomainsCreateResponse +- ProjectV1DomainsListResponse +- ProjectV1DomainsRetrieveResponse +- ProjectV1DomainsUpdateResponse +- ProjectV1TemplatesCreateResponse +- ProjectV1TemplatesListResponse +- ProjectV1TemplatesRetrieveResponse +- ProjectV1TemplatesUpdateResponse Methods: -- client.project.v1.templates.create({ ...params }) -> TemplateCreateResponse -- client.project.v1.templates.retrieve(id) -> TemplateRetrieveResponse -- client.project.v1.templates.update(id, { ...params }) -> TemplateUpdateResponse -- client.project.v1.templates.list() -> TemplateListResponse -- client.project.v1.templates.delete(id) -> void - -# Documents +- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse +- client.projectV1.apiKeysDelete(id) -> void +- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse +- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse +- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse +- client.projectV1.currentList() -> ProjectV1CurrentListResponse +- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse +- client.projectV1.domainsDelete(id) -> void +- client.projectV1.domainsList() -> ProjectV1DomainsListResponse +- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse +- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse +- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse +- client.projectV1.templatesDelete(id) -> void +- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse +- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse +- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse -## V1 +# Project Types: -- V1RetrieveResponse +- ProjectAPIKeysCreateResponse +- ProjectAPIKeysListResponse +- ProjectAPIKeysRetrieveResponse +- ProjectAPIKeysUpdateResponse +- ProjectCurrentListResponse +- ProjectDomainsCreateResponse +- ProjectDomainsListResponse +- ProjectDomainsRetrieveResponse +- ProjectDomainsUpdateResponse +- ProjectTemplatesCreateResponse +- ProjectTemplatesListResponse +- ProjectTemplatesRetrieveResponse +- ProjectTemplatesUpdateResponse Methods: -- client.documents.v1.retrieve(id) -> V1RetrieveResponse - -### Generate +- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse +- client.project.apiKeysDelete(id) -> void +- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse +- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse +- client.project.currentList() -> ProjectCurrentListResponse +- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse +- client.project.domainsDelete(id) -> void +- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse +- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse +- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse +- client.project.templatesDelete(id) -> void +- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse +- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse + +# DocumentsV1 Types: -- GenerateCreateResponse -- GenerateCreateFromTemplateResponse +- DocumentsV1DocumentsRetrieveResponse +- DocumentsV1GenerateCreateResponse +- DocumentsV1GenerateTemplateTemplateResponse Methods: -- client.documents.v1.generate.create({ ...params }) -> GenerateCreateResponse -- client.documents.v1.generate.createFromTemplate({ ...params }) -> GenerateCreateFromTemplateResponse +- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse +- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse +- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse -# Emails - -## V1 +# Documents Types: -- V1RetrieveResponse -- V1RenderResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.emails.v1.retrieve(id) -> V1RetrieveResponse -- client.emails.v1.render({ ...params }) -> V1RenderResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse -### Send +# PagesV1 Types: -- SendSendResponse -- SendSendFromTemplateResponse +- PagesV1RenderCreateResponse Methods: -- client.emails.v1.send.send({ ...params }) -> SendSendResponse -- client.emails.v1.send.sendFromTemplate({ ...params }) -> SendSendFromTemplateResponse +- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse # Pages -## V1 - Types: -- V1RenderResponse +- PageRenderCreateResponse Methods: -- client.pages.v1.render({ ...params }) -> V1RenderResponse +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/eslint.config.mjs b/eslint.config.mjs index be1e121..e0dbbf8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^unlayer(/.*)?', + regex: '^@unlayer/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index 0f5ccc3..da92a62 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^unlayer$': '/src/index.ts', - '^unlayer/(.*)$': '/src/$1', + '^@unlayer/sdk$': '/src/index.ts', + '^@unlayer/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index 23feed2..cea38cc 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "unlayer", + "name": "@unlayer/sdk", "version": "0.0.1", "description": "The official TypeScript library for the Unlayer API", - "author": "Unlayer <>", + "author": "Unlayer ", "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", diff --git a/scripts/build b/scripts/build index 24c3b0d..6de20d4 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"unlayer/resources/foo"` works +# This way importing from `"@unlayer/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("unlayer")') -(cd dist && node -e 'import("unlayer")' --input-type=module) +(cd dist && node -e 'require("@unlayer/sdk")') +(cd dist && node -e 'import("@unlayer/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/src/client.ts b/src/client.ts index 81ba5bd..58e3524 100644 --- a/src/client.ts +++ b/src/client.ts @@ -16,10 +16,88 @@ import * as Errors from './core/error'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { Documents } from './resources/documents/documents'; -import { Emails } from './resources/emails/emails'; -import { Pages } from './resources/pages/pages'; -import { Project } from './resources/project/project'; +import { + DocumentDocumentsRetrieveResponse, + DocumentGenerateCreateParams, + DocumentGenerateCreateResponse, + DocumentGenerateTemplateTemplateParams, + DocumentGenerateTemplateTemplateResponse, + Documents, +} from './resources/documents'; +import { + DocumentsV1, + DocumentsV1DocumentsRetrieveResponse, + DocumentsV1GenerateCreateParams, + DocumentsV1GenerateCreateResponse, + DocumentsV1GenerateTemplateTemplateParams, + DocumentsV1GenerateTemplateTemplateResponse, +} from './resources/documents-v1'; +import { + EmailEmailsRetrieveResponse, + EmailRenderCreateParams, + EmailRenderCreateResponse, + EmailSendCreateParams, + EmailSendCreateResponse, + EmailSendTemplateTemplateParams, + EmailSendTemplateTemplateResponse, + Emails, +} from './resources/emails'; +import { + EmailsV1, + EmailsV1EmailsRetrieveResponse, + EmailsV1RenderCreateParams, + EmailsV1RenderCreateResponse, + EmailsV1SendCreateParams, + EmailsV1SendCreateResponse, + EmailsV1SendTemplateTemplateParams, + EmailsV1SendTemplateTemplateResponse, +} from './resources/emails-v1'; +import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages'; +import { PagesV1, PagesV1RenderCreateParams, PagesV1RenderCreateResponse } from './resources/pages-v1'; +import { + Project, + ProjectAPIKeysCreateParams, + ProjectAPIKeysCreateResponse, + ProjectAPIKeysListResponse, + ProjectAPIKeysRetrieveResponse, + ProjectAPIKeysUpdateParams, + ProjectAPIKeysUpdateResponse, + ProjectCurrentListResponse, + ProjectDomainsCreateParams, + ProjectDomainsCreateResponse, + ProjectDomainsListResponse, + ProjectDomainsRetrieveResponse, + ProjectDomainsUpdateParams, + ProjectDomainsUpdateResponse, + ProjectTemplatesCreateParams, + ProjectTemplatesCreateResponse, + ProjectTemplatesListResponse, + ProjectTemplatesRetrieveResponse, + ProjectTemplatesUpdateParams, + ProjectTemplatesUpdateResponse, +} from './resources/project'; +import { + ProjectV1, + ProjectV1APIKeysCreateParams, + ProjectV1APIKeysCreateResponse, + ProjectV1APIKeysListResponse, + ProjectV1APIKeysRetrieveResponse, + ProjectV1APIKeysUpdateParams, + ProjectV1APIKeysUpdateResponse, + ProjectV1CurrentListResponse, + ProjectV1DomainsCreateParams, + ProjectV1DomainsCreateResponse, + ProjectV1DomainsListResponse, + ProjectV1DomainsRetrieveResponse, + ProjectV1DomainsUpdateParams, + ProjectV1DomainsUpdateResponse, + ProjectV1TemplatesCreateParams, + ProjectV1TemplatesCreateResponse, + ProjectV1TemplatesListResponse, + ProjectV1TemplatesRetrieveResponse, + ProjectV1TemplatesUpdateParams, + ProjectV1TemplatesUpdateResponse, +} from './resources/project-v1'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -34,11 +112,6 @@ import { import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { - /** - * Defaults to process.env['UNLAYER_API_KEY']. - */ - apiKey?: string | undefined; - /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" * @@ -112,8 +185,6 @@ export interface ClientOptions { * API Client for interfacing with the Unlayer API. */ export class Unlayer { - apiKey: string; - baseURL: string; maxRetries: number; timeout: number; @@ -129,7 +200,6 @@ export class Unlayer { /** * API Client for interfacing with the Unlayer API. * - * @param {string | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? undefined] * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -138,19 +208,8 @@ export class Unlayer { * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. * @param {Record} opts.defaultQuery - Default query parameters to include with every request to the API. */ - constructor({ - baseURL = readEnv('UNLAYER_BASE_URL'), - apiKey = readEnv('UNLAYER_API_KEY'), - ...opts - }: ClientOptions = {}) { - if (apiKey === undefined) { - throw new Errors.UnlayerError( - "The UNLAYER_API_KEY environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an apiKey option, like new Unlayer({ apiKey: 'My API Key' }).", - ); - } - + constructor({ baseURL = readEnv('UNLAYER_BASE_URL'), ...opts }: ClientOptions = {}) { const options: ClientOptions = { - apiKey, ...opts, baseURL: baseURL || `https://api.unlayer.com`, }; @@ -171,8 +230,6 @@ export class Unlayer { this.#encoder = Opts.FallbackEncoder; this._options = options; - - this.apiKey = apiKey; } /** @@ -188,7 +245,6 @@ export class Unlayer { logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, - apiKey: this.apiKey, ...options, }); return client; @@ -209,10 +265,6 @@ export class Unlayer { return; } - protected async authHeaders(opts: FinalRequestOptions): Promise { - return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); - } - /** * Basic re-implementation of `qs.stringify` for primitive types. */ @@ -650,7 +702,6 @@ export class Unlayer { ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), ...getPlatformHeaders(), }, - await this.authHeaders(options), this._options.defaultHeaders, bodyHeaders, options.headers, @@ -717,25 +768,123 @@ export class Unlayer { static toFile = Uploads.toFile; + emailsV1: API.EmailsV1 = new API.EmailsV1(this); + emails: API.Emails = new API.Emails(this); + projectV1: API.ProjectV1 = new API.ProjectV1(this); project: API.Project = new API.Project(this); + documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); - emails: API.Emails = new API.Emails(this); + pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); } +Unlayer.EmailsV1 = EmailsV1; +Unlayer.Emails = Emails; +Unlayer.ProjectV1 = ProjectV1; Unlayer.Project = Project; +Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; -Unlayer.Emails = Emails; +Unlayer.PagesV1 = PagesV1; Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { Project as Project }; - - export { Documents as Documents }; - - export { Emails as Emails }; - - export { Pages as Pages }; + export { + EmailsV1 as EmailsV1, + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + }; + + export { + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + + export { + ProjectV1 as ProjectV1, + type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, + type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, + type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, + type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, + type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, + type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, + type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, + type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, + type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, + type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, + type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, + type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, + type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, + type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, + type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, + type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, + type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, + type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, + type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, + }; + + export { + Project as Project, + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; + + export { + DocumentsV1 as DocumentsV1, + type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, + type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, + type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, + type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, + type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, + }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + + export { + PagesV1 as PagesV1, + type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, + type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; } diff --git a/src/resources/documents-v1.ts b/src/resources/documents-v1.ts new file mode 100644 index 0000000..e544426 --- /dev/null +++ b/src/resources/documents-v1.ts @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class DocumentsV1 extends APIResource { + /** + * Retrieve details of a previously generated document. + */ + documentsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, options); + } + + /** + * Generate PDF document from JSON design, HTML content, or URL. + */ + generateCreate( + body: DocumentsV1GenerateCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate', { body, ...options }); + } + + /** + * Generate PDF document from an existing template with merge tags. + */ + generateTemplateTemplate( + body: DocumentsV1GenerateTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/template', { body, ...options }); + } +} + +export interface DocumentsV1DocumentsRetrieveResponse { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentsV1GenerateCreateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentsV1GenerateTemplateTemplateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentsV1GenerateCreateParams { + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * HTML content to convert to PDF + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * URL to convert to PDF + */ + url?: string; +} + +export interface DocumentsV1GenerateTemplateTemplateParams { + /** + * ID of the template to use for generation + */ + templateId: string; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace DocumentsV1 { + export { + type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, + type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, + type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, + type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, + type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, + }; +} diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 6dcfade..edca7d6 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -1,3 +1,169 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './documents/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Documents extends APIResource { + /** + * Retrieve details of a previously generated document. + */ + documentsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, options); + } + + /** + * Generate PDF document from JSON design, HTML content, or URL. + */ + generateCreate( + body: DocumentGenerateCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate', { body, ...options }); + } + + /** + * Generate PDF document from an existing template with merge tags. + */ + generateTemplateTemplate( + body: DocumentGenerateTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/template', { body, ...options }); + } +} + +export interface DocumentDocumentsRetrieveResponse { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateTemplateTemplateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateParams { + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * HTML content to convert to PDF + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * URL to convert to PDF + */ + url?: string; +} + +export interface DocumentGenerateTemplateTemplateParams { + /** + * ID of the template to use for generation + */ + templateId: string; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Documents { + export { + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; +} diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts deleted file mode 100644 index 991d6bd..0000000 --- a/src/resources/documents/documents.ts +++ /dev/null @@ -1,15 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1/v1'; -import { V1, V1RetrieveResponse } from './v1/v1'; - -export class Documents extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); -} - -Documents.V1 = V1; - -export declare namespace Documents { - export { V1 as V1, type V1RetrieveResponse as V1RetrieveResponse }; -} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts deleted file mode 100644 index 2703c77..0000000 --- a/src/resources/documents/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Documents } from './documents'; -export { V1, type V1RetrieveResponse } from './v1/index'; diff --git a/src/resources/documents/v1.ts b/src/resources/documents/v1.ts deleted file mode 100644 index d02995c..0000000 --- a/src/resources/documents/v1.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './v1/index'; diff --git a/src/resources/documents/v1/generate.ts b/src/resources/documents/v1/generate.ts deleted file mode 100644 index 64126bf..0000000 --- a/src/resources/documents/v1/generate.ts +++ /dev/null @@ -1,118 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; - -export class Generate extends APIResource { - /** - * Generate PDF document from JSON design, HTML content, or URL. - */ - create( - body: GenerateCreateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate/', { body, ...options }); - } - - /** - * Generate PDF document from an existing template with merge tags. - */ - createFromTemplate( - body: GenerateCreateFromTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate/template/', { body, ...options }); - } -} - -export interface GenerateCreateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface GenerateCreateFromTemplateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface GenerateCreateParams { - /** - * Proprietary design format JSON - */ - design?: unknown; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * HTML content to convert to PDF - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * URL to convert to PDF - */ - url?: string; -} - -export interface GenerateCreateFromTemplateParams { - /** - * ID of the template to use for generation - */ - templateId: string; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Generate { - export { - type GenerateCreateResponse as GenerateCreateResponse, - type GenerateCreateFromTemplateResponse as GenerateCreateFromTemplateResponse, - type GenerateCreateParams as GenerateCreateParams, - type GenerateCreateFromTemplateParams as GenerateCreateFromTemplateParams, - }; -} diff --git a/src/resources/documents/v1/index.ts b/src/resources/documents/v1/index.ts deleted file mode 100644 index 2aa59e3..0000000 --- a/src/resources/documents/v1/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Generate, - type GenerateCreateResponse, - type GenerateCreateFromTemplateResponse, - type GenerateCreateParams, - type GenerateCreateFromTemplateParams, -} from './generate'; -export { V1, type V1RetrieveResponse } from './v1'; diff --git a/src/resources/documents/v1/v1.ts b/src/resources/documents/v1/v1.ts deleted file mode 100644 index 0571c5b..0000000 --- a/src/resources/documents/v1/v1.ts +++ /dev/null @@ -1,81 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as GenerateAPI from './generate'; -import { - Generate, - GenerateCreateFromTemplateParams, - GenerateCreateFromTemplateResponse, - GenerateCreateParams, - GenerateCreateResponse, -} from './generate'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class V1 extends APIResource { - generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); - - /** - * Retrieve details of a previously generated document. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}/`, options); - } -} - -export interface V1RetrieveResponse { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; -} - -V1.Generate = Generate; - -export declare namespace V1 { - export { type V1RetrieveResponse as V1RetrieveResponse }; - - export { - Generate as Generate, - type GenerateCreateResponse as GenerateCreateResponse, - type GenerateCreateFromTemplateResponse as GenerateCreateFromTemplateResponse, - type GenerateCreateParams as GenerateCreateParams, - type GenerateCreateFromTemplateParams as GenerateCreateFromTemplateParams, - }; -} diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts new file mode 100644 index 0000000..f2f92a6 --- /dev/null +++ b/src/resources/emails-v1.ts @@ -0,0 +1,175 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class EmailsV1 extends APIResource { + /** + * Retrieve details of a previously sent email. + */ + emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, options); + } + + /** + * Convert design JSON to HTML with optional merge tags. + */ + renderCreate( + body: EmailsV1RenderCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/render', { body, ...options }); + } + + /** + * Send email with design JSON or HTML content. + */ + sendCreate( + body: EmailsV1SendCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send', { body, ...options }); + } + + /** + * Send email using an existing template with merge tags. + */ + sendTemplateTemplate( + body: EmailsV1SendTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send/template', { body, ...options }); + } +} + +export interface EmailsV1EmailsRetrieveResponse { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; +} + +export interface EmailsV1RenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface EmailsV1SendCreateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailsV1SendTemplateTemplateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailsV1RenderCreateParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export interface EmailsV1SendCreateParams { + /** + * Recipient email address + */ + to: string; + + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * HTML content to send + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line + */ + subject?: string; +} + +export interface EmailsV1SendTemplateTemplateParams { + /** + * ID of the template to use + */ + templateId: string; + + /** + * Recipient email address + */ + to: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +export declare namespace EmailsV1 { + export { + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + }; +} diff --git a/src/resources/emails.ts b/src/resources/emails.ts index bd0ec59..447bce6 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -1,3 +1,172 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './emails/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Emails extends APIResource { + /** + * Retrieve details of a previously sent email. + */ + emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, options); + } + + /** + * Convert design JSON to HTML with optional merge tags. + */ + renderCreate( + body: EmailRenderCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/render', { body, ...options }); + } + + /** + * Send email with design JSON or HTML content. + */ + sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/emails/v1/send', { body, ...options }); + } + + /** + * Send email using an existing template with merge tags. + */ + sendTemplateTemplate( + body: EmailSendTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send/template', { body, ...options }); + } +} + +export interface EmailEmailsRetrieveResponse { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; +} + +export interface EmailRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface EmailSendCreateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailSendTemplateTemplateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export interface EmailSendCreateParams { + /** + * Recipient email address + */ + to: string; + + /** + * Proprietary design format JSON + */ + design?: unknown; + + /** + * HTML content to send + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line + */ + subject?: string; +} + +export interface EmailSendTemplateTemplateParams { + /** + * ID of the template to use + */ + templateId: string; + + /** + * Recipient email address + */ + to: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +export declare namespace Emails { + export { + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; +} diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts deleted file mode 100644 index b324159..0000000 --- a/src/resources/emails/emails.ts +++ /dev/null @@ -1,20 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1/v1'; -import { V1, V1RenderParams, V1RenderResponse, V1RetrieveResponse } from './v1/v1'; - -export class Emails extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); -} - -Emails.V1 = V1; - -export declare namespace Emails { - export { - V1 as V1, - type V1RetrieveResponse as V1RetrieveResponse, - type V1RenderResponse as V1RenderResponse, - type V1RenderParams as V1RenderParams, - }; -} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts deleted file mode 100644 index dc35058..0000000 --- a/src/resources/emails/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Emails } from './emails'; -export { V1, type V1RetrieveResponse, type V1RenderResponse, type V1RenderParams } from './v1/index'; diff --git a/src/resources/emails/v1.ts b/src/resources/emails/v1.ts deleted file mode 100644 index d02995c..0000000 --- a/src/resources/emails/v1.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './v1/index'; diff --git a/src/resources/emails/v1/index.ts b/src/resources/emails/v1/index.ts deleted file mode 100644 index e28438b..0000000 --- a/src/resources/emails/v1/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Send, - type SendSendResponse, - type SendSendFromTemplateResponse, - type SendSendParams, - type SendSendFromTemplateParams, -} from './send'; -export { V1, type V1RetrieveResponse, type V1RenderResponse, type V1RenderParams } from './v1'; diff --git a/src/resources/emails/v1/send.ts b/src/resources/emails/v1/send.ts deleted file mode 100644 index aba8ff6..0000000 --- a/src/resources/emails/v1/send.ts +++ /dev/null @@ -1,100 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; - -export class Send extends APIResource { - /** - * Send email with design JSON or HTML content. - */ - send(body: SendSendParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/send/', { body, ...options }); - } - - /** - * Send email using an existing template with merge tags. - */ - sendFromTemplate( - body: SendSendFromTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/send/template/', { body, ...options }); - } -} - -export interface SendSendResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface SendSendFromTemplateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface SendSendParams { - /** - * Recipient email address - */ - to: string; - - /** - * Proprietary design format JSON - */ - design?: unknown; - - /** - * HTML content to send - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line - */ - subject?: string; -} - -export interface SendSendFromTemplateParams { - /** - * ID of the template to use - */ - templateId: string; - - /** - * Recipient email address - */ - to: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -export declare namespace Send { - export { - type SendSendResponse as SendSendResponse, - type SendSendFromTemplateResponse as SendSendFromTemplateResponse, - type SendSendParams as SendSendParams, - type SendSendFromTemplateParams as SendSendFromTemplateParams, - }; -} diff --git a/src/resources/emails/v1/v1.ts b/src/resources/emails/v1/v1.ts deleted file mode 100644 index 40daab2..0000000 --- a/src/resources/emails/v1/v1.ts +++ /dev/null @@ -1,101 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as SendAPI from './send'; -import { - Send, - SendSendFromTemplateParams, - SendSendFromTemplateResponse, - SendSendParams, - SendSendResponse, -} from './send'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class V1 extends APIResource { - send: SendAPI.Send = new SendAPI.Send(this._client); - - /** - * Retrieve details of a previously sent email. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}/`, options); - } - - /** - * Convert design JSON to HTML with optional merge tags. - */ - render(body: V1RenderParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/render/', { body, ...options }); - } -} - -export interface V1RetrieveResponse { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; -} - -export interface V1RenderResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface V1RenderParams { - /** - * Proprietary design format JSON - */ - design: unknown; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -V1.Send = Send; - -export declare namespace V1 { - export { - type V1RetrieveResponse as V1RetrieveResponse, - type V1RenderResponse as V1RenderResponse, - type V1RenderParams as V1RenderParams, - }; - - export { - Send as Send, - type SendSendResponse as SendSendResponse, - type SendSendFromTemplateResponse as SendSendFromTemplateResponse, - type SendSendParams as SendSendParams, - type SendSendFromTemplateParams as SendSendFromTemplateParams, - }; -} diff --git a/src/resources/index.ts b/src/resources/index.ts index 5a6059e..cee5531 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,84 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Documents } from './documents/documents'; -export { Emails } from './emails/emails'; -export { Pages } from './pages/pages'; -export { Project } from './project/project'; +export { + Documents, + type DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams, +} from './documents'; +export { + DocumentsV1, + type DocumentsV1DocumentsRetrieveResponse, + type DocumentsV1GenerateCreateResponse, + type DocumentsV1GenerateTemplateTemplateResponse, + type DocumentsV1GenerateCreateParams, + type DocumentsV1GenerateTemplateTemplateParams, +} from './documents-v1'; +export { + Emails, + type EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse, + type EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams, + type EmailSendCreateParams, + type EmailSendTemplateTemplateParams, +} from './emails'; +export { + EmailsV1, + type EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams, +} from './emails-v1'; +export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; +export { PagesV1, type PagesV1RenderCreateResponse, type PagesV1RenderCreateParams } from './pages-v1'; +export { + Project, + type ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse, + type ProjectDomainsCreateResponse, + type ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams, +} from './project'; +export { + ProjectV1, + type ProjectV1APIKeysCreateResponse, + type ProjectV1APIKeysListResponse, + type ProjectV1APIKeysRetrieveResponse, + type ProjectV1APIKeysUpdateResponse, + type ProjectV1CurrentListResponse, + type ProjectV1DomainsCreateResponse, + type ProjectV1DomainsListResponse, + type ProjectV1DomainsRetrieveResponse, + type ProjectV1DomainsUpdateResponse, + type ProjectV1TemplatesCreateResponse, + type ProjectV1TemplatesListResponse, + type ProjectV1TemplatesRetrieveResponse, + type ProjectV1TemplatesUpdateResponse, + type ProjectV1APIKeysCreateParams, + type ProjectV1APIKeysUpdateParams, + type ProjectV1DomainsCreateParams, + type ProjectV1DomainsUpdateParams, + type ProjectV1TemplatesCreateParams, + type ProjectV1TemplatesUpdateParams, +} from './project-v1'; diff --git a/src/resources/pages-v1.ts b/src/resources/pages-v1.ts new file mode 100644 index 0000000..7efc857 --- /dev/null +++ b/src/resources/pages-v1.ts @@ -0,0 +1,43 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class PagesV1 extends APIResource { + /** + * Convert page design JSON to HTML with optional merge tags. + */ + renderCreate( + body: PagesV1RenderCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/pages/v1/render', { body, ...options }); + } +} + +export interface PagesV1RenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface PagesV1RenderCreateParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace PagesV1 { + export { + type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, + type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + }; +} diff --git a/src/resources/pages.ts b/src/resources/pages.ts index c218cbe..611ddcf 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -1,3 +1,40 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './pages/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class Pages extends APIResource { + /** + * Convert page design JSON to HTML with optional merge tags. + */ + renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/pages/v1/render', { body, ...options }); + } +} + +export interface PageRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface PageRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: unknown; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Pages { + export { + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; +} diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts deleted file mode 100644 index 3ec0047..0000000 --- a/src/resources/pages/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Pages } from './pages'; -export { V1, type V1RenderResponse, type V1RenderParams } from './v1'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts deleted file mode 100644 index d93f869..0000000 --- a/src/resources/pages/pages.ts +++ /dev/null @@ -1,15 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1'; -import { V1, V1RenderParams, V1RenderResponse } from './v1'; - -export class Pages extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); -} - -Pages.V1 = V1; - -export declare namespace Pages { - export { V1 as V1, type V1RenderResponse as V1RenderResponse, type V1RenderParams as V1RenderParams }; -} diff --git a/src/resources/pages/v1.ts b/src/resources/pages/v1.ts deleted file mode 100644 index d2ccfe8..0000000 --- a/src/resources/pages/v1.ts +++ /dev/null @@ -1,37 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class V1 extends APIResource { - /** - * Convert page design JSON to HTML with optional merge tags. - */ - render(body: V1RenderParams, options?: RequestOptions): APIPromise { - return this._client.post('/pages/v1/render/', { body, ...options }); - } -} - -export interface V1RenderResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface V1RenderParams { - /** - * Proprietary design format JSON - */ - design: unknown; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace V1 { - export { type V1RenderResponse as V1RenderResponse, type V1RenderParams as V1RenderParams }; -} diff --git a/src/resources/project-v1.ts b/src/resources/project-v1.ts new file mode 100644 index 0000000..d10168d --- /dev/null +++ b/src/resources/project-v1.ts @@ -0,0 +1,516 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class ProjectV1 extends APIResource { + /** + * Create a new API key for the project. + */ + apiKeysCreate( + body: ProjectV1APIKeysCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/api-keys', { body, ...options }); + } + + /** + * Revoke API key. + */ + apiKeysDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/api-keys/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all API keys for the project. + */ + apiKeysList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/api-keys', options); + } + + /** + * Get API key details by ID. + */ + apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/api-keys/${id}`, options); + } + + /** + * Update API key settings. + */ + apiKeysUpdate( + id: string, + body: ProjectV1APIKeysUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); + } + + /** + * Get project details for the authenticated project. + */ + currentList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current', options); + } + + /** + * Add a new domain to the project. + */ + domainsCreate( + body: ProjectV1DomainsCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/domains', { body, ...options }); + } + + /** + * Remove domain from project. + */ + domainsDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all domains for the project. + */ + domainsList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains', options); + } + + /** + * Get domain details by ID. + */ + domainsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}`, options); + } + + /** + * Update domain settings. + */ + domainsUpdate( + id: string, + body: ProjectV1DomainsUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); + } + + /** + * Create a new project template. + */ + templatesCreate( + body: ProjectV1TemplatesCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/templates', { body, ...options }); + } + + /** + * Delete project template. + */ + templatesDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Get all project templates. + */ + templatesList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates', options); + } + + /** + * Get project template by ID. + */ + templatesRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}`, options); + } + + /** + * Update project template. + */ + templatesUpdate( + id: string, + body: ProjectV1TemplatesUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + } +} + +export interface ProjectV1APIKeysCreateResponse { + data?: ProjectV1APIKeysCreateResponse.Data; +} + +export namespace ProjectV1APIKeysCreateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + name?: string; + } +} + +export interface ProjectV1APIKeysListResponse { + data?: Array; +} + +export namespace ProjectV1APIKeysListResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectV1APIKeysRetrieveResponse { + data?: ProjectV1APIKeysRetrieveResponse.Data; +} + +export namespace ProjectV1APIKeysRetrieveResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectV1APIKeysUpdateResponse { + data?: ProjectV1APIKeysUpdateResponse.Data; +} + +export namespace ProjectV1APIKeysUpdateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectV1CurrentListResponse { + data?: ProjectV1CurrentListResponse.Data; +} + +export namespace ProjectV1CurrentListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectV1DomainsCreateResponse { + data?: ProjectV1DomainsCreateResponse.Data; +} + +export namespace ProjectV1DomainsCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectV1DomainsListResponse { + data?: Array; +} + +export namespace ProjectV1DomainsListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface ProjectV1DomainsRetrieveResponse { + data?: ProjectV1DomainsRetrieveResponse.Data; +} + +export namespace ProjectV1DomainsRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectV1DomainsUpdateResponse { + data?: ProjectV1DomainsUpdateResponse.Data; +} + +export namespace ProjectV1DomainsUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectV1TemplatesCreateResponse { + data?: ProjectV1TemplatesCreateResponse.Data; +} + +export namespace ProjectV1TemplatesCreateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectV1TemplatesListResponse { + data?: Array; +} + +export namespace ProjectV1TemplatesListResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectV1TemplatesRetrieveResponse { + data?: ProjectV1TemplatesRetrieveResponse.Data; +} + +export namespace ProjectV1TemplatesRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectV1TemplatesUpdateResponse { + data?: ProjectV1TemplatesUpdateResponse.Data; +} + +export namespace ProjectV1TemplatesUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectV1APIKeysCreateParams { + /** + * Name for the API key + */ + name: string; + + /** + * Allowed domains for this API key + */ + domains?: Array; +} + +export interface ProjectV1APIKeysUpdateParams { + /** + * Whether the API key is active + */ + active?: boolean; + + /** + * Updated allowed domains + */ + domains?: Array; + + /** + * Updated name for the API key + */ + name?: string; +} + +export interface ProjectV1DomainsCreateParams { + /** + * Domain name to add + */ + domain: string; +} + +export interface ProjectV1DomainsUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export interface ProjectV1TemplatesCreateParams { + /** + * Template name + */ + name: string; + + /** + * Email body content + */ + body?: string; + + /** + * Email subject line + */ + subject?: string; +} + +export interface ProjectV1TemplatesUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +export declare namespace ProjectV1 { + export { + type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, + type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, + type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, + type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, + type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, + type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, + type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, + type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, + type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, + type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, + type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, + type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, + type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, + type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, + type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, + type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, + type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, + type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, + type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, + }; +} diff --git a/src/resources/project.ts b/src/resources/project.ts index 60fc38d..70418cb 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -1,3 +1,516 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './project/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Project extends APIResource { + /** + * Create a new API key for the project. + */ + apiKeysCreate( + body: ProjectAPIKeysCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/api-keys', { body, ...options }); + } + + /** + * Revoke API key. + */ + apiKeysDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/api-keys/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all API keys for the project. + */ + apiKeysList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/api-keys', options); + } + + /** + * Get API key details by ID. + */ + apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/api-keys/${id}`, options); + } + + /** + * Update API key settings. + */ + apiKeysUpdate( + id: string, + body: ProjectAPIKeysUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); + } + + /** + * Get project details for the authenticated project. + */ + currentList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current', options); + } + + /** + * Add a new domain to the project. + */ + domainsCreate( + body: ProjectDomainsCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/domains', { body, ...options }); + } + + /** + * Remove domain from project. + */ + domainsDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all domains for the project. + */ + domainsList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains', options); + } + + /** + * Get domain details by ID. + */ + domainsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}`, options); + } + + /** + * Update domain settings. + */ + domainsUpdate( + id: string, + body: ProjectDomainsUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); + } + + /** + * Create a new project template. + */ + templatesCreate( + body: ProjectTemplatesCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/templates', { body, ...options }); + } + + /** + * Delete project template. + */ + templatesDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Get all project templates. + */ + templatesList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates', options); + } + + /** + * Get project template by ID. + */ + templatesRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}`, options); + } + + /** + * Update project template. + */ + templatesUpdate( + id: string, + body: ProjectTemplatesUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + } +} + +export interface ProjectAPIKeysCreateResponse { + data?: ProjectAPIKeysCreateResponse.Data; +} + +export namespace ProjectAPIKeysCreateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysListResponse { + data?: Array; +} + +export namespace ProjectAPIKeysListResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysRetrieveResponse { + data?: ProjectAPIKeysRetrieveResponse.Data; +} + +export namespace ProjectAPIKeysRetrieveResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysUpdateResponse { + data?: ProjectAPIKeysUpdateResponse.Data; +} + +export namespace ProjectAPIKeysUpdateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectCurrentListResponse { + data?: ProjectCurrentListResponse.Data; +} + +export namespace ProjectCurrentListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectDomainsCreateResponse { + data?: ProjectDomainsCreateResponse.Data; +} + +export namespace ProjectDomainsCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsListResponse { + data?: Array; +} + +export namespace ProjectDomainsListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface ProjectDomainsRetrieveResponse { + data?: ProjectDomainsRetrieveResponse.Data; +} + +export namespace ProjectDomainsRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsUpdateResponse { + data?: ProjectDomainsUpdateResponse.Data; +} + +export namespace ProjectDomainsUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectTemplatesCreateResponse { + data?: ProjectTemplatesCreateResponse.Data; +} + +export namespace ProjectTemplatesCreateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesListResponse { + data?: Array; +} + +export namespace ProjectTemplatesListResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesRetrieveResponse { + data?: ProjectTemplatesRetrieveResponse.Data; +} + +export namespace ProjectTemplatesRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesUpdateResponse { + data?: ProjectTemplatesUpdateResponse.Data; +} + +export namespace ProjectTemplatesUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectAPIKeysCreateParams { + /** + * Name for the API key + */ + name: string; + + /** + * Allowed domains for this API key + */ + domains?: Array; +} + +export interface ProjectAPIKeysUpdateParams { + /** + * Whether the API key is active + */ + active?: boolean; + + /** + * Updated allowed domains + */ + domains?: Array; + + /** + * Updated name for the API key + */ + name?: string; +} + +export interface ProjectDomainsCreateParams { + /** + * Domain name to add + */ + domain: string; +} + +export interface ProjectDomainsUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export interface ProjectTemplatesCreateParams { + /** + * Template name + */ + name: string; + + /** + * Email body content + */ + body?: string; + + /** + * Email subject line + */ + subject?: string; +} + +export interface ProjectTemplatesUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +export declare namespace Project { + export { + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; +} diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts deleted file mode 100644 index ee7bdc4..0000000 --- a/src/resources/project/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Project } from './project'; -export { V1, type V1GetCurrentResponse } from './v1/index'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts deleted file mode 100644 index 568bb2a..0000000 --- a/src/resources/project/project.ts +++ /dev/null @@ -1,15 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1/v1'; -import { V1, V1GetCurrentResponse } from './v1/v1'; - -export class Project extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); -} - -Project.V1 = V1; - -export declare namespace Project { - export { V1 as V1, type V1GetCurrentResponse as V1GetCurrentResponse }; -} diff --git a/src/resources/project/v1.ts b/src/resources/project/v1.ts deleted file mode 100644 index d02995c..0000000 --- a/src/resources/project/v1.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './v1/index'; diff --git a/src/resources/project/v1/api-keys.ts b/src/resources/project/v1/api-keys.ts deleted file mode 100644 index 5b8388e..0000000 --- a/src/resources/project/v1/api-keys.ts +++ /dev/null @@ -1,177 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { buildHeaders } from '../../../internal/headers'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class APIKeys extends APIResource { - /** - * Create a new API key for the project. - */ - create(body: APIKeyCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/project/v1/api-keys/', { body, ...options }); - } - - /** - * Get API key details by ID. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/api-keys/${id}/`, options); - } - - /** - * Update API key settings. - */ - update( - id: string, - body: APIKeyUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/api-keys/${id}/`, { body, ...options }); - } - - /** - * List all API keys for the project. - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/api-keys/', options); - } - - /** - * Revoke API key. - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/api-keys/${id}/`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export interface APIKeyCreateResponse { - data?: APIKeyCreateResponse.Data; -} - -export namespace APIKeyCreateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - name?: string; - } -} - -export interface APIKeyRetrieveResponse { - data?: APIKeyRetrieveResponse.Data; -} - -export namespace APIKeyRetrieveResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface APIKeyUpdateResponse { - data?: APIKeyUpdateResponse.Data; -} - -export namespace APIKeyUpdateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface APIKeyListResponse { - data?: Array; -} - -export namespace APIKeyListResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface APIKeyCreateParams { - /** - * Name for the API key - */ - name: string; - - /** - * Allowed domains for this API key - */ - domains?: Array; -} - -export interface APIKeyUpdateParams { - /** - * Whether the API key is active - */ - active?: boolean; - - /** - * Updated allowed domains - */ - domains?: Array; - - /** - * Updated name for the API key - */ - name?: string; -} - -export declare namespace APIKeys { - export { - type APIKeyCreateResponse as APIKeyCreateResponse, - type APIKeyRetrieveResponse as APIKeyRetrieveResponse, - type APIKeyUpdateResponse as APIKeyUpdateResponse, - type APIKeyListResponse as APIKeyListResponse, - type APIKeyCreateParams as APIKeyCreateParams, - type APIKeyUpdateParams as APIKeyUpdateParams, - }; -} diff --git a/src/resources/project/v1/domains.ts b/src/resources/project/v1/domains.ts deleted file mode 100644 index 38dc6c2..0000000 --- a/src/resources/project/v1/domains.ts +++ /dev/null @@ -1,148 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { buildHeaders } from '../../../internal/headers'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class Domains extends APIResource { - /** - * Add a new domain to the project. - */ - create(body: DomainCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/project/v1/domains/', { body, ...options }); - } - - /** - * Get domain details by ID. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}/`, options); - } - - /** - * Update domain settings. - */ - update( - id: string, - body: DomainUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}/`, { body, ...options }); - } - - /** - * List all domains for the project. - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains/', options); - } - - /** - * Remove domain from project. - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}/`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export interface DomainCreateResponse { - data?: DomainCreateResponse.Data; -} - -export namespace DomainCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainRetrieveResponse { - data?: DomainRetrieveResponse.Data; -} - -export namespace DomainRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainUpdateResponse { - data?: DomainUpdateResponse.Data; -} - -export namespace DomainUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainListResponse { - data?: Array; -} - -export namespace DomainListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface DomainCreateParams { - /** - * Domain name to add - */ - domain: string; -} - -export interface DomainUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export declare namespace Domains { - export { - type DomainCreateResponse as DomainCreateResponse, - type DomainRetrieveResponse as DomainRetrieveResponse, - type DomainUpdateResponse as DomainUpdateResponse, - type DomainListResponse as DomainListResponse, - type DomainCreateParams as DomainCreateParams, - type DomainUpdateParams as DomainUpdateParams, - }; -} diff --git a/src/resources/project/v1/index.ts b/src/resources/project/v1/index.ts deleted file mode 100644 index 3677d68..0000000 --- a/src/resources/project/v1/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - APIKeys, - type APIKeyCreateResponse, - type APIKeyRetrieveResponse, - type APIKeyUpdateResponse, - type APIKeyListResponse, - type APIKeyCreateParams, - type APIKeyUpdateParams, -} from './api-keys'; -export { - Domains, - type DomainCreateResponse, - type DomainRetrieveResponse, - type DomainUpdateResponse, - type DomainListResponse, - type DomainCreateParams, - type DomainUpdateParams, -} from './domains'; -export { - Templates, - type TemplateCreateResponse, - type TemplateRetrieveResponse, - type TemplateUpdateResponse, - type TemplateListResponse, - type TemplateCreateParams, - type TemplateUpdateParams, -} from './templates'; -export { V1, type V1GetCurrentResponse } from './v1'; diff --git a/src/resources/project/v1/templates.ts b/src/resources/project/v1/templates.ts deleted file mode 100644 index b8e29a3..0000000 --- a/src/resources/project/v1/templates.ts +++ /dev/null @@ -1,176 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { buildHeaders } from '../../../internal/headers'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class Templates extends APIResource { - /** - * Create a new project template. - */ - create(body: TemplateCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/project/v1/templates/', { body, ...options }); - } - - /** - * Get project template by ID. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}/`, options); - } - - /** - * Update project template. - */ - update( - id: string, - body: TemplateUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}/`, { body, ...options }); - } - - /** - * Get all project templates. - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates/', options); - } - - /** - * Delete project template. - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}/`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export interface TemplateCreateResponse { - data?: TemplateCreateResponse.Data; -} - -export namespace TemplateCreateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface TemplateRetrieveResponse { - data?: TemplateRetrieveResponse.Data; -} - -export namespace TemplateRetrieveResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface TemplateUpdateResponse { - data?: TemplateUpdateResponse.Data; -} - -export namespace TemplateUpdateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface TemplateListResponse { - data?: Array; -} - -export namespace TemplateListResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface TemplateCreateParams { - /** - * Template name - */ - name: string; - - /** - * Email body content - */ - body?: string; - - /** - * Email subject line - */ - subject?: string; -} - -export interface TemplateUpdateParams { - /** - * Updated email body content - */ - body?: string; - - /** - * Updated template name - */ - name?: string; - - /** - * Updated email subject line - */ - subject?: string; -} - -export declare namespace Templates { - export { - type TemplateCreateResponse as TemplateCreateResponse, - type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateUpdateResponse as TemplateUpdateResponse, - type TemplateListResponse as TemplateListResponse, - type TemplateCreateParams as TemplateCreateParams, - type TemplateUpdateParams as TemplateUpdateParams, - }; -} diff --git a/src/resources/project/v1/v1.ts b/src/resources/project/v1/v1.ts deleted file mode 100644 index 03405f8..0000000 --- a/src/resources/project/v1/v1.ts +++ /dev/null @@ -1,112 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as APIKeysAPI from './api-keys'; -import { - APIKeyCreateParams, - APIKeyCreateResponse, - APIKeyListResponse, - APIKeyRetrieveResponse, - APIKeyUpdateParams, - APIKeyUpdateResponse, - APIKeys, -} from './api-keys'; -import * as DomainsAPI from './domains'; -import { - DomainCreateParams, - DomainCreateResponse, - DomainListResponse, - DomainRetrieveResponse, - DomainUpdateParams, - DomainUpdateResponse, - Domains, -} from './domains'; -import * as TemplatesAPI from './templates'; -import { - TemplateCreateParams, - TemplateCreateResponse, - TemplateListResponse, - TemplateRetrieveResponse, - TemplateUpdateParams, - TemplateUpdateResponse, - Templates, -} from './templates'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; - -export class V1 extends APIResource { - apiKeys: APIKeysAPI.APIKeys = new APIKeysAPI.APIKeys(this._client); - domains: DomainsAPI.Domains = new DomainsAPI.Domains(this._client); - templates: TemplatesAPI.Templates = new TemplatesAPI.Templates(this._client); - - /** - * Get project details for the authenticated project. - */ - getCurrent(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current/', options); - } -} - -export interface V1GetCurrentResponse { - data?: V1GetCurrentResponse.Data; -} - -export namespace V1GetCurrentResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -V1.APIKeys = APIKeys; -V1.Domains = Domains; -V1.Templates = Templates; - -export declare namespace V1 { - export { type V1GetCurrentResponse as V1GetCurrentResponse }; - - export { - APIKeys as APIKeys, - type APIKeyCreateResponse as APIKeyCreateResponse, - type APIKeyRetrieveResponse as APIKeyRetrieveResponse, - type APIKeyUpdateResponse as APIKeyUpdateResponse, - type APIKeyListResponse as APIKeyListResponse, - type APIKeyCreateParams as APIKeyCreateParams, - type APIKeyUpdateParams as APIKeyUpdateParams, - }; - - export { - Domains as Domains, - type DomainCreateResponse as DomainCreateResponse, - type DomainRetrieveResponse as DomainRetrieveResponse, - type DomainUpdateResponse as DomainUpdateResponse, - type DomainListResponse as DomainListResponse, - type DomainCreateParams as DomainCreateParams, - type DomainUpdateParams as DomainUpdateParams, - }; - - export { - Templates as Templates, - type TemplateCreateResponse as TemplateCreateResponse, - type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateUpdateResponse as TemplateUpdateResponse, - type TemplateListResponse as TemplateListResponse, - type TemplateCreateParams as TemplateCreateParams, - type TemplateUpdateParams as TemplateUpdateParams, - }; -} diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents-v1.test.ts new file mode 100644 index 0000000..e3bd6e3 --- /dev/null +++ b/tests/api-resources/documents-v1.test.ts @@ -0,0 +1,64 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource documentsV1', () => { + test('documentsRetrieve', async () => { + const responsePromise = client.documentsV1.documentsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('generateCreate', async () => { + const responsePromise = client.documentsV1.generateCreate(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('generateCreate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.documentsV1.generateCreate( + { + design: {}, + filename: 'filename', + html: 'html', + mergeTags: { foo: 'string' }, + url: 'https://example.com', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('generateTemplateTemplate: only required params', async () => { + const responsePromise = client.documentsV1.generateTemplateTemplate({ templateId: 'templateId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('generateTemplateTemplate: required and optional params', async () => { + const response = await client.documentsV1.generateTemplateTemplate({ + templateId: 'templateId', + filename: 'filename', + mergeTags: { foo: 'string' }, + }); + }); +}); diff --git a/tests/api-resources/documents/v1/generate.test.ts b/tests/api-resources/documents.test.ts similarity index 53% rename from tests/api-resources/documents/v1/generate.test.ts rename to tests/api-resources/documents.test.ts index affc37f..039f27a 100644 --- a/tests/api-resources/documents/v1/generate.test.ts +++ b/tests/api-resources/documents.test.ts @@ -1,16 +1,23 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Unlayer from 'unlayer'; +import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource documents', () => { + test('documentsRetrieve', async () => { + const responsePromise = client.documents.documentsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); -describe('resource generate', () => { - // Prism tests are disabled - test.skip('create', async () => { - const responsePromise = client.documents.v1.generate.create(); + test('generateCreate', async () => { + const responsePromise = client.documents.generateCreate(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,11 +27,10 @@ describe('resource generate', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('create: request options and params are passed correctly', async () => { + test('generateCreate: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.documents.v1.generate.create( + client.documents.generateCreate( { design: {}, filename: 'filename', @@ -37,9 +43,8 @@ describe('resource generate', () => { ).rejects.toThrow(Unlayer.NotFoundError); }); - // Prism tests are disabled - test.skip('createFromTemplate: only required params', async () => { - const responsePromise = client.documents.v1.generate.createFromTemplate({ templateId: 'templateId' }); + test('generateTemplateTemplate: only required params', async () => { + const responsePromise = client.documents.generateTemplateTemplate({ templateId: 'templateId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -49,9 +54,8 @@ describe('resource generate', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('createFromTemplate: required and optional params', async () => { - const response = await client.documents.v1.generate.createFromTemplate({ + test('generateTemplateTemplate: required and optional params', async () => { + const response = await client.documents.generateTemplateTemplate({ templateId: 'templateId', filename: 'filename', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/documents/v1/v1.test.ts b/tests/api-resources/documents/v1/v1.test.ts deleted file mode 100644 index 538a6ed..0000000 --- a/tests/api-resources/documents/v1/v1.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.documents.v1.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts new file mode 100644 index 0000000..bdde36f --- /dev/null +++ b/tests/api-resources/emails-v1.test.ts @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource emailsV1', () => { + test('emailsRetrieve', async () => { + const responsePromise = client.emailsV1.emailsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: only required params', async () => { + const responsePromise = client.emailsV1.renderCreate({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: required and optional params', async () => { + const response = await client.emailsV1.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + }); + + test('sendCreate: only required params', async () => { + const responsePromise = client.emailsV1.sendCreate({ to: 'dev@stainless.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('sendCreate: required and optional params', async () => { + const response = await client.emailsV1.sendCreate({ + to: 'dev@stainless.com', + design: {}, + html: 'html', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); + + test('sendTemplateTemplate: only required params', async () => { + const responsePromise = client.emailsV1.sendTemplateTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('sendTemplateTemplate: required and optional params', async () => { + const response = await client.emailsV1.sendTemplateTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); +}); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts new file mode 100644 index 0000000..99b0c83 --- /dev/null +++ b/tests/api-resources/emails.test.ts @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource emails', () => { + test('emailsRetrieve', async () => { + const responsePromise = client.emails.emailsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: only required params', async () => { + const responsePromise = client.emails.renderCreate({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: required and optional params', async () => { + const response = await client.emails.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + }); + + test('sendCreate: only required params', async () => { + const responsePromise = client.emails.sendCreate({ to: 'dev@stainless.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('sendCreate: required and optional params', async () => { + const response = await client.emails.sendCreate({ + to: 'dev@stainless.com', + design: {}, + html: 'html', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); + + test('sendTemplateTemplate: only required params', async () => { + const responsePromise = client.emails.sendTemplateTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('sendTemplateTemplate: required and optional params', async () => { + const response = await client.emails.sendTemplateTemplate({ + templateId: 'templateId', + to: 'dev@stainless.com', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); +}); diff --git a/tests/api-resources/emails/v1/send.test.ts b/tests/api-resources/emails/v1/send.test.ts deleted file mode 100644 index 26872d8..0000000 --- a/tests/api-resources/emails/v1/send.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource send', () => { - // Prism tests are disabled - test.skip('send: only required params', async () => { - const responsePromise = client.emails.v1.send.send({ to: 'dev@stainless.com' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('send: required and optional params', async () => { - const response = await client.emails.v1.send.send({ - to: 'dev@stainless.com', - design: {}, - html: 'html', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); - }); - - // Prism tests are disabled - test.skip('sendFromTemplate: only required params', async () => { - const responsePromise = client.emails.v1.send.sendFromTemplate({ - templateId: 'templateId', - to: 'dev@stainless.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('sendFromTemplate: required and optional params', async () => { - const response = await client.emails.v1.send.sendFromTemplate({ - templateId: 'templateId', - to: 'dev@stainless.com', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); - }); -}); diff --git a/tests/api-resources/emails/v1/v1.test.ts b/tests/api-resources/emails/v1/v1.test.ts deleted file mode 100644 index 2296fd8..0000000 --- a/tests/api-resources/emails/v1/v1.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.emails.v1.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('render: only required params', async () => { - const responsePromise = client.emails.v1.render({ design: {} }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('render: required and optional params', async () => { - const response = await client.emails.v1.render({ design: {}, mergeTags: { foo: 'string' } }); - }); -}); diff --git a/tests/api-resources/pages-v1.test.ts b/tests/api-resources/pages-v1.test.ts new file mode 100644 index 0000000..129c470 --- /dev/null +++ b/tests/api-resources/pages-v1.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource pagesV1', () => { + test('renderCreate: only required params', async () => { + const responsePromise = client.pagesV1.renderCreate({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: required and optional params', async () => { + const response = await client.pagesV1.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + }); +}); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts new file mode 100644 index 0000000..9efaa8a --- /dev/null +++ b/tests/api-resources/pages.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource pages', () => { + test('renderCreate: only required params', async () => { + const responsePromise = client.pages.renderCreate({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('renderCreate: required and optional params', async () => { + const response = await client.pages.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + }); +}); diff --git a/tests/api-resources/pages/v1.test.ts b/tests/api-resources/pages/v1.test.ts deleted file mode 100644 index 3dbe14f..0000000 --- a/tests/api-resources/pages/v1.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - // Prism tests are disabled - test.skip('render: only required params', async () => { - const responsePromise = client.pages.v1.render({ design: {} }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('render: required and optional params', async () => { - const response = await client.pages.v1.render({ design: {}, mergeTags: { foo: 'string' } }); - }); -}); diff --git a/tests/api-resources/project-v1.test.ts b/tests/api-resources/project-v1.test.ts new file mode 100644 index 0000000..bfc2831 --- /dev/null +++ b/tests/api-resources/project-v1.test.ts @@ -0,0 +1,228 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource projectV1', () => { + test('apiKeysCreate: only required params', async () => { + const responsePromise = client.projectV1.apiKeysCreate({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysCreate: required and optional params', async () => { + const response = await client.projectV1.apiKeysCreate({ name: 'name', domains: ['string'] }); + }); + + test('apiKeysDelete', async () => { + const responsePromise = client.projectV1.apiKeysDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysList', async () => { + const responsePromise = client.projectV1.apiKeysList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysRetrieve', async () => { + const responsePromise = client.projectV1.apiKeysRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysUpdate', async () => { + const responsePromise = client.projectV1.apiKeysUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projectV1.apiKeysUpdate( + 'id', + { active: true, domains: ['string'], name: 'name' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('currentList', async () => { + const responsePromise = client.projectV1.currentList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsCreate: only required params', async () => { + const responsePromise = client.projectV1.domainsCreate({ domain: 'domain' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsCreate: required and optional params', async () => { + const response = await client.projectV1.domainsCreate({ domain: 'domain' }); + }); + + test('domainsDelete', async () => { + const responsePromise = client.projectV1.domainsDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsList', async () => { + const responsePromise = client.projectV1.domainsList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsRetrieve', async () => { + const responsePromise = client.projectV1.domainsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsUpdate', async () => { + const responsePromise = client.projectV1.domainsUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projectV1.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('templatesCreate: only required params', async () => { + const responsePromise = client.projectV1.templatesCreate({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesCreate: required and optional params', async () => { + const response = await client.projectV1.templatesCreate({ + name: 'name', + body: 'body', + subject: 'subject', + }); + }); + + test('templatesDelete', async () => { + const responsePromise = client.projectV1.templatesDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesList', async () => { + const responsePromise = client.projectV1.templatesList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesRetrieve', async () => { + const responsePromise = client.projectV1.templatesRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesUpdate', async () => { + const responsePromise = client.projectV1.templatesUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projectV1.templatesUpdate( + 'id', + { body: 'body', name: 'name', subject: 'subject' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts new file mode 100644 index 0000000..4e2bcf0 --- /dev/null +++ b/tests/api-resources/project.test.ts @@ -0,0 +1,224 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); + +describe('resource project', () => { + test('apiKeysCreate: only required params', async () => { + const responsePromise = client.project.apiKeysCreate({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysCreate: required and optional params', async () => { + const response = await client.project.apiKeysCreate({ name: 'name', domains: ['string'] }); + }); + + test('apiKeysDelete', async () => { + const responsePromise = client.project.apiKeysDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysList', async () => { + const responsePromise = client.project.apiKeysList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysRetrieve', async () => { + const responsePromise = client.project.apiKeysRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysUpdate', async () => { + const responsePromise = client.project.apiKeysUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('apiKeysUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.apiKeysUpdate( + 'id', + { active: true, domains: ['string'], name: 'name' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('currentList', async () => { + const responsePromise = client.project.currentList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsCreate: only required params', async () => { + const responsePromise = client.project.domainsCreate({ domain: 'domain' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsCreate: required and optional params', async () => { + const response = await client.project.domainsCreate({ domain: 'domain' }); + }); + + test('domainsDelete', async () => { + const responsePromise = client.project.domainsDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsList', async () => { + const responsePromise = client.project.domainsList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsRetrieve', async () => { + const responsePromise = client.project.domainsRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsUpdate', async () => { + const responsePromise = client.project.domainsUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('domainsUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('templatesCreate: only required params', async () => { + const responsePromise = client.project.templatesCreate({ name: 'name' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesCreate: required and optional params', async () => { + const response = await client.project.templatesCreate({ name: 'name', body: 'body', subject: 'subject' }); + }); + + test('templatesDelete', async () => { + const responsePromise = client.project.templatesDelete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesList', async () => { + const responsePromise = client.project.templatesList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesRetrieve', async () => { + const responsePromise = client.project.templatesRetrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesUpdate', async () => { + const responsePromise = client.project.templatesUpdate('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('templatesUpdate: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.templatesUpdate( + 'id', + { body: 'body', name: 'name', subject: 'subject' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/project/v1/api-keys.test.ts b/tests/api-resources/project/v1/api-keys.test.ts deleted file mode 100644 index 007ac27..0000000 --- a/tests/api-resources/project/v1/api-keys.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource apiKeys', () => { - // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.project.v1.apiKeys.create({ name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.project.v1.apiKeys.create({ name: 'name', domains: ['string'] }); - }); - - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.project.v1.apiKeys.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update', async () => { - const responsePromise = client.project.v1.apiKeys.update('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.apiKeys.update( - 'id', - { active: true, domains: ['string'], name: 'name' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.project.v1.apiKeys.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.project.v1.apiKeys.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/project/v1/domains.test.ts b/tests/api-resources/project/v1/domains.test.ts deleted file mode 100644 index 1e0e635..0000000 --- a/tests/api-resources/project/v1/domains.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource domains', () => { - // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.project.v1.domains.create({ domain: 'domain' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.project.v1.domains.create({ domain: 'domain' }); - }); - - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.project.v1.domains.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update', async () => { - const responsePromise = client.project.v1.domains.update('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.domains.update('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.project.v1.domains.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.project.v1.domains.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/project/v1/templates.test.ts b/tests/api-resources/project/v1/templates.test.ts deleted file mode 100644 index b8f0682..0000000 --- a/tests/api-resources/project/v1/templates.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource templates', () => { - // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.project.v1.templates.create({ name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.project.v1.templates.create({ - name: 'name', - body: 'body', - subject: 'subject', - }); - }); - - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.project.v1.templates.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update', async () => { - const responsePromise = client.project.v1.templates.update('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('update: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.templates.update( - 'id', - { body: 'body', name: 'name', subject: 'subject' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.project.v1.templates.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.project.v1.templates.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/project/v1/v1.test.ts b/tests/api-resources/project/v1/v1.test.ts deleted file mode 100644 index 76cb40c..0000000 --- a/tests/api-resources/project/v1/v1.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from 'unlayer'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - // Prism tests are disabled - test.skip('getCurrent', async () => { - const responsePromise = client.project.v1.getCurrent(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 5566771..eff76d7 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from 'unlayer/internal/utils/base64'; +import { fromBase64, toBase64 } from '@unlayer/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index 385421a..0509e8e 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from 'unlayer/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@unlayer/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 59ce14f..02d5fad 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from 'unlayer/internal/uploads'; -import { toFile } from 'unlayer/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@unlayer/sdk/internal/uploads'; +import { toFile } from '@unlayer/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 1165c4d..89ec21b 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from 'unlayer/core/api-promise'; +import { APIPromise } from '@unlayer/sdk/core/api-promise'; import util from 'node:util'; -import Unlayer from 'unlayer'; -import { APIUserAbortError } from 'unlayer'; +import Unlayer from '@unlayer/sdk'; +import { APIUserAbortError } from '@unlayer/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { @@ -23,7 +23,6 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-My-Default-Header': '2' }, - apiKey: 'My API Key', }); test('they are used in the request', async () => { @@ -87,14 +86,14 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, logLevel: 'debug' }); await forceAPIResponseForClient(client); expect(debugMock).toHaveBeenCalled(); }); test('default logLevel is warn', async () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.logLevel).toBe('warn'); }); @@ -107,7 +106,7 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, logLevel: 'info' }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -123,7 +122,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger }); expect(client.logLevel).toBe('debug'); await forceAPIResponseForClient(client); @@ -140,7 +139,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger }); expect(client.logLevel).toBe('warn'); expect(warnMock).toHaveBeenCalledWith( 'process.env[\'UNLAYER_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', @@ -157,7 +156,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, logLevel: 'off' }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -173,7 +172,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, logLevel: 'debug' }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); }); @@ -181,11 +180,7 @@ describe('instantiate client', () => { describe('defaultQuery', () => { test('with null query params given', () => { - const client = new Unlayer({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo' }, - apiKey: 'My API Key', - }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' } }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); @@ -193,17 +188,12 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo', hello: 'world' }, - apiKey: 'My API Key', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); test('overriding with `undefined`', () => { - const client = new Unlayer({ - baseURL: 'http://localhost:5000/', - defaultQuery: { hello: 'world' }, - apiKey: 'My API Key', - }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' } }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); }); @@ -211,7 +201,6 @@ describe('instantiate client', () => { test('custom fetch', async () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', fetch: (url) => { return Promise.resolve( new Response(JSON.stringify({ url, custom: true }), { @@ -227,17 +216,12 @@ describe('instantiate client', () => { test('explicit global fetch', async () => { // make sure the global fetch type is assignable to our Fetch type - const client = new Unlayer({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: defaultFetch, - }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', fetch: defaultFetch }); }); test('custom signal', async () => { const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - apiKey: 'My API Key', fetch: (...args) => { return new Promise((resolve, reject) => setTimeout( @@ -267,7 +251,7 @@ describe('instantiate client', () => { return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', fetch: testFetch }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -275,12 +259,12 @@ describe('instantiate client', () => { describe('baseUrl', () => { test('trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); test('no trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); @@ -289,37 +273,37 @@ describe('instantiate client', () => { }); test('explicit option', () => { - const client = new Unlayer({ baseURL: 'https://example.com', apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'https://example.com' }); expect(client.baseURL).toEqual('https://example.com'); }); test('env variable', () => { process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.baseURL).toEqual('https://example.com/from_env'); }); test('empty env variable', () => { process.env['UNLAYER_BASE_URL'] = ''; // empty - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('blank env variable', () => { process.env['UNLAYER_BASE_URL'] = ' '; // blank - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('in request options', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/option/foo', ); }); test('in request options overridden by client options', () => { - const client = new Unlayer({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/client' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/client/foo', ); @@ -327,7 +311,7 @@ describe('instantiate client', () => { test('in request options overridden by env variable', () => { process.env['UNLAYER_BASE_URL'] = 'http://localhost:5000/env'; - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/env/foo', ); @@ -335,17 +319,17 @@ describe('instantiate client', () => { }); test('maxRetries option is correctly set', () => { - const client = new Unlayer({ maxRetries: 4, apiKey: 'My API Key' }); + const client = new Unlayer({ maxRetries: 4 }); expect(client.maxRetries).toEqual(4); // default - const client2 = new Unlayer({ apiKey: 'My API Key' }); + const client2 = new Unlayer({}); expect(client2.maxRetries).toEqual(2); }); describe('withOptions', () => { test('creates a new client with overridden options', async () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3 }); const newClient = client.withOptions({ maxRetries: 5, @@ -370,7 +354,6 @@ describe('instantiate client', () => { baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-Test-Header': 'test-value' }, defaultQuery: { 'test-param': 'test-value' }, - apiKey: 'My API Key', }); const newClient = client.withOptions({ @@ -385,7 +368,7 @@ describe('instantiate client', () => { }); test('respects runtime property changes when creating new client', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000 }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -410,24 +393,10 @@ describe('instantiate client', () => { expect(newClient.buildURL('/bar', null)).toEqual('http://localhost:6000/bar'); }); }); - - test('with environment variable arguments', () => { - // set options via env var - process.env['UNLAYER_API_KEY'] = 'My API Key'; - const client = new Unlayer(); - expect(client.apiKey).toBe('My API Key'); - }); - - test('with overridden environment variable arguments', () => { - // set options via env var - process.env['UNLAYER_API_KEY'] = 'another My API Key'; - const client = new Unlayer({ apiKey: 'My API Key' }); - expect(client.apiKey).toBe('My API Key'); - }); }); describe('request building', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); describe('custom headers', () => { test('handles undefined', async () => { @@ -446,7 +415,7 @@ describe('request building', () => { }); describe('default encoder', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({}); class Serializable { toJSON() { @@ -531,7 +500,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + const client = new Unlayer({ timeout: 10, fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -561,7 +530,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -585,7 +554,7 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); expect( await client.request({ @@ -615,7 +584,6 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, defaultHeaders: { 'X-Stainless-Retry-Count': null }, @@ -647,7 +615,7 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); expect( await client.request({ @@ -677,7 +645,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -707,7 +675,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); diff --git a/tests/path.test.ts b/tests/path.test.ts index 9f8f4b6..510298d 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from 'unlayer/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@unlayer/sdk/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 53bba53..4f47883 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Unlayer } from 'unlayer'; +import { Unlayer } from '@unlayer/sdk'; const { stringifyQuery } = Unlayer.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index b4686ca..7765432 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from 'unlayer/internal/to-file'; -import { toFile } from 'unlayer/core/uploads'; +import type { ResponseLike } from '@unlayer/sdk/internal/to-file'; +import { toFile } from '@unlayer/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('unlayer/core/uploads'); + const uploads = await import('@unlayer/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 8fae373..5a9d0af 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "unlayer/*": ["./dist/src/*"], - "unlayer": ["./dist/src/index.ts"] + "@unlayer/sdk/*": ["./dist/src/*"], + "@unlayer/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 284b45c..e28a793 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "moduleResolution": "node", "esModuleInterop": true, "paths": { - "unlayer/*": ["./src/*"], - "unlayer": ["./src/index.ts"] + "@unlayer/sdk/*": ["./src/*"], + "@unlayer/sdk": ["./src/index.ts"] }, "noEmit": true, From 697cb20a1044064b106d892e497485e9b7e56595 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:44:21 +0000 Subject: [PATCH 015/118] feat(api): api update --- .stats.yml | 6 +- README.md | 8 +- api.md | 104 +++++++++---------- src/client.ts | 125 ++++++++++++++--------- tests/api-resources/documents-v1.test.ts | 5 +- tests/api-resources/documents.test.ts | 5 +- tests/api-resources/emails-v1.test.ts | 5 +- tests/api-resources/emails.test.ts | 5 +- tests/api-resources/pages-v1.test.ts | 5 +- tests/api-resources/pages.test.ts | 5 +- tests/api-resources/project-v1.test.ts | 5 +- tests/api-resources/project.test.ts | 5 +- tests/index.test.ts | 96 +++++++++++------ 13 files changed, 233 insertions(+), 146 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3f69762..a781546 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-9c0284025bec8c18271ce41a95293d975923e9ef9b3e1ff38890a04163c1b3de.yml -openapi_spec_hash: f0bec2b2df750ce635ad4b2e4a05cde1 -config_hash: 1799607c695a40200c35bb8fa5685014 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-fc81363e6d0ba052e31137423ff1b8a013e586045837c40cc625b7a9feff8cf5.yml +openapi_spec_hash: 6cd80e99a1c0accc93055b2e0fe3773d +config_hash: f84271374781c3e600f1a9d0757e53a0 diff --git a/README.md b/README.md index 27b8a90..827d403 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,9 @@ The full API of this library can be found in [api.md](api.md). ```js import Unlayer from '@unlayer/sdk'; -const client = new Unlayer(); +const client = new Unlayer({ + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted +}); const response = await client.projectV1.currentList(); @@ -40,7 +42,9 @@ This library includes TypeScript definitions for all request params and response ```ts import Unlayer from '@unlayer/sdk'; -const client = new Unlayer(); +const client = new Unlayer({ + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted +}); const response: Unlayer.ProjectV1CurrentListResponse = await client.projectV1.currentList(); ``` diff --git a/api.md b/api.md index 49167ca..d89dd07 100644 --- a/api.md +++ b/api.md @@ -1,34 +1,50 @@ -# EmailsV1 +# DocumentsV1 Types: -- EmailsV1EmailsRetrieveResponse -- EmailsV1RenderCreateResponse -- EmailsV1SendCreateResponse -- EmailsV1SendTemplateTemplateResponse +- DocumentsV1DocumentsRetrieveResponse +- DocumentsV1GenerateCreateResponse +- DocumentsV1GenerateTemplateTemplateResponse Methods: -- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse -- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse -- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse -- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse +- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse +- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse +- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse -# Emails +# Documents Types: -- EmailEmailsRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + +# PagesV1 + +Types: + +- PagesV1RenderCreateResponse + +Methods: + +- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse + +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse # ProjectV1 @@ -104,50 +120,34 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# DocumentsV1 - -Types: - -- DocumentsV1DocumentsRetrieveResponse -- DocumentsV1GenerateCreateResponse -- DocumentsV1GenerateTemplateTemplateResponse - -Methods: - -- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse -- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse -- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - -# PagesV1 +# EmailsV1 Types: -- PagesV1RenderCreateResponse +- EmailsV1EmailsRetrieveResponse +- EmailsV1RenderCreateResponse +- EmailsV1SendCreateResponse +- EmailsV1SendTemplateTemplateResponse Methods: -- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse +- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse +- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse +- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse +- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse -# Pages +# Emails Types: -- PageRenderCreateResponse +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 58e3524..5a24e4e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -112,6 +112,11 @@ import { import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { + /** + * Defaults to process.env['UNLAYER_API_KEY']. + */ + apiKey?: string | undefined; + /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" * @@ -185,6 +190,8 @@ export interface ClientOptions { * API Client for interfacing with the Unlayer API. */ export class Unlayer { + apiKey: string; + baseURL: string; maxRetries: number; timeout: number; @@ -200,6 +207,7 @@ export class Unlayer { /** * API Client for interfacing with the Unlayer API. * + * @param {string | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? undefined] * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -208,8 +216,19 @@ export class Unlayer { * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. * @param {Record} opts.defaultQuery - Default query parameters to include with every request to the API. */ - constructor({ baseURL = readEnv('UNLAYER_BASE_URL'), ...opts }: ClientOptions = {}) { + constructor({ + baseURL = readEnv('UNLAYER_BASE_URL'), + apiKey = readEnv('UNLAYER_API_KEY'), + ...opts + }: ClientOptions = {}) { + if (apiKey === undefined) { + throw new Errors.UnlayerError( + "The UNLAYER_API_KEY environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an apiKey option, like new Unlayer({ apiKey: 'My API Key' }).", + ); + } + const options: ClientOptions = { + apiKey, ...opts, baseURL: baseURL || `https://api.unlayer.com`, }; @@ -230,6 +249,8 @@ export class Unlayer { this.#encoder = Opts.FallbackEncoder; this._options = options; + + this.apiKey = apiKey; } /** @@ -245,6 +266,7 @@ export class Unlayer { logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, + apiKey: this.apiKey, ...options, }); return client; @@ -265,6 +287,10 @@ export class Unlayer { return; } + protected async authHeaders(opts: FinalRequestOptions): Promise { + return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); + } + /** * Basic re-implementation of `qs.stringify` for primitive types. */ @@ -702,6 +728,7 @@ export class Unlayer { ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), ...getPlatformHeaders(), }, + await this.authHeaders(options), this._options.defaultHeaders, bodyHeaders, options.headers, @@ -768,48 +795,56 @@ export class Unlayer { static toFile = Uploads.toFile; - emailsV1: API.EmailsV1 = new API.EmailsV1(this); - emails: API.Emails = new API.Emails(this); - projectV1: API.ProjectV1 = new API.ProjectV1(this); - project: API.Project = new API.Project(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); + projectV1: API.ProjectV1 = new API.ProjectV1(this); + project: API.Project = new API.Project(this); + emailsV1: API.EmailsV1 = new API.EmailsV1(this); + emails: API.Emails = new API.Emails(this); } -Unlayer.EmailsV1 = EmailsV1; -Unlayer.Emails = Emails; -Unlayer.ProjectV1 = ProjectV1; -Unlayer.Project = Project; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; Unlayer.Pages = Pages; +Unlayer.ProjectV1 = ProjectV1; +Unlayer.Project = Project; +Unlayer.EmailsV1 = EmailsV1; +Unlayer.Emails = Emails; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; export { - EmailsV1 as EmailsV1, - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + DocumentsV1 as DocumentsV1, + type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, + type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, + type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, + type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, + type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, }; export { - Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + + export { + PagesV1 as PagesV1, + type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, + type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, }; export { @@ -859,32 +894,24 @@ export declare namespace Unlayer { }; export { - DocumentsV1 as DocumentsV1, - type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, - type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, - type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, - type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, - type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, - }; - - export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; - - export { - PagesV1 as PagesV1, - type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, - type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + EmailsV1 as EmailsV1, + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, }; export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; } diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents-v1.test.ts index e3bd6e3..c3e5def 100644 --- a/tests/api-resources/documents-v1.test.ts +++ b/tests/api-resources/documents-v1.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource documentsV1', () => { test('documentsRetrieve', async () => { diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 039f27a..22f3fed 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource documents', () => { test('documentsRetrieve', async () => { diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index bdde36f..d0ecf34 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource emailsV1', () => { test('emailsRetrieve', async () => { diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index 99b0c83..20c332c 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource emails', () => { test('emailsRetrieve', async () => { diff --git a/tests/api-resources/pages-v1.test.ts b/tests/api-resources/pages-v1.test.ts index 129c470..776b0bf 100644 --- a/tests/api-resources/pages-v1.test.ts +++ b/tests/api-resources/pages-v1.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource pagesV1', () => { test('renderCreate: only required params', async () => { diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts index 9efaa8a..1204716 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/pages.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource pages', () => { test('renderCreate: only required params', async () => { diff --git a/tests/api-resources/project-v1.test.ts b/tests/api-resources/project-v1.test.ts index bfc2831..8ec008d 100644 --- a/tests/api-resources/project-v1.test.ts +++ b/tests/api-resources/project-v1.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource projectV1', () => { test('apiKeysCreate: only required params', async () => { diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts index 4e2bcf0..c6b96c3 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/project.test.ts @@ -2,7 +2,10 @@ import Unlayer from '@unlayer/sdk'; -const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource project', () => { test('apiKeysCreate: only required params', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 89ec21b..df8dca4 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -23,6 +23,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-My-Default-Header': '2' }, + apiKey: 'My API Key', }); test('they are used in the request', async () => { @@ -86,14 +87,14 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'debug' }); + const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); await forceAPIResponseForClient(client); expect(debugMock).toHaveBeenCalled(); }); test('default logLevel is warn', async () => { - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.logLevel).toBe('warn'); }); @@ -106,7 +107,7 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'info' }); + const client = new Unlayer({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -122,7 +123,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger }); + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); expect(client.logLevel).toBe('debug'); await forceAPIResponseForClient(client); @@ -139,7 +140,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger }); + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); expect(client.logLevel).toBe('warn'); expect(warnMock).toHaveBeenCalledWith( 'process.env[\'UNLAYER_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', @@ -156,7 +157,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, logLevel: 'off' }); + const client = new Unlayer({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -172,7 +173,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, logLevel: 'debug' }); + const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); }); @@ -180,7 +181,11 @@ describe('instantiate client', () => { describe('defaultQuery', () => { test('with null query params given', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' } }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo' }, + apiKey: 'My API Key', + }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); @@ -188,12 +193,17 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo', hello: 'world' }, + apiKey: 'My API Key', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); test('overriding with `undefined`', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' } }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + defaultQuery: { hello: 'world' }, + apiKey: 'My API Key', + }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); }); @@ -201,6 +211,7 @@ describe('instantiate client', () => { test('custom fetch', async () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', fetch: (url) => { return Promise.resolve( new Response(JSON.stringify({ url, custom: true }), { @@ -216,12 +227,17 @@ describe('instantiate client', () => { test('explicit global fetch', async () => { // make sure the global fetch type is assignable to our Fetch type - const client = new Unlayer({ baseURL: 'http://localhost:5000/', fetch: defaultFetch }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, + }); }); test('custom signal', async () => { const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', fetch: (...args) => { return new Promise((resolve, reject) => setTimeout( @@ -251,7 +267,7 @@ describe('instantiate client', () => { return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ baseURL: 'http://localhost:5000/', fetch: testFetch }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -259,12 +275,12 @@ describe('instantiate client', () => { describe('baseUrl', () => { test('trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); test('no trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path' }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); @@ -273,37 +289,37 @@ describe('instantiate client', () => { }); test('explicit option', () => { - const client = new Unlayer({ baseURL: 'https://example.com' }); + const client = new Unlayer({ baseURL: 'https://example.com', apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://example.com'); }); test('env variable', () => { process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://example.com/from_env'); }); test('empty env variable', () => { process.env['UNLAYER_BASE_URL'] = ''; // empty - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('blank env variable', () => { process.env['UNLAYER_BASE_URL'] = ' '; // blank - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('in request options', () => { - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/option/foo', ); }); test('in request options overridden by client options', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/client' }); + const client = new Unlayer({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/client/foo', ); @@ -311,7 +327,7 @@ describe('instantiate client', () => { test('in request options overridden by env variable', () => { process.env['UNLAYER_BASE_URL'] = 'http://localhost:5000/env'; - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/env/foo', ); @@ -319,17 +335,17 @@ describe('instantiate client', () => { }); test('maxRetries option is correctly set', () => { - const client = new Unlayer({ maxRetries: 4 }); + const client = new Unlayer({ maxRetries: 4, apiKey: 'My API Key' }); expect(client.maxRetries).toEqual(4); // default - const client2 = new Unlayer({}); + const client2 = new Unlayer({ apiKey: 'My API Key' }); expect(client2.maxRetries).toEqual(2); }); describe('withOptions', () => { test('creates a new client with overridden options', async () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3 }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); const newClient = client.withOptions({ maxRetries: 5, @@ -354,6 +370,7 @@ describe('instantiate client', () => { baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-Test-Header': 'test-value' }, defaultQuery: { 'test-param': 'test-value' }, + apiKey: 'My API Key', }); const newClient = client.withOptions({ @@ -368,7 +385,7 @@ describe('instantiate client', () => { }); test('respects runtime property changes when creating new client', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000 }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -393,10 +410,24 @@ describe('instantiate client', () => { expect(newClient.buildURL('/bar', null)).toEqual('http://localhost:6000/bar'); }); }); + + test('with environment variable arguments', () => { + // set options via env var + process.env['UNLAYER_API_KEY'] = 'My API Key'; + const client = new Unlayer(); + expect(client.apiKey).toBe('My API Key'); + }); + + test('with overridden environment variable arguments', () => { + // set options via env var + process.env['UNLAYER_API_KEY'] = 'another My API Key'; + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.apiKey).toBe('My API Key'); + }); }); describe('request building', () => { - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); describe('custom headers', () => { test('handles undefined', async () => { @@ -415,7 +446,7 @@ describe('request building', () => { }); describe('default encoder', () => { - const client = new Unlayer({}); + const client = new Unlayer({ apiKey: 'My API Key' }); class Serializable { toJSON() { @@ -500,7 +531,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ timeout: 10, fetch: testFetch }); + const client = new Unlayer({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -530,7 +561,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -554,7 +585,7 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); expect( await client.request({ @@ -584,6 +615,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ + apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, defaultHeaders: { 'X-Stainless-Retry-Count': null }, @@ -615,7 +647,7 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); expect( await client.request({ @@ -645,7 +677,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ fetch: testFetch }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -675,7 +707,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ fetch: testFetch }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); From 563ad23ed7642786d1155b65aca983e2553dcd25 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 08:02:30 +0000 Subject: [PATCH 016/118] feat(api): api update --- .stats.yml | 6 +- api.md | 96 ++++++++++++------------ src/client.ts | 76 +++++++++---------- src/resources/documents-v1.ts | 2 +- src/resources/documents.ts | 2 +- src/resources/emails-v1.ts | 4 +- src/resources/emails.ts | 4 +- src/resources/pages-v1.ts | 2 +- src/resources/pages.ts | 2 +- tests/api-resources/documents-v1.test.ts | 2 +- tests/api-resources/documents.test.ts | 2 +- tests/api-resources/emails-v1.test.ts | 9 ++- tests/api-resources/emails.test.ts | 9 ++- tests/api-resources/pages-v1.test.ts | 7 +- tests/api-resources/pages.test.ts | 7 +- 15 files changed, 121 insertions(+), 109 deletions(-) diff --git a/.stats.yml b/.stats.yml index a781546..6e1c907 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-fc81363e6d0ba052e31137423ff1b8a013e586045837c40cc625b7a9feff8cf5.yml -openapi_spec_hash: 6cd80e99a1c0accc93055b2e0fe3773d -config_hash: f84271374781c3e600f1a9d0757e53a0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-364ec0aeb9733e9dbc414c5f10caa56e33bd72332e63930d43b92141bf1aec84.yml +openapi_spec_hash: 6e9b8d1784233f0968870759ecf3fb52 +config_hash: 8884bc600a5a226418f2d362a6eb98bb diff --git a/api.md b/api.md index d89dd07..21020df 100644 --- a/api.md +++ b/api.md @@ -1,51 +1,3 @@ -# DocumentsV1 - -Types: - -- DocumentsV1DocumentsRetrieveResponse -- DocumentsV1GenerateCreateResponse -- DocumentsV1GenerateTemplateTemplateResponse - -Methods: - -- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse -- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse -- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - -# PagesV1 - -Types: - -- PagesV1RenderCreateResponse - -Methods: - -- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse - -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - # ProjectV1 Types: @@ -151,3 +103,51 @@ Methods: - client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse - client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse - client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + +# DocumentsV1 + +Types: + +- DocumentsV1DocumentsRetrieveResponse +- DocumentsV1GenerateCreateResponse +- DocumentsV1GenerateTemplateTemplateResponse + +Methods: + +- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse +- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse +- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse + +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + +# PagesV1 + +Types: + +- PagesV1RenderCreateResponse + +Methods: + +- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse + +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/src/client.ts b/src/client.ts index 5a24e4e..fc956b9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,58 +795,28 @@ export class Unlayer { static toFile = Uploads.toFile; - documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); - documents: API.Documents = new API.Documents(this); - pagesV1: API.PagesV1 = new API.PagesV1(this); - pages: API.Pages = new API.Pages(this); projectV1: API.ProjectV1 = new API.ProjectV1(this); project: API.Project = new API.Project(this); emailsV1: API.EmailsV1 = new API.EmailsV1(this); emails: API.Emails = new API.Emails(this); + documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); + documents: API.Documents = new API.Documents(this); + pagesV1: API.PagesV1 = new API.PagesV1(this); + pages: API.Pages = new API.Pages(this); } -Unlayer.DocumentsV1 = DocumentsV1; -Unlayer.Documents = Documents; -Unlayer.PagesV1 = PagesV1; -Unlayer.Pages = Pages; Unlayer.ProjectV1 = ProjectV1; Unlayer.Project = Project; Unlayer.EmailsV1 = EmailsV1; Unlayer.Emails = Emails; +Unlayer.DocumentsV1 = DocumentsV1; +Unlayer.Documents = Documents; +Unlayer.PagesV1 = PagesV1; +Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - DocumentsV1 as DocumentsV1, - type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, - type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, - type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, - type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, - type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, - }; - - export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; - - export { - PagesV1 as PagesV1, - type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, - type PagesV1RenderCreateParams as PagesV1RenderCreateParams, - }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - export { ProjectV1 as ProjectV1, type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, @@ -914,4 +884,34 @@ export declare namespace Unlayer { type EmailSendCreateParams as EmailSendCreateParams, type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; + + export { + DocumentsV1 as DocumentsV1, + type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, + type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, + type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, + type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, + type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, + }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + + export { + PagesV1 as PagesV1, + type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, + type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; } diff --git a/src/resources/documents-v1.ts b/src/resources/documents-v1.ts index e544426..dc184d6 100644 --- a/src/resources/documents-v1.ts +++ b/src/resources/documents-v1.ts @@ -118,7 +118,7 @@ export interface DocumentsV1GenerateCreateParams { /** * Proprietary design format JSON */ - design?: unknown; + design?: { [key: string]: unknown }; /** * Optional filename for the generated PDF diff --git a/src/resources/documents.ts b/src/resources/documents.ts index edca7d6..468a1c7 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -118,7 +118,7 @@ export interface DocumentGenerateCreateParams { /** * Proprietary design format JSON */ - design?: unknown; + design?: { [key: string]: unknown }; /** * Optional filename for the generated PDF diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts index f2f92a6..70fe594 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails-v1.ts @@ -105,7 +105,7 @@ export interface EmailsV1RenderCreateParams { /** * Proprietary design format JSON */ - design: unknown; + design: { [key: string]: unknown }; /** * Optional merge tags for personalization @@ -122,7 +122,7 @@ export interface EmailsV1SendCreateParams { /** * Proprietary design format JSON */ - design?: unknown; + design?: { [key: string]: unknown }; /** * HTML content to send diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 447bce6..ab67686 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -102,7 +102,7 @@ export interface EmailRenderCreateParams { /** * Proprietary design format JSON */ - design: unknown; + design: { [key: string]: unknown }; /** * Optional merge tags for personalization @@ -119,7 +119,7 @@ export interface EmailSendCreateParams { /** * Proprietary design format JSON */ - design?: unknown; + design?: { [key: string]: unknown }; /** * HTML content to send diff --git a/src/resources/pages-v1.ts b/src/resources/pages-v1.ts index 7efc857..298e484 100644 --- a/src/resources/pages-v1.ts +++ b/src/resources/pages-v1.ts @@ -27,7 +27,7 @@ export interface PagesV1RenderCreateParams { /** * Proprietary design format JSON */ - design: unknown; + design: { [key: string]: unknown }; /** * Optional merge tags for personalization diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 611ddcf..9216b49 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -24,7 +24,7 @@ export interface PageRenderCreateParams { /** * Proprietary design format JSON */ - design: unknown; + design: { [key: string]: unknown }; /** * Optional merge tags for personalization diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents-v1.test.ts index c3e5def..2fe76fd 100644 --- a/tests/api-resources/documents-v1.test.ts +++ b/tests/api-resources/documents-v1.test.ts @@ -35,7 +35,7 @@ describe('resource documentsV1', () => { await expect( client.documentsV1.generateCreate( { - design: {}, + design: { foo: 'bar' }, filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 22f3fed..7a28e9e 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -35,7 +35,7 @@ describe('resource documents', () => { await expect( client.documents.generateCreate( { - design: {}, + design: { foo: 'bar' }, filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index d0ecf34..9903e2c 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -20,7 +20,7 @@ describe('resource emailsV1', () => { }); test('renderCreate: only required params', async () => { - const responsePromise = client.emailsV1.renderCreate({ design: {} }); + const responsePromise = client.emailsV1.renderCreate({ design: { foo: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -31,7 +31,10 @@ describe('resource emailsV1', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.emailsV1.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + const response = await client.emailsV1.renderCreate({ + design: { foo: 'bar' }, + mergeTags: { foo: 'string' }, + }); }); test('sendCreate: only required params', async () => { @@ -48,7 +51,7 @@ describe('resource emailsV1', () => { test('sendCreate: required and optional params', async () => { const response = await client.emailsV1.sendCreate({ to: 'dev@stainless.com', - design: {}, + design: { foo: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, subject: 'subject', diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index 20c332c..842df14 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -20,7 +20,7 @@ describe('resource emails', () => { }); test('renderCreate: only required params', async () => { - const responsePromise = client.emails.renderCreate({ design: {} }); + const responsePromise = client.emails.renderCreate({ design: { foo: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -31,7 +31,10 @@ describe('resource emails', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.emails.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + const response = await client.emails.renderCreate({ + design: { foo: 'bar' }, + mergeTags: { foo: 'string' }, + }); }); test('sendCreate: only required params', async () => { @@ -48,7 +51,7 @@ describe('resource emails', () => { test('sendCreate: required and optional params', async () => { const response = await client.emails.sendCreate({ to: 'dev@stainless.com', - design: {}, + design: { foo: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, subject: 'subject', diff --git a/tests/api-resources/pages-v1.test.ts b/tests/api-resources/pages-v1.test.ts index 776b0bf..b8d164f 100644 --- a/tests/api-resources/pages-v1.test.ts +++ b/tests/api-resources/pages-v1.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource pagesV1', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pagesV1.renderCreate({ design: {} }); + const responsePromise = client.pagesV1.renderCreate({ design: { foo: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,6 +20,9 @@ describe('resource pagesV1', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.pagesV1.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + const response = await client.pagesV1.renderCreate({ + design: { foo: 'bar' }, + mergeTags: { foo: 'string' }, + }); }); }); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts index 1204716..e582465 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/pages.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource pages', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pages.renderCreate({ design: {} }); + const responsePromise = client.pages.renderCreate({ design: { foo: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,6 +20,9 @@ describe('resource pages', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.pages.renderCreate({ design: {}, mergeTags: { foo: 'string' } }); + const response = await client.pages.renderCreate({ + design: { foo: 'bar' }, + mergeTags: { foo: 'string' }, + }); }); }); From 16b56ff2169da0803fad8fa5078997527d22ef8b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 08:11:00 +0000 Subject: [PATCH 017/118] feat(api): api update --- .stats.yml | 6 +-- api.md | 64 ++++++++++++------------ src/client.ts | 52 +++++++++---------- src/resources/documents-v1.ts | 20 ++++++++ src/resources/documents.ts | 20 ++++++++ src/resources/emails-v1.ts | 26 ++++++++++ src/resources/emails.ts | 27 ++++++++++ src/resources/pages-v1.ts | 7 +++ src/resources/pages.ts | 7 +++ tests/api-resources/documents-v1.test.ts | 2 +- tests/api-resources/documents.test.ts | 2 +- tests/api-resources/emails-v1.test.ts | 6 +-- tests/api-resources/emails.test.ts | 6 +-- tests/api-resources/pages-v1.test.ts | 4 +- tests/api-resources/pages.test.ts | 4 +- 15 files changed, 180 insertions(+), 73 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6e1c907..838d8a3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-364ec0aeb9733e9dbc414c5f10caa56e33bd72332e63930d43b92141bf1aec84.yml -openapi_spec_hash: 6e9b8d1784233f0968870759ecf3fb52 -config_hash: 8884bc600a5a226418f2d362a6eb98bb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-66fac6e9cc311c01b211096fdfad381fd68cead59cc8cbfda34594f2d4fe73f3.yml +openapi_spec_hash: 16fe1ba9c8f4d9a4d6adfe4c3685afe3 +config_hash: a4f34863030203b80da5a78b0d4ea416 diff --git a/api.md b/api.md index 21020df..49167ca 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,35 @@ +# EmailsV1 + +Types: + +- EmailsV1EmailsRetrieveResponse +- EmailsV1RenderCreateResponse +- EmailsV1SendCreateResponse +- EmailsV1SendTemplateTemplateResponse + +Methods: + +- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse +- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse +- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse +- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse + +# Emails + +Types: + +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # ProjectV1 Types: @@ -72,38 +104,6 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# EmailsV1 - -Types: - -- EmailsV1EmailsRetrieveResponse -- EmailsV1RenderCreateResponse -- EmailsV1SendCreateResponse -- EmailsV1SendTemplateTemplateResponse - -Methods: - -- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse -- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse -- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse -- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse - -# Emails - -Types: - -- EmailEmailsRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - # DocumentsV1 Types: diff --git a/src/client.ts b/src/client.ts index fc956b9..fb711d9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,20 +795,20 @@ export class Unlayer { static toFile = Uploads.toFile; - projectV1: API.ProjectV1 = new API.ProjectV1(this); - project: API.Project = new API.Project(this); emailsV1: API.EmailsV1 = new API.EmailsV1(this); emails: API.Emails = new API.Emails(this); + projectV1: API.ProjectV1 = new API.ProjectV1(this); + project: API.Project = new API.Project(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); } -Unlayer.ProjectV1 = ProjectV1; -Unlayer.Project = Project; Unlayer.EmailsV1 = EmailsV1; Unlayer.Emails = Emails; +Unlayer.ProjectV1 = ProjectV1; +Unlayer.Project = Project; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; @@ -817,6 +817,28 @@ Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + EmailsV1 as EmailsV1, + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + }; + + export { + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { ProjectV1 as ProjectV1, type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, @@ -863,28 +885,6 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - export { - EmailsV1 as EmailsV1, - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, - }; - - export { - Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { DocumentsV1 as DocumentsV1, type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, diff --git a/src/resources/documents-v1.ts b/src/resources/documents-v1.ts index dc184d6..ca4fcc2 100644 --- a/src/resources/documents-v1.ts +++ b/src/resources/documents-v1.ts @@ -8,6 +8,13 @@ import { path } from '../internal/utils/path'; export class DocumentsV1 extends APIResource { /** * Retrieve details of a previously generated document. + * + * @example + * ```ts + * const response = await client.documentsV1.documentsRetrieve( + * 'id', + * ); + * ``` */ documentsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/documents/v1/documents/${id}`, options); @@ -15,6 +22,11 @@ export class DocumentsV1 extends APIResource { /** * Generate PDF document from JSON design, HTML content, or URL. + * + * @example + * ```ts + * const response = await client.documentsV1.generateCreate(); + * ``` */ generateCreate( body: DocumentsV1GenerateCreateParams | null | undefined = {}, @@ -25,6 +37,14 @@ export class DocumentsV1 extends APIResource { /** * Generate PDF document from an existing template with merge tags. + * + * @example + * ```ts + * const response = + * await client.documentsV1.generateTemplateTemplate({ + * templateId: 'templateId', + * }); + * ``` */ generateTemplateTemplate( body: DocumentsV1GenerateTemplateTemplateParams, diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 468a1c7..6b6d6d3 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -8,6 +8,13 @@ import { path } from '../internal/utils/path'; export class Documents extends APIResource { /** * Retrieve details of a previously generated document. + * + * @example + * ```ts + * const response = await client.documents.documentsRetrieve( + * 'id', + * ); + * ``` */ documentsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/documents/v1/documents/${id}`, options); @@ -15,6 +22,11 @@ export class Documents extends APIResource { /** * Generate PDF document from JSON design, HTML content, or URL. + * + * @example + * ```ts + * const response = await client.documents.generateCreate(); + * ``` */ generateCreate( body: DocumentGenerateCreateParams | null | undefined = {}, @@ -25,6 +37,14 @@ export class Documents extends APIResource { /** * Generate PDF document from an existing template with merge tags. + * + * @example + * ```ts + * const response = + * await client.documents.generateTemplateTemplate({ + * templateId: 'templateId', + * }); + * ``` */ generateTemplateTemplate( body: DocumentGenerateTemplateTemplateParams, diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts index 70fe594..aed065c 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails-v1.ts @@ -8,6 +8,11 @@ import { path } from '../internal/utils/path'; export class EmailsV1 extends APIResource { /** * Retrieve details of a previously sent email. + * + * @example + * ```ts + * const response = await client.emailsV1.emailsRetrieve('id'); + * ``` */ emailsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, options); @@ -15,6 +20,13 @@ export class EmailsV1 extends APIResource { /** * Convert design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.emailsV1.renderCreate({ + * design: { counters: 'bar', body: 'bar' }, + * }); + * ``` */ renderCreate( body: EmailsV1RenderCreateParams, @@ -25,6 +37,13 @@ export class EmailsV1 extends APIResource { /** * Send email with design JSON or HTML content. + * + * @example + * ```ts + * const response = await client.emailsV1.sendCreate({ + * to: 'dev@stainless.com', + * }); + * ``` */ sendCreate( body: EmailsV1SendCreateParams, @@ -35,6 +54,13 @@ export class EmailsV1 extends APIResource { /** * Send email using an existing template with merge tags. + * + * @example + * ```ts + * const response = await client.emailsV1.sendTemplateTemplate( + * { templateId: 'templateId', to: 'dev@stainless.com' }, + * ); + * ``` */ sendTemplateTemplate( body: EmailsV1SendTemplateTemplateParams, diff --git a/src/resources/emails.ts b/src/resources/emails.ts index ab67686..a687c6a 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -8,6 +8,11 @@ import { path } from '../internal/utils/path'; export class Emails extends APIResource { /** * Retrieve details of a previously sent email. + * + * @example + * ```ts + * const response = await client.emails.emailsRetrieve('id'); + * ``` */ emailsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, options); @@ -15,6 +20,13 @@ export class Emails extends APIResource { /** * Convert design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.emails.renderCreate({ + * design: { counters: 'bar', body: 'bar' }, + * }); + * ``` */ renderCreate( body: EmailRenderCreateParams, @@ -25,6 +37,13 @@ export class Emails extends APIResource { /** * Send email with design JSON or HTML content. + * + * @example + * ```ts + * const response = await client.emails.sendCreate({ + * to: 'dev@stainless.com', + * }); + * ``` */ sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/emails/v1/send', { body, ...options }); @@ -32,6 +51,14 @@ export class Emails extends APIResource { /** * Send email using an existing template with merge tags. + * + * @example + * ```ts + * const response = await client.emails.sendTemplateTemplate({ + * templateId: 'templateId', + * to: 'dev@stainless.com', + * }); + * ``` */ sendTemplateTemplate( body: EmailSendTemplateTemplateParams, diff --git a/src/resources/pages-v1.ts b/src/resources/pages-v1.ts index 298e484..f847a6d 100644 --- a/src/resources/pages-v1.ts +++ b/src/resources/pages-v1.ts @@ -7,6 +7,13 @@ import { RequestOptions } from '../internal/request-options'; export class PagesV1 extends APIResource { /** * Convert page design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.pagesV1.renderCreate({ + * design: { counters: 'bar', body: 'bar' }, + * }); + * ``` */ renderCreate( body: PagesV1RenderCreateParams, diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 9216b49..8ebff59 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -7,6 +7,13 @@ import { RequestOptions } from '../internal/request-options'; export class Pages extends APIResource { /** * Convert page design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.pages.renderCreate({ + * design: { counters: 'bar', body: 'bar' }, + * }); + * ``` */ renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/pages/v1/render', { body, ...options }); diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents-v1.test.ts index 2fe76fd..a77fb32 100644 --- a/tests/api-resources/documents-v1.test.ts +++ b/tests/api-resources/documents-v1.test.ts @@ -35,7 +35,7 @@ describe('resource documentsV1', () => { await expect( client.documentsV1.generateCreate( { - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 7a28e9e..2231eef 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -35,7 +35,7 @@ describe('resource documents', () => { await expect( client.documents.generateCreate( { - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index 9903e2c..050b58f 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -20,7 +20,7 @@ describe('resource emailsV1', () => { }); test('renderCreate: only required params', async () => { - const responsePromise = client.emailsV1.renderCreate({ design: { foo: 'bar' } }); + const responsePromise = client.emailsV1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -32,7 +32,7 @@ describe('resource emailsV1', () => { test('renderCreate: required and optional params', async () => { const response = await client.emailsV1.renderCreate({ - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); }); @@ -51,7 +51,7 @@ describe('resource emailsV1', () => { test('sendCreate: required and optional params', async () => { const response = await client.emailsV1.sendCreate({ to: 'dev@stainless.com', - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, subject: 'subject', diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index 842df14..ff14606 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -20,7 +20,7 @@ describe('resource emails', () => { }); test('renderCreate: only required params', async () => { - const responsePromise = client.emails.renderCreate({ design: { foo: 'bar' } }); + const responsePromise = client.emails.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -32,7 +32,7 @@ describe('resource emails', () => { test('renderCreate: required and optional params', async () => { const response = await client.emails.renderCreate({ - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); }); @@ -51,7 +51,7 @@ describe('resource emails', () => { test('sendCreate: required and optional params', async () => { const response = await client.emails.sendCreate({ to: 'dev@stainless.com', - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, subject: 'subject', diff --git a/tests/api-resources/pages-v1.test.ts b/tests/api-resources/pages-v1.test.ts index b8d164f..db9031c 100644 --- a/tests/api-resources/pages-v1.test.ts +++ b/tests/api-resources/pages-v1.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource pagesV1', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pagesV1.renderCreate({ design: { foo: 'bar' } }); + const responsePromise = client.pagesV1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,7 +21,7 @@ describe('resource pagesV1', () => { test('renderCreate: required and optional params', async () => { const response = await client.pagesV1.renderCreate({ - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); }); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts index e582465..3a817b2 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/pages.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource pages', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pages.renderCreate({ design: { foo: 'bar' } }); + const responsePromise = client.pages.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,7 +21,7 @@ describe('resource pages', () => { test('renderCreate: required and optional params', async () => { const response = await client.pages.renderCreate({ - design: { foo: 'bar' }, + design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); }); From 40bf584ad226c25dbdd4f1fe3ed63e13d774e8ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 08:18:54 +0000 Subject: [PATCH 018/118] feat(api): api update --- .stats.yml | 6 +-- api.md | 64 +++++++++++++-------------- src/client.ts | 52 +++++++++++----------- src/resources/documents-v1.ts | 23 +++++++++- src/resources/documents.ts | 23 +++++++++- src/resources/emails-v1.ts | 44 +++++++++++++++++- src/resources/emails.ts | 44 +++++++++++++++++- src/resources/pages-v1.ts | 21 ++++++++- src/resources/pages.ts | 21 ++++++++- tests/api-resources/emails-v1.test.ts | 6 +-- tests/api-resources/emails.test.ts | 6 +-- 11 files changed, 235 insertions(+), 75 deletions(-) diff --git a/.stats.yml b/.stats.yml index 838d8a3..743d129 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-66fac6e9cc311c01b211096fdfad381fd68cead59cc8cbfda34594f2d4fe73f3.yml -openapi_spec_hash: 16fe1ba9c8f4d9a4d6adfe4c3685afe3 -config_hash: a4f34863030203b80da5a78b0d4ea416 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4be7b3f2c706cddbbc687166d7c1a309702cef50babef8ecc8bcfc65d3747d46.yml +openapi_spec_hash: 69afe56b204ccd36031c6cbe76856403 +config_hash: 8884bc600a5a226418f2d362a6eb98bb diff --git a/api.md b/api.md index 49167ca..21020df 100644 --- a/api.md +++ b/api.md @@ -1,35 +1,3 @@ -# EmailsV1 - -Types: - -- EmailsV1EmailsRetrieveResponse -- EmailsV1RenderCreateResponse -- EmailsV1SendCreateResponse -- EmailsV1SendTemplateTemplateResponse - -Methods: - -- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse -- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse -- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse -- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse - -# Emails - -Types: - -- EmailEmailsRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - # ProjectV1 Types: @@ -104,6 +72,38 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse +# EmailsV1 + +Types: + +- EmailsV1EmailsRetrieveResponse +- EmailsV1RenderCreateResponse +- EmailsV1SendCreateResponse +- EmailsV1SendTemplateTemplateResponse + +Methods: + +- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse +- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse +- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse +- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse + +# Emails + +Types: + +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # DocumentsV1 Types: diff --git a/src/client.ts b/src/client.ts index fb711d9..fc956b9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,20 +795,20 @@ export class Unlayer { static toFile = Uploads.toFile; - emailsV1: API.EmailsV1 = new API.EmailsV1(this); - emails: API.Emails = new API.Emails(this); projectV1: API.ProjectV1 = new API.ProjectV1(this); project: API.Project = new API.Project(this); + emailsV1: API.EmailsV1 = new API.EmailsV1(this); + emails: API.Emails = new API.Emails(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); } -Unlayer.EmailsV1 = EmailsV1; -Unlayer.Emails = Emails; Unlayer.ProjectV1 = ProjectV1; Unlayer.Project = Project; +Unlayer.EmailsV1 = EmailsV1; +Unlayer.Emails = Emails; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; @@ -817,28 +817,6 @@ Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - EmailsV1 as EmailsV1, - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, - }; - - export { - Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { ProjectV1 as ProjectV1, type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, @@ -885,6 +863,28 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; + export { + EmailsV1 as EmailsV1, + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + }; + + export { + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { DocumentsV1 as DocumentsV1, type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, diff --git a/src/resources/documents-v1.ts b/src/resources/documents-v1.ts index ca4fcc2..55c23ab 100644 --- a/src/resources/documents-v1.ts +++ b/src/resources/documents-v1.ts @@ -25,7 +25,28 @@ export class DocumentsV1 extends APIResource { * * @example * ```ts - * const response = await client.documentsV1.generateCreate(); + * const response = await client.documentsV1.generateCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); * ``` */ generateCreate( diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 6b6d6d3..ecfe98d 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -25,7 +25,28 @@ export class Documents extends APIResource { * * @example * ```ts - * const response = await client.documents.generateCreate(); + * const response = await client.documents.generateCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); * ``` */ generateCreate( diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts index aed065c..d827d04 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails-v1.ts @@ -24,7 +24,26 @@ export class EmailsV1 extends APIResource { * @example * ```ts * const response = await client.emailsV1.renderCreate({ - * design: { counters: 'bar', body: 'bar' }, + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, * }); * ``` */ @@ -41,7 +60,28 @@ export class EmailsV1 extends APIResource { * @example * ```ts * const response = await client.emailsV1.sendCreate({ - * to: 'dev@stainless.com', + * to: 'test@example.com', + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * subject: 'Test Email', * }); * ``` */ diff --git a/src/resources/emails.ts b/src/resources/emails.ts index a687c6a..51f0641 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -24,7 +24,26 @@ export class Emails extends APIResource { * @example * ```ts * const response = await client.emails.renderCreate({ - * design: { counters: 'bar', body: 'bar' }, + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, * }); * ``` */ @@ -41,7 +60,28 @@ export class Emails extends APIResource { * @example * ```ts * const response = await client.emails.sendCreate({ - * to: 'dev@stainless.com', + * to: 'test@example.com', + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * subject: 'Test Email', * }); * ``` */ diff --git a/src/resources/pages-v1.ts b/src/resources/pages-v1.ts index f847a6d..44775af 100644 --- a/src/resources/pages-v1.ts +++ b/src/resources/pages-v1.ts @@ -11,7 +11,26 @@ export class PagesV1 extends APIResource { * @example * ```ts * const response = await client.pagesV1.renderCreate({ - * design: { counters: 'bar', body: 'bar' }, + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, * }); * ``` */ diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 8ebff59..05af321 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -11,7 +11,26 @@ export class Pages extends APIResource { * @example * ```ts * const response = await client.pages.renderCreate({ - * design: { counters: 'bar', body: 'bar' }, + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, * }); * ``` */ diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index 050b58f..e5d218d 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -38,7 +38,7 @@ describe('resource emailsV1', () => { }); test('sendCreate: only required params', async () => { - const responsePromise = client.emailsV1.sendCreate({ to: 'dev@stainless.com' }); + const responsePromise = client.emailsV1.sendCreate({ to: 'test@example.com' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -50,11 +50,11 @@ describe('resource emailsV1', () => { test('sendCreate: required and optional params', async () => { const response = await client.emailsV1.sendCreate({ - to: 'dev@stainless.com', + to: 'test@example.com', design: { counters: 'bar', body: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, - subject: 'subject', + subject: 'Test Email', }); }); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index ff14606..d60f29c 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -38,7 +38,7 @@ describe('resource emails', () => { }); test('sendCreate: only required params', async () => { - const responsePromise = client.emails.sendCreate({ to: 'dev@stainless.com' }); + const responsePromise = client.emails.sendCreate({ to: 'test@example.com' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -50,11 +50,11 @@ describe('resource emails', () => { test('sendCreate: required and optional params', async () => { const response = await client.emails.sendCreate({ - to: 'dev@stainless.com', + to: 'test@example.com', design: { counters: 'bar', body: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, - subject: 'subject', + subject: 'Test Email', }); }); From 301bc9bf328671a9a1069e0be1fdf3dcf8a01be2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 08:25:30 +0000 Subject: [PATCH 019/118] feat(api): api update --- .stats.yml | 6 +- api.md | 148 +++++++++++------------ src/client.ts | 100 +++++++-------- src/resources/documents-v1.ts | 4 +- src/resources/documents.ts | 4 +- src/resources/emails-v1.ts | 10 +- src/resources/emails.ts | 10 +- tests/api-resources/documents-v1.test.ts | 26 ++-- tests/api-resources/documents.test.ts | 26 ++-- tests/api-resources/emails-v1.test.ts | 7 +- tests/api-resources/emails.test.ts | 7 +- 11 files changed, 171 insertions(+), 177 deletions(-) diff --git a/.stats.yml b/.stats.yml index 743d129..76b92d7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4be7b3f2c706cddbbc687166d7c1a309702cef50babef8ecc8bcfc65d3747d46.yml -openapi_spec_hash: 69afe56b204ccd36031c6cbe76856403 -config_hash: 8884bc600a5a226418f2d362a6eb98bb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-168db8cc4eb5bba88beea6baf4121fa28092e423fc8457088a1feb755a7b2f79.yml +openapi_spec_hash: 137bedbc636b64c2971b6cd06f8debe2 +config_hash: 4679527c1267fd5656a4122b4f89960c diff --git a/api.md b/api.md index 21020df..3301910 100644 --- a/api.md +++ b/api.md @@ -1,77 +1,3 @@ -# ProjectV1 - -Types: - -- ProjectV1APIKeysCreateResponse -- ProjectV1APIKeysListResponse -- ProjectV1APIKeysRetrieveResponse -- ProjectV1APIKeysUpdateResponse -- ProjectV1CurrentListResponse -- ProjectV1DomainsCreateResponse -- ProjectV1DomainsListResponse -- ProjectV1DomainsRetrieveResponse -- ProjectV1DomainsUpdateResponse -- ProjectV1TemplatesCreateResponse -- ProjectV1TemplatesListResponse -- ProjectV1TemplatesRetrieveResponse -- ProjectV1TemplatesUpdateResponse - -Methods: - -- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse -- client.projectV1.apiKeysDelete(id) -> void -- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse -- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse -- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse -- client.projectV1.currentList() -> ProjectV1CurrentListResponse -- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse -- client.projectV1.domainsDelete(id) -> void -- client.projectV1.domainsList() -> ProjectV1DomainsListResponse -- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse -- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse -- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse -- client.projectV1.templatesDelete(id) -> void -- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse -- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse -- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse - -# Project - -Types: - -- ProjectAPIKeysCreateResponse -- ProjectAPIKeysListResponse -- ProjectAPIKeysRetrieveResponse -- ProjectAPIKeysUpdateResponse -- ProjectCurrentListResponse -- ProjectDomainsCreateResponse -- ProjectDomainsListResponse -- ProjectDomainsRetrieveResponse -- ProjectDomainsUpdateResponse -- ProjectTemplatesCreateResponse -- ProjectTemplatesListResponse -- ProjectTemplatesRetrieveResponse -- ProjectTemplatesUpdateResponse - -Methods: - -- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse -- client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList() -> ProjectAPIKeysListResponse -- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse -- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse -- client.project.currentList() -> ProjectCurrentListResponse -- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse -- client.project.domainsDelete(id) -> void -- client.project.domainsList() -> ProjectDomainsListResponse -- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse -- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse -- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse -- client.project.templatesDelete(id) -> void -- client.project.templatesList() -> ProjectTemplatesListResponse -- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse -- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse - # EmailsV1 Types: @@ -151,3 +77,77 @@ Types: Methods: - client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse + +# ProjectV1 + +Types: + +- ProjectV1APIKeysCreateResponse +- ProjectV1APIKeysListResponse +- ProjectV1APIKeysRetrieveResponse +- ProjectV1APIKeysUpdateResponse +- ProjectV1CurrentListResponse +- ProjectV1DomainsCreateResponse +- ProjectV1DomainsListResponse +- ProjectV1DomainsRetrieveResponse +- ProjectV1DomainsUpdateResponse +- ProjectV1TemplatesCreateResponse +- ProjectV1TemplatesListResponse +- ProjectV1TemplatesRetrieveResponse +- ProjectV1TemplatesUpdateResponse + +Methods: + +- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse +- client.projectV1.apiKeysDelete(id) -> void +- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse +- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse +- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse +- client.projectV1.currentList() -> ProjectV1CurrentListResponse +- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse +- client.projectV1.domainsDelete(id) -> void +- client.projectV1.domainsList() -> ProjectV1DomainsListResponse +- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse +- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse +- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse +- client.projectV1.templatesDelete(id) -> void +- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse +- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse +- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse + +# Project + +Types: + +- ProjectAPIKeysCreateResponse +- ProjectAPIKeysListResponse +- ProjectAPIKeysRetrieveResponse +- ProjectAPIKeysUpdateResponse +- ProjectCurrentListResponse +- ProjectDomainsCreateResponse +- ProjectDomainsListResponse +- ProjectDomainsRetrieveResponse +- ProjectDomainsUpdateResponse +- ProjectTemplatesCreateResponse +- ProjectTemplatesListResponse +- ProjectTemplatesRetrieveResponse +- ProjectTemplatesUpdateResponse + +Methods: + +- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse +- client.project.apiKeysDelete(id) -> void +- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse +- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse +- client.project.currentList() -> ProjectCurrentListResponse +- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse +- client.project.domainsDelete(id) -> void +- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse +- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse +- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse +- client.project.templatesDelete(id) -> void +- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse +- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse diff --git a/src/client.ts b/src/client.ts index fc956b9..6b9ae4c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,74 +795,28 @@ export class Unlayer { static toFile = Uploads.toFile; - projectV1: API.ProjectV1 = new API.ProjectV1(this); - project: API.Project = new API.Project(this); emailsV1: API.EmailsV1 = new API.EmailsV1(this); emails: API.Emails = new API.Emails(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); + projectV1: API.ProjectV1 = new API.ProjectV1(this); + project: API.Project = new API.Project(this); } -Unlayer.ProjectV1 = ProjectV1; -Unlayer.Project = Project; Unlayer.EmailsV1 = EmailsV1; Unlayer.Emails = Emails; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; Unlayer.Pages = Pages; +Unlayer.ProjectV1 = ProjectV1; +Unlayer.Project = Project; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - ProjectV1 as ProjectV1, - type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, - type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, - type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, - type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, - type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, - type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, - type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, - type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, - type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, - type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, - type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, - type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, - type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, - type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, - type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, - type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, - type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, - type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, - type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, - }; - - export { - Project as Project, - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; - export { EmailsV1 as EmailsV1, type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, @@ -914,4 +868,50 @@ export declare namespace Unlayer { type PageRenderCreateResponse as PageRenderCreateResponse, type PageRenderCreateParams as PageRenderCreateParams, }; + + export { + ProjectV1 as ProjectV1, + type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, + type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, + type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, + type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, + type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, + type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, + type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, + type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, + type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, + type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, + type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, + type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, + type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, + type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, + type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, + type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, + type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, + type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, + type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, + }; + + export { + Project as Project, + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; } diff --git a/src/resources/documents-v1.ts b/src/resources/documents-v1.ts index 55c23ab..4a3ffc5 100644 --- a/src/resources/documents-v1.ts +++ b/src/resources/documents-v1.ts @@ -50,7 +50,7 @@ export class DocumentsV1 extends APIResource { * ``` */ generateCreate( - body: DocumentsV1GenerateCreateParams | null | undefined = {}, + body: DocumentsV1GenerateCreateParams, options?: RequestOptions, ): APIPromise { return this._client.post('/documents/v1/generate', { body, ...options }); @@ -159,7 +159,7 @@ export interface DocumentsV1GenerateCreateParams { /** * Proprietary design format JSON */ - design?: { [key: string]: unknown }; + design: { [key: string]: unknown }; /** * Optional filename for the generated PDF diff --git a/src/resources/documents.ts b/src/resources/documents.ts index ecfe98d..bb6b135 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -50,7 +50,7 @@ export class Documents extends APIResource { * ``` */ generateCreate( - body: DocumentGenerateCreateParams | null | undefined = {}, + body: DocumentGenerateCreateParams, options?: RequestOptions, ): APIPromise { return this._client.post('/documents/v1/generate', { body, ...options }); @@ -159,7 +159,7 @@ export interface DocumentGenerateCreateParams { /** * Proprietary design format JSON */ - design?: { [key: string]: unknown }; + design: { [key: string]: unknown }; /** * Optional filename for the generated PDF diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts index d827d04..e73be22 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails-v1.ts @@ -60,7 +60,6 @@ export class EmailsV1 extends APIResource { * @example * ```ts * const response = await client.emailsV1.sendCreate({ - * to: 'test@example.com', * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -81,6 +80,7 @@ export class EmailsV1 extends APIResource { * ], * }, * }, + * to: 'test@example.com', * subject: 'Test Email', * }); * ``` @@ -181,14 +181,14 @@ export interface EmailsV1RenderCreateParams { export interface EmailsV1SendCreateParams { /** - * Recipient email address + * Proprietary design format JSON */ - to: string; + design: { [key: string]: unknown }; /** - * Proprietary design format JSON + * Recipient email address */ - design?: { [key: string]: unknown }; + to: string; /** * HTML content to send diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 51f0641..5bf461c 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -60,7 +60,6 @@ export class Emails extends APIResource { * @example * ```ts * const response = await client.emails.sendCreate({ - * to: 'test@example.com', * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -81,6 +80,7 @@ export class Emails extends APIResource { * ], * }, * }, + * to: 'test@example.com', * subject: 'Test Email', * }); * ``` @@ -179,14 +179,14 @@ export interface EmailRenderCreateParams { export interface EmailSendCreateParams { /** - * Recipient email address + * Proprietary design format JSON */ - to: string; + design: { [key: string]: unknown }; /** - * Proprietary design format JSON + * Recipient email address */ - design?: { [key: string]: unknown }; + to: string; /** * HTML content to send diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents-v1.test.ts index a77fb32..dcd865c 100644 --- a/tests/api-resources/documents-v1.test.ts +++ b/tests/api-resources/documents-v1.test.ts @@ -19,8 +19,8 @@ describe('resource documentsV1', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('generateCreate', async () => { - const responsePromise = client.documentsV1.generateCreate(); + test('generateCreate: only required params', async () => { + const responsePromise = client.documentsV1.generateCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -30,20 +30,14 @@ describe('resource documentsV1', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('generateCreate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.documentsV1.generateCreate( - { - design: { counters: 'bar', body: 'bar' }, - filename: 'filename', - html: 'html', - mergeTags: { foo: 'string' }, - url: 'https://example.com', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); + test('generateCreate: required and optional params', async () => { + const response = await client.documentsV1.generateCreate({ + design: { counters: 'bar', body: 'bar' }, + filename: 'filename', + html: 'html', + mergeTags: { foo: 'string' }, + url: 'https://example.com', + }); }); test('generateTemplateTemplate: only required params', async () => { diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 2231eef..01a1bdd 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -19,8 +19,8 @@ describe('resource documents', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('generateCreate', async () => { - const responsePromise = client.documents.generateCreate(); + test('generateCreate: only required params', async () => { + const responsePromise = client.documents.generateCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -30,20 +30,14 @@ describe('resource documents', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('generateCreate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.documents.generateCreate( - { - design: { counters: 'bar', body: 'bar' }, - filename: 'filename', - html: 'html', - mergeTags: { foo: 'string' }, - url: 'https://example.com', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); + test('generateCreate: required and optional params', async () => { + const response = await client.documents.generateCreate({ + design: { counters: 'bar', body: 'bar' }, + filename: 'filename', + html: 'html', + mergeTags: { foo: 'string' }, + url: 'https://example.com', + }); }); test('generateTemplateTemplate: only required params', async () => { diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index e5d218d..1487ee5 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -38,7 +38,10 @@ describe('resource emailsV1', () => { }); test('sendCreate: only required params', async () => { - const responsePromise = client.emailsV1.sendCreate({ to: 'test@example.com' }); + const responsePromise = client.emailsV1.sendCreate({ + design: { counters: 'bar', body: 'bar' }, + to: 'test@example.com', + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -50,8 +53,8 @@ describe('resource emailsV1', () => { test('sendCreate: required and optional params', async () => { const response = await client.emailsV1.sendCreate({ - to: 'test@example.com', design: { counters: 'bar', body: 'bar' }, + to: 'test@example.com', html: 'html', mergeTags: { foo: 'string' }, subject: 'Test Email', diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index d60f29c..cd09080 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -38,7 +38,10 @@ describe('resource emails', () => { }); test('sendCreate: only required params', async () => { - const responsePromise = client.emails.sendCreate({ to: 'test@example.com' }); + const responsePromise = client.emails.sendCreate({ + design: { counters: 'bar', body: 'bar' }, + to: 'test@example.com', + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -50,8 +53,8 @@ describe('resource emails', () => { test('sendCreate: required and optional params', async () => { const response = await client.emails.sendCreate({ - to: 'test@example.com', design: { counters: 'bar', body: 'bar' }, + to: 'test@example.com', html: 'html', mergeTags: { foo: 'string' }, subject: 'Test Email', From 050a25491de7bd4ff8f817ce927dc63c1ce8b9f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:05:59 +0000 Subject: [PATCH 020/118] feat(api): api update --- .stats.yml | 6 +- api.md | 148 +++++++++++++++++++++++++------------------------- src/client.ts | 100 +++++++++++++++++----------------- 3 files changed, 127 insertions(+), 127 deletions(-) diff --git a/.stats.yml b/.stats.yml index 76b92d7..462f78d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-168db8cc4eb5bba88beea6baf4121fa28092e423fc8457088a1feb755a7b2f79.yml -openapi_spec_hash: 137bedbc636b64c2971b6cd06f8debe2 -config_hash: 4679527c1267fd5656a4122b4f89960c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-36e6b164f4fc145ef8b0068290d8ffa479dbfadb8fe11263d6ccd49ea0dd4a22.yml +openapi_spec_hash: b4022090026a2d0b27e2c2c19e6581b2 +config_hash: 8884bc600a5a226418f2d362a6eb98bb diff --git a/api.md b/api.md index 3301910..21020df 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,77 @@ +# ProjectV1 + +Types: + +- ProjectV1APIKeysCreateResponse +- ProjectV1APIKeysListResponse +- ProjectV1APIKeysRetrieveResponse +- ProjectV1APIKeysUpdateResponse +- ProjectV1CurrentListResponse +- ProjectV1DomainsCreateResponse +- ProjectV1DomainsListResponse +- ProjectV1DomainsRetrieveResponse +- ProjectV1DomainsUpdateResponse +- ProjectV1TemplatesCreateResponse +- ProjectV1TemplatesListResponse +- ProjectV1TemplatesRetrieveResponse +- ProjectV1TemplatesUpdateResponse + +Methods: + +- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse +- client.projectV1.apiKeysDelete(id) -> void +- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse +- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse +- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse +- client.projectV1.currentList() -> ProjectV1CurrentListResponse +- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse +- client.projectV1.domainsDelete(id) -> void +- client.projectV1.domainsList() -> ProjectV1DomainsListResponse +- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse +- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse +- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse +- client.projectV1.templatesDelete(id) -> void +- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse +- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse +- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse + +# Project + +Types: + +- ProjectAPIKeysCreateResponse +- ProjectAPIKeysListResponse +- ProjectAPIKeysRetrieveResponse +- ProjectAPIKeysUpdateResponse +- ProjectCurrentListResponse +- ProjectDomainsCreateResponse +- ProjectDomainsListResponse +- ProjectDomainsRetrieveResponse +- ProjectDomainsUpdateResponse +- ProjectTemplatesCreateResponse +- ProjectTemplatesListResponse +- ProjectTemplatesRetrieveResponse +- ProjectTemplatesUpdateResponse + +Methods: + +- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse +- client.project.apiKeysDelete(id) -> void +- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse +- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse +- client.project.currentList() -> ProjectCurrentListResponse +- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse +- client.project.domainsDelete(id) -> void +- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse +- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse +- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse +- client.project.templatesDelete(id) -> void +- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse +- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse + # EmailsV1 Types: @@ -77,77 +151,3 @@ Types: Methods: - client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - -# ProjectV1 - -Types: - -- ProjectV1APIKeysCreateResponse -- ProjectV1APIKeysListResponse -- ProjectV1APIKeysRetrieveResponse -- ProjectV1APIKeysUpdateResponse -- ProjectV1CurrentListResponse -- ProjectV1DomainsCreateResponse -- ProjectV1DomainsListResponse -- ProjectV1DomainsRetrieveResponse -- ProjectV1DomainsUpdateResponse -- ProjectV1TemplatesCreateResponse -- ProjectV1TemplatesListResponse -- ProjectV1TemplatesRetrieveResponse -- ProjectV1TemplatesUpdateResponse - -Methods: - -- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse -- client.projectV1.apiKeysDelete(id) -> void -- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse -- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse -- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse -- client.projectV1.currentList() -> ProjectV1CurrentListResponse -- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse -- client.projectV1.domainsDelete(id) -> void -- client.projectV1.domainsList() -> ProjectV1DomainsListResponse -- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse -- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse -- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse -- client.projectV1.templatesDelete(id) -> void -- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse -- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse -- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse - -# Project - -Types: - -- ProjectAPIKeysCreateResponse -- ProjectAPIKeysListResponse -- ProjectAPIKeysRetrieveResponse -- ProjectAPIKeysUpdateResponse -- ProjectCurrentListResponse -- ProjectDomainsCreateResponse -- ProjectDomainsListResponse -- ProjectDomainsRetrieveResponse -- ProjectDomainsUpdateResponse -- ProjectTemplatesCreateResponse -- ProjectTemplatesListResponse -- ProjectTemplatesRetrieveResponse -- ProjectTemplatesUpdateResponse - -Methods: - -- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse -- client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList() -> ProjectAPIKeysListResponse -- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse -- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse -- client.project.currentList() -> ProjectCurrentListResponse -- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse -- client.project.domainsDelete(id) -> void -- client.project.domainsList() -> ProjectDomainsListResponse -- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse -- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse -- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse -- client.project.templatesDelete(id) -> void -- client.project.templatesList() -> ProjectTemplatesListResponse -- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse -- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse diff --git a/src/client.ts b/src/client.ts index 6b9ae4c..fc956b9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,28 +795,74 @@ export class Unlayer { static toFile = Uploads.toFile; + projectV1: API.ProjectV1 = new API.ProjectV1(this); + project: API.Project = new API.Project(this); emailsV1: API.EmailsV1 = new API.EmailsV1(this); emails: API.Emails = new API.Emails(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); - projectV1: API.ProjectV1 = new API.ProjectV1(this); - project: API.Project = new API.Project(this); } +Unlayer.ProjectV1 = ProjectV1; +Unlayer.Project = Project; Unlayer.EmailsV1 = EmailsV1; Unlayer.Emails = Emails; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; Unlayer.Pages = Pages; -Unlayer.ProjectV1 = ProjectV1; -Unlayer.Project = Project; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + ProjectV1 as ProjectV1, + type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, + type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, + type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, + type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, + type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, + type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, + type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, + type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, + type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, + type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, + type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, + type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, + type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, + type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, + type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, + type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, + type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, + type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, + type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, + }; + + export { + Project as Project, + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; + export { EmailsV1 as EmailsV1, type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, @@ -868,50 +914,4 @@ export declare namespace Unlayer { type PageRenderCreateResponse as PageRenderCreateResponse, type PageRenderCreateParams as PageRenderCreateParams, }; - - export { - ProjectV1 as ProjectV1, - type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, - type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, - type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, - type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, - type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, - type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, - type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, - type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, - type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, - type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, - type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, - type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, - type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, - type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, - type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, - type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, - type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, - type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, - type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, - }; - - export { - Project as Project, - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; } From 7f4ea96777f30cf5a78e0bc38e1969612cd23a3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:17:16 +0000 Subject: [PATCH 021/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 462f78d..4b2f990 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-36e6b164f4fc145ef8b0068290d8ffa479dbfadb8fe11263d6ccd49ea0dd4a22.yml openapi_spec_hash: b4022090026a2d0b27e2c2c19e6581b2 -config_hash: 8884bc600a5a226418f2d362a6eb98bb +config_hash: 256da0d3adcdb5fa292234ddd8247f58 From 2ef7fd8f1fe203a9cbe0cbaab1872a3dcf14ac08 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:25:54 +0000 Subject: [PATCH 022/118] feat(api): api update --- .stats.yml | 6 ++--- api.md | 64 +++++++++++++++++++++++++-------------------------- src/client.ts | 52 ++++++++++++++++++++--------------------- 3 files changed, 61 insertions(+), 61 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4b2f990..2a30352 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-36e6b164f4fc145ef8b0068290d8ffa479dbfadb8fe11263d6ccd49ea0dd4a22.yml -openapi_spec_hash: b4022090026a2d0b27e2c2c19e6581b2 -config_hash: 256da0d3adcdb5fa292234ddd8247f58 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e7d9e7f911c6b5d98e662c31862450cb0519a86c051c80d6eaa47cdebfe86fb4.yml +openapi_spec_hash: e2a7835f5a7b7c5a6b6bd7c3a4786af3 +config_hash: a4f34863030203b80da5a78b0d4ea416 diff --git a/api.md b/api.md index 21020df..49167ca 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,35 @@ +# EmailsV1 + +Types: + +- EmailsV1EmailsRetrieveResponse +- EmailsV1RenderCreateResponse +- EmailsV1SendCreateResponse +- EmailsV1SendTemplateTemplateResponse + +Methods: + +- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse +- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse +- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse +- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse + +# Emails + +Types: + +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # ProjectV1 Types: @@ -72,38 +104,6 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# EmailsV1 - -Types: - -- EmailsV1EmailsRetrieveResponse -- EmailsV1RenderCreateResponse -- EmailsV1SendCreateResponse -- EmailsV1SendTemplateTemplateResponse - -Methods: - -- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse -- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse -- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse -- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse - -# Emails - -Types: - -- EmailEmailsRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - # DocumentsV1 Types: diff --git a/src/client.ts b/src/client.ts index fc956b9..fb711d9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -795,20 +795,20 @@ export class Unlayer { static toFile = Uploads.toFile; - projectV1: API.ProjectV1 = new API.ProjectV1(this); - project: API.Project = new API.Project(this); emailsV1: API.EmailsV1 = new API.EmailsV1(this); emails: API.Emails = new API.Emails(this); + projectV1: API.ProjectV1 = new API.ProjectV1(this); + project: API.Project = new API.Project(this); documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); documents: API.Documents = new API.Documents(this); pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); } -Unlayer.ProjectV1 = ProjectV1; -Unlayer.Project = Project; Unlayer.EmailsV1 = EmailsV1; Unlayer.Emails = Emails; +Unlayer.ProjectV1 = ProjectV1; +Unlayer.Project = Project; Unlayer.DocumentsV1 = DocumentsV1; Unlayer.Documents = Documents; Unlayer.PagesV1 = PagesV1; @@ -817,6 +817,28 @@ Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + EmailsV1 as EmailsV1, + type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, + type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, + type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, + type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, + type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, + type EmailsV1SendCreateParams as EmailsV1SendCreateParams, + type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + }; + + export { + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { ProjectV1 as ProjectV1, type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, @@ -863,28 +885,6 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - export { - EmailsV1 as EmailsV1, - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, - }; - - export { - Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { DocumentsV1 as DocumentsV1, type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, From 4bae4423fda5892cc395688d92fcc671a6d2c3bc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:55:53 +0000 Subject: [PATCH 023/118] feat(api): api update --- .stats.yml | 6 +++--- src/resources/emails-v1.ts | 2 +- src/resources/emails.ts | 2 +- tests/api-resources/emails-v1.test.ts | 2 +- tests/api-resources/emails.test.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2a30352..f155fdc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e7d9e7f911c6b5d98e662c31862450cb0519a86c051c80d6eaa47cdebfe86fb4.yml -openapi_spec_hash: e2a7835f5a7b7c5a6b6bd7c3a4786af3 -config_hash: a4f34863030203b80da5a78b0d4ea416 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml +openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e +config_hash: 60fe170373c35bb6b1455ffa12ac8dc2 diff --git a/src/resources/emails-v1.ts b/src/resources/emails-v1.ts index e73be22..af7324d 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails-v1.ts @@ -81,7 +81,7 @@ export class EmailsV1 extends APIResource { * }, * }, * to: 'test@example.com', - * subject: 'Test Email', + * subject: 'Test', * }); * ``` */ diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 5bf461c..d7f599d 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -81,7 +81,7 @@ export class Emails extends APIResource { * }, * }, * to: 'test@example.com', - * subject: 'Test Email', + * subject: 'Test', * }); * ``` */ diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails-v1.test.ts index 1487ee5..35e657d 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails-v1.test.ts @@ -57,7 +57,7 @@ describe('resource emailsV1', () => { to: 'test@example.com', html: 'html', mergeTags: { foo: 'string' }, - subject: 'Test Email', + subject: 'Test', }); }); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index cd09080..30a3ffd 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -57,7 +57,7 @@ describe('resource emails', () => { to: 'test@example.com', html: 'html', mergeTags: { foo: 'string' }, - subject: 'Test Email', + subject: 'Test', }); }); From 23c9dd8480ceda66092ffbbb13f57b2f6a50bacf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 19:06:26 +0000 Subject: [PATCH 024/118] feat(api): api update --- .stats.yml | 6 +- README.md | 16 +- api.md | 200 +++---- src/client.ts | 126 +--- src/resources/documents.ts | 209 +------ src/resources/documents/documents.ts | 232 +++++++ src/resources/documents/index.ts | 18 + .../{documents-v1.ts => documents/v1.ts} | 51 +- src/resources/emails.ts | 238 +------- src/resources/emails/emails.ts | 265 ++++++++ src/resources/emails/index.ts | 22 + src/resources/{emails-v1.ts => emails/v1.ts} | 72 ++- src/resources/index.ts | 49 +- src/resources/pages.ts | 65 +- src/resources/pages/index.ts | 4 + src/resources/pages/pages.ts | 78 +++ src/resources/{pages-v1.ts => pages/v1.ts} | 25 +- src/resources/project.ts | 515 +--------------- src/resources/project/index.ts | 46 ++ src/resources/project/project.ts | 566 ++++++++++++++++++ .../{project-v1.ts => project/v1.ts} | 182 +++--- .../{ => documents}/documents.test.ts | 0 .../v1.test.ts} | 12 +- .../api-resources/{ => emails}/emails.test.ts | 0 .../{emails-v1.test.ts => emails/v1.test.ts} | 16 +- tests/api-resources/{ => pages}/pages.test.ts | 0 .../{pages-v1.test.ts => pages/v1.test.ts} | 6 +- .../{ => project}/project.test.ts | 0 .../v1.test.ts} | 46 +- 29 files changed, 1563 insertions(+), 1502 deletions(-) create mode 100644 src/resources/documents/documents.ts create mode 100644 src/resources/documents/index.ts rename src/resources/{documents-v1.ts => documents/v1.ts} (67%) create mode 100644 src/resources/emails/emails.ts create mode 100644 src/resources/emails/index.ts rename src/resources/{emails-v1.ts => emails/v1.ts} (66%) create mode 100644 src/resources/pages/index.ts create mode 100644 src/resources/pages/pages.ts rename src/resources/{pages-v1.ts => pages/v1.ts} (61%) create mode 100644 src/resources/project/index.ts create mode 100644 src/resources/project/project.ts rename src/resources/{project-v1.ts => project/v1.ts} (54%) rename tests/api-resources/{ => documents}/documents.test.ts (100%) rename tests/api-resources/{documents-v1.test.ts => documents/v1.test.ts} (81%) rename tests/api-resources/{ => emails}/emails.test.ts (100%) rename tests/api-resources/{emails-v1.test.ts => emails/v1.test.ts} (84%) rename tests/api-resources/{ => pages}/pages.test.ts (100%) rename tests/api-resources/{pages-v1.test.ts => pages/v1.test.ts} (81%) rename tests/api-resources/{ => project}/project.test.ts (100%) rename tests/api-resources/{project-v1.test.ts => project/v1.test.ts} (84%) diff --git a/.stats.yml b/.stats.yml index f155fdc..b7a5fc0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml -openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e -config_hash: 60fe170373c35bb6b1455ffa12ac8dc2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d746e93c3c920dca97596edec38c9ec25feef644db419156ae1b538bb54b6d72.yml +openapi_spec_hash: 437dce81b84c463ef9cc84dafa2ca92a +config_hash: 355cc7936ae5249f192357f93dab04c8 diff --git a/README.md b/README.md index 827d403..2f826bf 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); -const response = await client.projectV1.currentList(); +const response = await client.project.currentList(); console.log(response.data); ``` @@ -46,7 +46,7 @@ const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); -const response: Unlayer.ProjectV1CurrentListResponse = await client.projectV1.currentList(); +const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -59,7 +59,7 @@ a subclass of `APIError` will be thrown: ```ts -const response = await client.projectV1.currentList().catch(async (err) => { +const response = await client.project.currentList().catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 console.log(err.name); // BadRequestError @@ -99,7 +99,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.projectV1.currentList({ +await client.project.currentList({ maxRetries: 5, }); ``` @@ -116,7 +116,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.projectV1.currentList({ +await client.project.currentList({ timeout: 5 * 1000, }); ``` @@ -139,11 +139,11 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.projectV1.currentList().asResponse(); +const response = await client.project.currentList().asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: response, response: raw } = await client.projectV1.currentList().withResponse(); +const { data: response, response: raw } = await client.project.currentList().withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(response.data); ``` @@ -225,7 +225,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.projectV1.currentList({ +client.project.currentList({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index 49167ca..e24871e 100644 --- a/api.md +++ b/api.md @@ -1,153 +1,153 @@ -# EmailsV1 +# Project Types: -- EmailsV1EmailsRetrieveResponse -- EmailsV1RenderCreateResponse -- EmailsV1SendCreateResponse -- EmailsV1SendTemplateTemplateResponse +- ProjectAPIKeysCreateResponse +- ProjectAPIKeysListResponse +- ProjectAPIKeysRetrieveResponse +- ProjectAPIKeysUpdateResponse +- ProjectCurrentListResponse +- ProjectDomainsCreateResponse +- ProjectDomainsListResponse +- ProjectDomainsRetrieveResponse +- ProjectDomainsUpdateResponse +- ProjectTemplatesCreateResponse +- ProjectTemplatesListResponse +- ProjectTemplatesRetrieveResponse +- ProjectTemplatesUpdateResponse Methods: -- client.emailsV1.emailsRetrieve(id) -> EmailsV1EmailsRetrieveResponse -- client.emailsV1.renderCreate({ ...params }) -> EmailsV1RenderCreateResponse -- client.emailsV1.sendCreate({ ...params }) -> EmailsV1SendCreateResponse -- client.emailsV1.sendTemplateTemplate({ ...params }) -> EmailsV1SendTemplateTemplateResponse - -# Emails +- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse +- client.project.apiKeysDelete(id) -> void +- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse +- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse +- client.project.currentList() -> ProjectCurrentListResponse +- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse +- client.project.domainsDelete(id) -> void +- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse +- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse +- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse +- client.project.templatesDelete(id) -> void +- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse +- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse + +## V1 Types: -- EmailEmailsRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- V1APIKeysCreateResponse +- V1APIKeysListResponse +- V1APIKeysRetrieveResponse +- V1APIKeysUpdateResponse +- V1CurrentListResponse +- V1DomainsCreateResponse +- V1DomainsListResponse +- V1DomainsRetrieveResponse +- V1DomainsUpdateResponse +- V1TemplatesCreateResponse +- V1TemplatesListResponse +- V1TemplatesRetrieveResponse +- V1TemplatesUpdateResponse Methods: -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.project.v1.apiKeysCreate({ ...params }) -> V1APIKeysCreateResponse +- client.project.v1.apiKeysDelete(id) -> void +- client.project.v1.apiKeysList() -> V1APIKeysListResponse +- client.project.v1.apiKeysRetrieve(id) -> V1APIKeysRetrieveResponse +- client.project.v1.apiKeysUpdate(id, { ...params }) -> V1APIKeysUpdateResponse +- client.project.v1.currentList() -> V1CurrentListResponse +- client.project.v1.domainsCreate({ ...params }) -> V1DomainsCreateResponse +- client.project.v1.domainsDelete(id) -> void +- client.project.v1.domainsList() -> V1DomainsListResponse +- client.project.v1.domainsRetrieve(id) -> V1DomainsRetrieveResponse +- client.project.v1.domainsUpdate(id, { ...params }) -> V1DomainsUpdateResponse +- client.project.v1.templatesCreate({ ...params }) -> V1TemplatesCreateResponse +- client.project.v1.templatesDelete(id) -> void +- client.project.v1.templatesList() -> V1TemplatesListResponse +- client.project.v1.templatesRetrieve(id) -> V1TemplatesRetrieveResponse +- client.project.v1.templatesUpdate(id, { ...params }) -> V1TemplatesUpdateResponse -# ProjectV1 +# Emails Types: -- ProjectV1APIKeysCreateResponse -- ProjectV1APIKeysListResponse -- ProjectV1APIKeysRetrieveResponse -- ProjectV1APIKeysUpdateResponse -- ProjectV1CurrentListResponse -- ProjectV1DomainsCreateResponse -- ProjectV1DomainsListResponse -- ProjectV1DomainsRetrieveResponse -- ProjectV1DomainsUpdateResponse -- ProjectV1TemplatesCreateResponse -- ProjectV1TemplatesListResponse -- ProjectV1TemplatesRetrieveResponse -- ProjectV1TemplatesUpdateResponse +- EmailEmailsRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.projectV1.apiKeysCreate({ ...params }) -> ProjectV1APIKeysCreateResponse -- client.projectV1.apiKeysDelete(id) -> void -- client.projectV1.apiKeysList() -> ProjectV1APIKeysListResponse -- client.projectV1.apiKeysRetrieve(id) -> ProjectV1APIKeysRetrieveResponse -- client.projectV1.apiKeysUpdate(id, { ...params }) -> ProjectV1APIKeysUpdateResponse -- client.projectV1.currentList() -> ProjectV1CurrentListResponse -- client.projectV1.domainsCreate({ ...params }) -> ProjectV1DomainsCreateResponse -- client.projectV1.domainsDelete(id) -> void -- client.projectV1.domainsList() -> ProjectV1DomainsListResponse -- client.projectV1.domainsRetrieve(id) -> ProjectV1DomainsRetrieveResponse -- client.projectV1.domainsUpdate(id, { ...params }) -> ProjectV1DomainsUpdateResponse -- client.projectV1.templatesCreate({ ...params }) -> ProjectV1TemplatesCreateResponse -- client.projectV1.templatesDelete(id) -> void -- client.projectV1.templatesList() -> ProjectV1TemplatesListResponse -- client.projectV1.templatesRetrieve(id) -> ProjectV1TemplatesRetrieveResponse -- client.projectV1.templatesUpdate(id, { ...params }) -> ProjectV1TemplatesUpdateResponse +- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse -# Project +## V1 Types: -- ProjectAPIKeysCreateResponse -- ProjectAPIKeysListResponse -- ProjectAPIKeysRetrieveResponse -- ProjectAPIKeysUpdateResponse -- ProjectCurrentListResponse -- ProjectDomainsCreateResponse -- ProjectDomainsListResponse -- ProjectDomainsRetrieveResponse -- ProjectDomainsUpdateResponse -- ProjectTemplatesCreateResponse -- ProjectTemplatesListResponse -- ProjectTemplatesRetrieveResponse -- ProjectTemplatesUpdateResponse +- V1EmailsRetrieveResponse +- V1RenderCreateResponse +- V1SendCreateResponse +- V1SendTemplateTemplateResponse Methods: -- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse -- client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList() -> ProjectAPIKeysListResponse -- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse -- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse -- client.project.currentList() -> ProjectCurrentListResponse -- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse -- client.project.domainsDelete(id) -> void -- client.project.domainsList() -> ProjectDomainsListResponse -- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse -- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse -- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse -- client.project.templatesDelete(id) -> void -- client.project.templatesList() -> ProjectTemplatesListResponse -- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse -- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse - -# DocumentsV1 +- client.emails.v1.emailsRetrieve(id) -> V1EmailsRetrieveResponse +- client.emails.v1.renderCreate({ ...params }) -> V1RenderCreateResponse +- client.emails.v1.sendCreate({ ...params }) -> V1SendCreateResponse +- client.emails.v1.sendTemplateTemplate({ ...params }) -> V1SendTemplateTemplateResponse + +# Documents Types: -- DocumentsV1DocumentsRetrieveResponse -- DocumentsV1GenerateCreateResponse -- DocumentsV1GenerateTemplateTemplateResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.documentsV1.documentsRetrieve(id) -> DocumentsV1DocumentsRetrieveResponse -- client.documentsV1.generateCreate({ ...params }) -> DocumentsV1GenerateCreateResponse -- client.documentsV1.generateTemplateTemplate({ ...params }) -> DocumentsV1GenerateTemplateTemplateResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse -# Documents +## V1 Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse +- V1DocumentsRetrieveResponse +- V1GenerateCreateResponse +- V1GenerateTemplateTemplateResponse Methods: -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse +- client.documents.v1.documentsRetrieve(id) -> V1DocumentsRetrieveResponse +- client.documents.v1.generateCreate({ ...params }) -> V1GenerateCreateResponse +- client.documents.v1.generateTemplateTemplate({ ...params }) -> V1GenerateTemplateTemplateResponse -# PagesV1 +# Pages Types: -- PagesV1RenderCreateResponse +- PageRenderCreateResponse Methods: -- client.pagesV1.renderCreate({ ...params }) -> PagesV1RenderCreateResponse +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse -# Pages +## V1 Types: -- PageRenderCreateResponse +- V1RenderCreateResponse Methods: -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse +- client.pages.v1.renderCreate({ ...params }) -> V1RenderCreateResponse diff --git a/src/client.ts b/src/client.ts index fb711d9..c04de55 100644 --- a/src/client.ts +++ b/src/client.ts @@ -23,15 +23,7 @@ import { DocumentGenerateTemplateTemplateParams, DocumentGenerateTemplateTemplateResponse, Documents, -} from './resources/documents'; -import { - DocumentsV1, - DocumentsV1DocumentsRetrieveResponse, - DocumentsV1GenerateCreateParams, - DocumentsV1GenerateCreateResponse, - DocumentsV1GenerateTemplateTemplateParams, - DocumentsV1GenerateTemplateTemplateResponse, -} from './resources/documents-v1'; +} from './resources/documents/documents'; import { EmailEmailsRetrieveResponse, EmailRenderCreateParams, @@ -41,19 +33,8 @@ import { EmailSendTemplateTemplateParams, EmailSendTemplateTemplateResponse, Emails, -} from './resources/emails'; -import { - EmailsV1, - EmailsV1EmailsRetrieveResponse, - EmailsV1RenderCreateParams, - EmailsV1RenderCreateResponse, - EmailsV1SendCreateParams, - EmailsV1SendCreateResponse, - EmailsV1SendTemplateTemplateParams, - EmailsV1SendTemplateTemplateResponse, -} from './resources/emails-v1'; -import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages'; -import { PagesV1, PagesV1RenderCreateParams, PagesV1RenderCreateResponse } from './resources/pages-v1'; +} from './resources/emails/emails'; +import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages/pages'; import { Project, ProjectAPIKeysCreateParams, @@ -75,29 +56,7 @@ import { ProjectTemplatesRetrieveResponse, ProjectTemplatesUpdateParams, ProjectTemplatesUpdateResponse, -} from './resources/project'; -import { - ProjectV1, - ProjectV1APIKeysCreateParams, - ProjectV1APIKeysCreateResponse, - ProjectV1APIKeysListResponse, - ProjectV1APIKeysRetrieveResponse, - ProjectV1APIKeysUpdateParams, - ProjectV1APIKeysUpdateResponse, - ProjectV1CurrentListResponse, - ProjectV1DomainsCreateParams, - ProjectV1DomainsCreateResponse, - ProjectV1DomainsListResponse, - ProjectV1DomainsRetrieveResponse, - ProjectV1DomainsUpdateParams, - ProjectV1DomainsUpdateResponse, - ProjectV1TemplatesCreateParams, - ProjectV1TemplatesCreateResponse, - ProjectV1TemplatesListResponse, - ProjectV1TemplatesRetrieveResponse, - ProjectV1TemplatesUpdateParams, - ProjectV1TemplatesUpdateResponse, -} from './resources/project-v1'; +} from './resources/project/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -795,73 +754,20 @@ export class Unlayer { static toFile = Uploads.toFile; - emailsV1: API.EmailsV1 = new API.EmailsV1(this); - emails: API.Emails = new API.Emails(this); - projectV1: API.ProjectV1 = new API.ProjectV1(this); project: API.Project = new API.Project(this); - documentsV1: API.DocumentsV1 = new API.DocumentsV1(this); + emails: API.Emails = new API.Emails(this); documents: API.Documents = new API.Documents(this); - pagesV1: API.PagesV1 = new API.PagesV1(this); pages: API.Pages = new API.Pages(this); } -Unlayer.EmailsV1 = EmailsV1; -Unlayer.Emails = Emails; -Unlayer.ProjectV1 = ProjectV1; Unlayer.Project = Project; -Unlayer.DocumentsV1 = DocumentsV1; +Unlayer.Emails = Emails; Unlayer.Documents = Documents; -Unlayer.PagesV1 = PagesV1; Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - EmailsV1 as EmailsV1, - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, - }; - - export { - Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - - export { - ProjectV1 as ProjectV1, - type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, - type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, - type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, - type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, - type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, - type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, - type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, - type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, - type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, - type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, - type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, - type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, - type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, - type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, - type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, - type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, - type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, - type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, - type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, - }; - export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -886,12 +792,14 @@ export declare namespace Unlayer { }; export { - DocumentsV1 as DocumentsV1, - type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, - type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, - type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, - type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, - type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, + Emails as Emails, + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; export { @@ -903,12 +811,6 @@ export declare namespace Unlayer { type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; - export { - PagesV1 as PagesV1, - type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, - type PagesV1RenderCreateParams as PagesV1RenderCreateParams, - }; - export { Pages as Pages, type PageRenderCreateResponse as PageRenderCreateResponse, diff --git a/src/resources/documents.ts b/src/resources/documents.ts index bb6b135..6dcfade 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -1,210 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Documents extends APIResource { - /** - * Retrieve details of a previously generated document. - * - * @example - * ```ts - * const response = await client.documents.documentsRetrieve( - * 'id', - * ); - * ``` - */ - documentsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, options); - } - - /** - * Generate PDF document from JSON design, HTML content, or URL. - * - * @example - * ```ts - * const response = await client.documents.generateCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - generateCreate( - body: DocumentGenerateCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate', { body, ...options }); - } - - /** - * Generate PDF document from an existing template with merge tags. - * - * @example - * ```ts - * const response = - * await client.documents.generateTemplateTemplate({ - * templateId: 'templateId', - * }); - * ``` - */ - generateTemplateTemplate( - body: DocumentGenerateTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate/template', { body, ...options }); - } -} - -export interface DocumentDocumentsRetrieveResponse { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateCreateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateTemplateTemplateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * HTML content to convert to PDF - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * URL to convert to PDF - */ - url?: string; -} - -export interface DocumentGenerateTemplateTemplateParams { - /** - * ID of the template to use for generation - */ - templateId: string; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Documents { - export { - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; -} +export * from './documents/index'; diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts new file mode 100644 index 0000000..ff05f41 --- /dev/null +++ b/src/resources/documents/documents.ts @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1'; +import { + V1, + V1DocumentsRetrieveResponse, + V1GenerateCreateParams, + V1GenerateCreateResponse, + V1GenerateTemplateTemplateParams, + V1GenerateTemplateTemplateResponse, +} from './v1'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Documents extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); + + /** + * Retrieve details of a previously generated document. + * + * @example + * ```ts + * const response = await client.documents.documentsRetrieve( + * 'id', + * ); + * ``` + */ + documentsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, options); + } + + /** + * Generate PDF document from JSON design, HTML content, or URL. + * + * @example + * ```ts + * const response = await client.documents.generateCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + generateCreate( + body: DocumentGenerateCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate', { body, ...options }); + } + + /** + * Generate PDF document from an existing template with merge tags. + * + * @example + * ```ts + * const response = + * await client.documents.generateTemplateTemplate({ + * templateId: 'templateId', + * }); + * ``` + */ + generateTemplateTemplate( + body: DocumentGenerateTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/template', { body, ...options }); + } +} + +export interface DocumentDocumentsRetrieveResponse { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateTemplateTemplateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * HTML content to convert to PDF + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * URL to convert to PDF + */ + url?: string; +} + +export interface DocumentGenerateTemplateTemplateParams { + /** + * ID of the template to use for generation + */ + templateId: string; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +Documents.V1 = V1; + +export declare namespace Documents { + export { + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + + export { + V1 as V1, + type V1DocumentsRetrieveResponse as V1DocumentsRetrieveResponse, + type V1GenerateCreateResponse as V1GenerateCreateResponse, + type V1GenerateTemplateTemplateResponse as V1GenerateTemplateTemplateResponse, + type V1GenerateCreateParams as V1GenerateCreateParams, + type V1GenerateTemplateTemplateParams as V1GenerateTemplateTemplateParams, + }; +} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts new file mode 100644 index 0000000..5bbd657 --- /dev/null +++ b/src/resources/documents/index.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Documents, + type DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams, +} from './documents'; +export { + V1, + type V1DocumentsRetrieveResponse, + type V1GenerateCreateResponse, + type V1GenerateTemplateTemplateResponse, + type V1GenerateCreateParams, + type V1GenerateTemplateTemplateParams, +} from './v1'; diff --git a/src/resources/documents-v1.ts b/src/resources/documents/v1.ts similarity index 67% rename from src/resources/documents-v1.ts rename to src/resources/documents/v1.ts index 4a3ffc5..85e4605 100644 --- a/src/resources/documents-v1.ts +++ b/src/resources/documents/v1.ts @@ -1,22 +1,21 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; -export class DocumentsV1 extends APIResource { +export class V1 extends APIResource { /** * Retrieve details of a previously generated document. * * @example * ```ts - * const response = await client.documentsV1.documentsRetrieve( - * 'id', - * ); + * const response = + * await client.documents.v1.documentsRetrieve('id'); * ``` */ - documentsRetrieve(id: string, options?: RequestOptions): APIPromise { + documentsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/documents/v1/documents/${id}`, options); } @@ -25,7 +24,7 @@ export class DocumentsV1 extends APIResource { * * @example * ```ts - * const response = await client.documentsV1.generateCreate({ + * const response = await client.documents.v1.generateCreate({ * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -50,9 +49,9 @@ export class DocumentsV1 extends APIResource { * ``` */ generateCreate( - body: DocumentsV1GenerateCreateParams, + body: V1GenerateCreateParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.post('/documents/v1/generate', { body, ...options }); } @@ -62,20 +61,20 @@ export class DocumentsV1 extends APIResource { * @example * ```ts * const response = - * await client.documentsV1.generateTemplateTemplate({ + * await client.documents.v1.generateTemplateTemplate({ * templateId: 'templateId', * }); * ``` */ generateTemplateTemplate( - body: DocumentsV1GenerateTemplateTemplateParams, + body: V1GenerateTemplateTemplateParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.post('/documents/v1/generate/template', { body, ...options }); } } -export interface DocumentsV1DocumentsRetrieveResponse { +export interface V1DocumentsRetrieveResponse { /** * Document ID */ @@ -117,7 +116,7 @@ export interface DocumentsV1DocumentsRetrieveResponse { status?: 'generating' | 'completed' | 'failed'; } -export interface DocumentsV1GenerateCreateResponse { +export interface V1GenerateCreateResponse { /** * Unique document identifier */ @@ -136,7 +135,7 @@ export interface DocumentsV1GenerateCreateResponse { status?: 'generating' | 'completed' | 'failed'; } -export interface DocumentsV1GenerateTemplateTemplateResponse { +export interface V1GenerateTemplateTemplateResponse { /** * Unique document identifier */ @@ -155,7 +154,7 @@ export interface DocumentsV1GenerateTemplateTemplateResponse { status?: 'generating' | 'completed' | 'failed'; } -export interface DocumentsV1GenerateCreateParams { +export interface V1GenerateCreateParams { /** * Proprietary design format JSON */ @@ -182,7 +181,7 @@ export interface DocumentsV1GenerateCreateParams { url?: string; } -export interface DocumentsV1GenerateTemplateTemplateParams { +export interface V1GenerateTemplateTemplateParams { /** * ID of the template to use for generation */ @@ -199,12 +198,12 @@ export interface DocumentsV1GenerateTemplateTemplateParams { mergeTags?: { [key: string]: string }; } -export declare namespace DocumentsV1 { +export declare namespace V1 { export { - type DocumentsV1DocumentsRetrieveResponse as DocumentsV1DocumentsRetrieveResponse, - type DocumentsV1GenerateCreateResponse as DocumentsV1GenerateCreateResponse, - type DocumentsV1GenerateTemplateTemplateResponse as DocumentsV1GenerateTemplateTemplateResponse, - type DocumentsV1GenerateCreateParams as DocumentsV1GenerateCreateParams, - type DocumentsV1GenerateTemplateTemplateParams as DocumentsV1GenerateTemplateTemplateParams, + type V1DocumentsRetrieveResponse as V1DocumentsRetrieveResponse, + type V1GenerateCreateResponse as V1GenerateCreateResponse, + type V1GenerateTemplateTemplateResponse as V1GenerateTemplateTemplateResponse, + type V1GenerateCreateParams as V1GenerateCreateParams, + type V1GenerateTemplateTemplateParams as V1GenerateTemplateTemplateParams, }; } diff --git a/src/resources/emails.ts b/src/resources/emails.ts index d7f599d..bd0ec59 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -1,239 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Emails extends APIResource { - /** - * Retrieve details of a previously sent email. - * - * @example - * ```ts - * const response = await client.emails.emailsRetrieve('id'); - * ``` - */ - emailsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, options); - } - - /** - * Convert design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.emails.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate( - body: EmailRenderCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/render', { body, ...options }); - } - - /** - * Send email with design JSON or HTML content. - * - * @example - * ```ts - * const response = await client.emails.sendCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * to: 'test@example.com', - * subject: 'Test', - * }); - * ``` - */ - sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/send', { body, ...options }); - } - - /** - * Send email using an existing template with merge tags. - * - * @example - * ```ts - * const response = await client.emails.sendTemplateTemplate({ - * templateId: 'templateId', - * to: 'dev@stainless.com', - * }); - * ``` - */ - sendTemplateTemplate( - body: EmailSendTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/send/template', { body, ...options }); - } -} - -export interface EmailEmailsRetrieveResponse { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; -} - -export interface EmailRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface EmailSendCreateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface EmailSendTemplateTemplateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface EmailRenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export interface EmailSendCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Recipient email address - */ - to: string; - - /** - * HTML content to send - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line - */ - subject?: string; -} - -export interface EmailSendTemplateTemplateParams { - /** - * ID of the template to use - */ - templateId: string; - - /** - * Recipient email address - */ - to: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -export declare namespace Emails { - export { - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; -} +export * from './emails/index'; diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts new file mode 100644 index 0000000..fd0404f --- /dev/null +++ b/src/resources/emails/emails.ts @@ -0,0 +1,265 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1'; +import { + V1, + V1EmailsRetrieveResponse, + V1RenderCreateParams, + V1RenderCreateResponse, + V1SendCreateParams, + V1SendCreateResponse, + V1SendTemplateTemplateParams, + V1SendTemplateTemplateResponse, +} from './v1'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Emails extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); + + /** + * Retrieve details of a previously sent email. + * + * @example + * ```ts + * const response = await client.emails.emailsRetrieve('id'); + * ``` + */ + emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, options); + } + + /** + * Convert design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.emails.renderCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + renderCreate( + body: EmailRenderCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/render', { body, ...options }); + } + + /** + * Send email with design JSON or HTML content. + * + * @example + * ```ts + * const response = await client.emails.sendCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * to: 'test@example.com', + * subject: 'Test', + * }); + * ``` + */ + sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/emails/v1/send', { body, ...options }); + } + + /** + * Send email using an existing template with merge tags. + * + * @example + * ```ts + * const response = await client.emails.sendTemplateTemplate({ + * templateId: 'templateId', + * to: 'dev@stainless.com', + * }); + * ``` + */ + sendTemplateTemplate( + body: EmailSendTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send/template', { body, ...options }); + } +} + +export interface EmailEmailsRetrieveResponse { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; +} + +export interface EmailRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface EmailSendCreateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailSendTemplateTemplateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export interface EmailSendCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Recipient email address + */ + to: string; + + /** + * HTML content to send + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line + */ + subject?: string; +} + +export interface EmailSendTemplateTemplateParams { + /** + * ID of the template to use + */ + templateId: string; + + /** + * Recipient email address + */ + to: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +Emails.V1 = V1; + +export declare namespace Emails { + export { + type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + + export { + V1 as V1, + type V1EmailsRetrieveResponse as V1EmailsRetrieveResponse, + type V1RenderCreateResponse as V1RenderCreateResponse, + type V1SendCreateResponse as V1SendCreateResponse, + type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, + type V1RenderCreateParams as V1RenderCreateParams, + type V1SendCreateParams as V1SendCreateParams, + type V1SendTemplateTemplateParams as V1SendTemplateTemplateParams, + }; +} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts new file mode 100644 index 0000000..e2e4c91 --- /dev/null +++ b/src/resources/emails/index.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Emails, + type EmailEmailsRetrieveResponse, + type EmailRenderCreateResponse, + type EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams, + type EmailSendCreateParams, + type EmailSendTemplateTemplateParams, +} from './emails'; +export { + V1, + type V1EmailsRetrieveResponse, + type V1RenderCreateResponse, + type V1SendCreateResponse, + type V1SendTemplateTemplateResponse, + type V1RenderCreateParams, + type V1SendCreateParams, + type V1SendTemplateTemplateParams, +} from './v1'; diff --git a/src/resources/emails-v1.ts b/src/resources/emails/v1.ts similarity index 66% rename from src/resources/emails-v1.ts rename to src/resources/emails/v1.ts index af7324d..e35ba39 100644 --- a/src/resources/emails-v1.ts +++ b/src/resources/emails/v1.ts @@ -1,20 +1,22 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; -export class EmailsV1 extends APIResource { +export class V1 extends APIResource { /** * Retrieve details of a previously sent email. * * @example * ```ts - * const response = await client.emailsV1.emailsRetrieve('id'); + * const response = await client.emails.v1.emailsRetrieve( + * 'id', + * ); * ``` */ - emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + emailsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, options); } @@ -23,7 +25,7 @@ export class EmailsV1 extends APIResource { * * @example * ```ts - * const response = await client.emailsV1.renderCreate({ + * const response = await client.emails.v1.renderCreate({ * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -47,10 +49,7 @@ export class EmailsV1 extends APIResource { * }); * ``` */ - renderCreate( - body: EmailsV1RenderCreateParams, - options?: RequestOptions, - ): APIPromise { + renderCreate(body: V1RenderCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/emails/v1/render', { body, ...options }); } @@ -59,7 +58,7 @@ export class EmailsV1 extends APIResource { * * @example * ```ts - * const response = await client.emailsV1.sendCreate({ + * const response = await client.emails.v1.sendCreate({ * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -85,10 +84,7 @@ export class EmailsV1 extends APIResource { * }); * ``` */ - sendCreate( - body: EmailsV1SendCreateParams, - options?: RequestOptions, - ): APIPromise { + sendCreate(body: V1SendCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/emails/v1/send', { body, ...options }); } @@ -97,20 +93,22 @@ export class EmailsV1 extends APIResource { * * @example * ```ts - * const response = await client.emailsV1.sendTemplateTemplate( - * { templateId: 'templateId', to: 'dev@stainless.com' }, - * ); + * const response = + * await client.emails.v1.sendTemplateTemplate({ + * templateId: 'templateId', + * to: 'dev@stainless.com', + * }); * ``` */ sendTemplateTemplate( - body: EmailsV1SendTemplateTemplateParams, + body: V1SendTemplateTemplateParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.post('/emails/v1/send/template', { body, ...options }); } } -export interface EmailsV1EmailsRetrieveResponse { +export interface V1EmailsRetrieveResponse { /** * Email message ID */ @@ -142,14 +140,14 @@ export interface EmailsV1EmailsRetrieveResponse { to?: string; } -export interface EmailsV1RenderCreateResponse { +export interface V1RenderCreateResponse { /** * Rendered HTML content */ html?: string; } -export interface EmailsV1SendCreateResponse { +export interface V1SendCreateResponse { /** * Unique message identifier */ @@ -158,7 +156,7 @@ export interface EmailsV1SendCreateResponse { status?: 'sent' | 'queued' | 'failed'; } -export interface EmailsV1SendTemplateTemplateResponse { +export interface V1SendTemplateTemplateResponse { /** * Unique message identifier */ @@ -167,7 +165,7 @@ export interface EmailsV1SendTemplateTemplateResponse { status?: 'sent' | 'queued' | 'failed'; } -export interface EmailsV1RenderCreateParams { +export interface V1RenderCreateParams { /** * Proprietary design format JSON */ @@ -179,7 +177,7 @@ export interface EmailsV1RenderCreateParams { mergeTags?: { [key: string]: string }; } -export interface EmailsV1SendCreateParams { +export interface V1SendCreateParams { /** * Proprietary design format JSON */ @@ -206,7 +204,7 @@ export interface EmailsV1SendCreateParams { subject?: string; } -export interface EmailsV1SendTemplateTemplateParams { +export interface V1SendTemplateTemplateParams { /** * ID of the template to use */ @@ -228,14 +226,14 @@ export interface EmailsV1SendTemplateTemplateParams { subject?: string; } -export declare namespace EmailsV1 { +export declare namespace V1 { export { - type EmailsV1EmailsRetrieveResponse as EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse as EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse as EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse as EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams as EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams as EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams as EmailsV1SendTemplateTemplateParams, + type V1EmailsRetrieveResponse as V1EmailsRetrieveResponse, + type V1RenderCreateResponse as V1RenderCreateResponse, + type V1SendCreateResponse as V1SendCreateResponse, + type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, + type V1RenderCreateParams as V1RenderCreateParams, + type V1SendCreateParams as V1SendCreateParams, + type V1SendTemplateTemplateParams as V1SendTemplateTemplateParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index cee5531..aee9e9e 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -7,15 +7,7 @@ export { type DocumentGenerateTemplateTemplateResponse, type DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams, -} from './documents'; -export { - DocumentsV1, - type DocumentsV1DocumentsRetrieveResponse, - type DocumentsV1GenerateCreateResponse, - type DocumentsV1GenerateTemplateTemplateResponse, - type DocumentsV1GenerateCreateParams, - type DocumentsV1GenerateTemplateTemplateParams, -} from './documents-v1'; +} from './documents/documents'; export { Emails, type EmailEmailsRetrieveResponse, @@ -25,19 +17,8 @@ export { type EmailRenderCreateParams, type EmailSendCreateParams, type EmailSendTemplateTemplateParams, -} from './emails'; -export { - EmailsV1, - type EmailsV1EmailsRetrieveResponse, - type EmailsV1RenderCreateResponse, - type EmailsV1SendCreateResponse, - type EmailsV1SendTemplateTemplateResponse, - type EmailsV1RenderCreateParams, - type EmailsV1SendCreateParams, - type EmailsV1SendTemplateTemplateParams, -} from './emails-v1'; -export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; -export { PagesV1, type PagesV1RenderCreateResponse, type PagesV1RenderCreateParams } from './pages-v1'; +} from './emails/emails'; +export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages/pages'; export { Project, type ProjectAPIKeysCreateResponse, @@ -59,26 +40,4 @@ export { type ProjectDomainsUpdateParams, type ProjectTemplatesCreateParams, type ProjectTemplatesUpdateParams, -} from './project'; -export { - ProjectV1, - type ProjectV1APIKeysCreateResponse, - type ProjectV1APIKeysListResponse, - type ProjectV1APIKeysRetrieveResponse, - type ProjectV1APIKeysUpdateResponse, - type ProjectV1CurrentListResponse, - type ProjectV1DomainsCreateResponse, - type ProjectV1DomainsListResponse, - type ProjectV1DomainsRetrieveResponse, - type ProjectV1DomainsUpdateResponse, - type ProjectV1TemplatesCreateResponse, - type ProjectV1TemplatesListResponse, - type ProjectV1TemplatesRetrieveResponse, - type ProjectV1TemplatesUpdateResponse, - type ProjectV1APIKeysCreateParams, - type ProjectV1APIKeysUpdateParams, - type ProjectV1DomainsCreateParams, - type ProjectV1DomainsUpdateParams, - type ProjectV1TemplatesCreateParams, - type ProjectV1TemplatesUpdateParams, -} from './project-v1'; +} from './project/project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 05af321..c218cbe 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -1,66 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; - -export class Pages extends APIResource { - /** - * Convert page design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.pages.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/pages/v1/render', { body, ...options }); - } -} - -export interface PageRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface PageRenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Pages { - export { - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; -} +export * from './pages/index'; diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts new file mode 100644 index 0000000..25cc7af --- /dev/null +++ b/src/resources/pages/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; +export { V1, type V1RenderCreateResponse, type V1RenderCreateParams } from './v1'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts new file mode 100644 index 0000000..549a81a --- /dev/null +++ b/src/resources/pages/pages.ts @@ -0,0 +1,78 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1'; +import { V1, V1RenderCreateParams, V1RenderCreateResponse } from './v1'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Pages extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); + + /** + * Convert page design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.pages.renderCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/pages/v1/render', { body, ...options }); + } +} + +export interface PageRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface PageRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +Pages.V1 = V1; + +export declare namespace Pages { + export { + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; + + export { + V1 as V1, + type V1RenderCreateResponse as V1RenderCreateResponse, + type V1RenderCreateParams as V1RenderCreateParams, + }; +} diff --git a/src/resources/pages-v1.ts b/src/resources/pages/v1.ts similarity index 61% rename from src/resources/pages-v1.ts rename to src/resources/pages/v1.ts index 44775af..d841749 100644 --- a/src/resources/pages-v1.ts +++ b/src/resources/pages/v1.ts @@ -1,16 +1,16 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; -export class PagesV1 extends APIResource { +export class V1 extends APIResource { /** * Convert page design JSON to HTML with optional merge tags. * * @example * ```ts - * const response = await client.pagesV1.renderCreate({ + * const response = await client.pages.v1.renderCreate({ * design: { * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, * body: { @@ -34,22 +34,19 @@ export class PagesV1 extends APIResource { * }); * ``` */ - renderCreate( - body: PagesV1RenderCreateParams, - options?: RequestOptions, - ): APIPromise { + renderCreate(body: V1RenderCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/pages/v1/render', { body, ...options }); } } -export interface PagesV1RenderCreateResponse { +export interface V1RenderCreateResponse { /** * Rendered HTML content */ html?: string; } -export interface PagesV1RenderCreateParams { +export interface V1RenderCreateParams { /** * Proprietary design format JSON */ @@ -61,9 +58,9 @@ export interface PagesV1RenderCreateParams { mergeTags?: { [key: string]: string }; } -export declare namespace PagesV1 { +export declare namespace V1 { export { - type PagesV1RenderCreateResponse as PagesV1RenderCreateResponse, - type PagesV1RenderCreateParams as PagesV1RenderCreateParams, + type V1RenderCreateResponse as V1RenderCreateResponse, + type V1RenderCreateParams as V1RenderCreateParams, }; } diff --git a/src/resources/project.ts b/src/resources/project.ts index 70418cb..60fc38d 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -1,516 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { buildHeaders } from '../internal/headers'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Project extends APIResource { - /** - * Create a new API key for the project. - */ - apiKeysCreate( - body: ProjectAPIKeysCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/api-keys', { body, ...options }); - } - - /** - * Revoke API key. - */ - apiKeysDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/api-keys/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all API keys for the project. - */ - apiKeysList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/api-keys', options); - } - - /** - * Get API key details by ID. - */ - apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/api-keys/${id}`, options); - } - - /** - * Update API key settings. - */ - apiKeysUpdate( - id: string, - body: ProjectAPIKeysUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); - } - - /** - * Get project details for the authenticated project. - */ - currentList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current', options); - } - - /** - * Add a new domain to the project. - */ - domainsCreate( - body: ProjectDomainsCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/domains', { body, ...options }); - } - - /** - * Remove domain from project. - */ - domainsDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all domains for the project. - */ - domainsList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains', options); - } - - /** - * Get domain details by ID. - */ - domainsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}`, options); - } - - /** - * Update domain settings. - */ - domainsUpdate( - id: string, - body: ProjectDomainsUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); - } - - /** - * Create a new project template. - */ - templatesCreate( - body: ProjectTemplatesCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/templates', { body, ...options }); - } - - /** - * Delete project template. - */ - templatesDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * Get all project templates. - */ - templatesList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates', options); - } - - /** - * Get project template by ID. - */ - templatesRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}`, options); - } - - /** - * Update project template. - */ - templatesUpdate( - id: string, - body: ProjectTemplatesUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); - } -} - -export interface ProjectAPIKeysCreateResponse { - data?: ProjectAPIKeysCreateResponse.Data; -} - -export namespace ProjectAPIKeysCreateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysListResponse { - data?: Array; -} - -export namespace ProjectAPIKeysListResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysRetrieveResponse { - data?: ProjectAPIKeysRetrieveResponse.Data; -} - -export namespace ProjectAPIKeysRetrieveResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysUpdateResponse { - data?: ProjectAPIKeysUpdateResponse.Data; -} - -export namespace ProjectAPIKeysUpdateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectCurrentListResponse { - data?: ProjectCurrentListResponse.Data; -} - -export namespace ProjectCurrentListResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface ProjectDomainsCreateResponse { - data?: ProjectDomainsCreateResponse.Data; -} - -export namespace ProjectDomainsCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsListResponse { - data?: Array; -} - -export namespace ProjectDomainsListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface ProjectDomainsRetrieveResponse { - data?: ProjectDomainsRetrieveResponse.Data; -} - -export namespace ProjectDomainsRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsUpdateResponse { - data?: ProjectDomainsUpdateResponse.Data; -} - -export namespace ProjectDomainsUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectTemplatesCreateResponse { - data?: ProjectTemplatesCreateResponse.Data; -} - -export namespace ProjectTemplatesCreateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesListResponse { - data?: Array; -} - -export namespace ProjectTemplatesListResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesRetrieveResponse { - data?: ProjectTemplatesRetrieveResponse.Data; -} - -export namespace ProjectTemplatesRetrieveResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesUpdateResponse { - data?: ProjectTemplatesUpdateResponse.Data; -} - -export namespace ProjectTemplatesUpdateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectAPIKeysCreateParams { - /** - * Name for the API key - */ - name: string; - - /** - * Allowed domains for this API key - */ - domains?: Array; -} - -export interface ProjectAPIKeysUpdateParams { - /** - * Whether the API key is active - */ - active?: boolean; - - /** - * Updated allowed domains - */ - domains?: Array; - - /** - * Updated name for the API key - */ - name?: string; -} - -export interface ProjectDomainsCreateParams { - /** - * Domain name to add - */ - domain: string; -} - -export interface ProjectDomainsUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export interface ProjectTemplatesCreateParams { - /** - * Template name - */ - name: string; - - /** - * Email body content - */ - body?: string; - - /** - * Email subject line - */ - subject?: string; -} - -export interface ProjectTemplatesUpdateParams { - /** - * Updated email body content - */ - body?: string; - - /** - * Updated template name - */ - name?: string; - - /** - * Updated email subject line - */ - subject?: string; -} - -export declare namespace Project { - export { - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; -} +export * from './project/index'; diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts new file mode 100644 index 0000000..94dc2ba --- /dev/null +++ b/src/resources/project/index.ts @@ -0,0 +1,46 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Project, + type ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse, + type ProjectDomainsCreateResponse, + type ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams, +} from './project'; +export { + V1, + type V1APIKeysCreateResponse, + type V1APIKeysListResponse, + type V1APIKeysRetrieveResponse, + type V1APIKeysUpdateResponse, + type V1CurrentListResponse, + type V1DomainsCreateResponse, + type V1DomainsListResponse, + type V1DomainsRetrieveResponse, + type V1DomainsUpdateResponse, + type V1TemplatesCreateResponse, + type V1TemplatesListResponse, + type V1TemplatesRetrieveResponse, + type V1TemplatesUpdateResponse, + type V1APIKeysCreateParams, + type V1APIKeysUpdateParams, + type V1DomainsCreateParams, + type V1DomainsUpdateParams, + type V1TemplatesCreateParams, + type V1TemplatesUpdateParams, +} from './v1'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts new file mode 100644 index 0000000..80e0cad --- /dev/null +++ b/src/resources/project/project.ts @@ -0,0 +1,566 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as V1API from './v1'; +import { + V1, + V1APIKeysCreateParams, + V1APIKeysCreateResponse, + V1APIKeysListResponse, + V1APIKeysRetrieveResponse, + V1APIKeysUpdateParams, + V1APIKeysUpdateResponse, + V1CurrentListResponse, + V1DomainsCreateParams, + V1DomainsCreateResponse, + V1DomainsListResponse, + V1DomainsRetrieveResponse, + V1DomainsUpdateParams, + V1DomainsUpdateResponse, + V1TemplatesCreateParams, + V1TemplatesCreateResponse, + V1TemplatesListResponse, + V1TemplatesRetrieveResponse, + V1TemplatesUpdateParams, + V1TemplatesUpdateResponse, +} from './v1'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Project extends APIResource { + v1: V1API.V1 = new V1API.V1(this._client); + + /** + * Create a new API key for the project. + */ + apiKeysCreate( + body: ProjectAPIKeysCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/api-keys', { body, ...options }); + } + + /** + * Revoke API key. + */ + apiKeysDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/api-keys/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all API keys for the project. + */ + apiKeysList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/api-keys', options); + } + + /** + * Get API key details by ID. + */ + apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/api-keys/${id}`, options); + } + + /** + * Update API key settings. + */ + apiKeysUpdate( + id: string, + body: ProjectAPIKeysUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); + } + + /** + * Get project details for the authenticated project. + */ + currentList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current', options); + } + + /** + * Add a new domain to the project. + */ + domainsCreate( + body: ProjectDomainsCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/domains', { body, ...options }); + } + + /** + * Remove domain from project. + */ + domainsDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all domains for the project. + */ + domainsList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains', options); + } + + /** + * Get domain details by ID. + */ + domainsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}`, options); + } + + /** + * Update domain settings. + */ + domainsUpdate( + id: string, + body: ProjectDomainsUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); + } + + /** + * Create a new project template. + */ + templatesCreate( + body: ProjectTemplatesCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/templates', { body, ...options }); + } + + /** + * Delete project template. + */ + templatesDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Get all project templates. + */ + templatesList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates', options); + } + + /** + * Get project template by ID. + */ + templatesRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}`, options); + } + + /** + * Update project template. + */ + templatesUpdate( + id: string, + body: ProjectTemplatesUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + } +} + +export interface ProjectAPIKeysCreateResponse { + data?: ProjectAPIKeysCreateResponse.Data; +} + +export namespace ProjectAPIKeysCreateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysListResponse { + data?: Array; +} + +export namespace ProjectAPIKeysListResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysRetrieveResponse { + data?: ProjectAPIKeysRetrieveResponse.Data; +} + +export namespace ProjectAPIKeysRetrieveResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysUpdateResponse { + data?: ProjectAPIKeysUpdateResponse.Data; +} + +export namespace ProjectAPIKeysUpdateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectCurrentListResponse { + data?: ProjectCurrentListResponse.Data; +} + +export namespace ProjectCurrentListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectDomainsCreateResponse { + data?: ProjectDomainsCreateResponse.Data; +} + +export namespace ProjectDomainsCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsListResponse { + data?: Array; +} + +export namespace ProjectDomainsListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface ProjectDomainsRetrieveResponse { + data?: ProjectDomainsRetrieveResponse.Data; +} + +export namespace ProjectDomainsRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsUpdateResponse { + data?: ProjectDomainsUpdateResponse.Data; +} + +export namespace ProjectDomainsUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectTemplatesCreateResponse { + data?: ProjectTemplatesCreateResponse.Data; +} + +export namespace ProjectTemplatesCreateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesListResponse { + data?: Array; +} + +export namespace ProjectTemplatesListResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesRetrieveResponse { + data?: ProjectTemplatesRetrieveResponse.Data; +} + +export namespace ProjectTemplatesRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesUpdateResponse { + data?: ProjectTemplatesUpdateResponse.Data; +} + +export namespace ProjectTemplatesUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectAPIKeysCreateParams { + /** + * Name for the API key + */ + name: string; + + /** + * Allowed domains for this API key + */ + domains?: Array; +} + +export interface ProjectAPIKeysUpdateParams { + /** + * Whether the API key is active + */ + active?: boolean; + + /** + * Updated allowed domains + */ + domains?: Array; + + /** + * Updated name for the API key + */ + name?: string; +} + +export interface ProjectDomainsCreateParams { + /** + * Domain name to add + */ + domain: string; +} + +export interface ProjectDomainsUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export interface ProjectTemplatesCreateParams { + /** + * Template name + */ + name: string; + + /** + * Email body content + */ + body?: string; + + /** + * Email subject line + */ + subject?: string; +} + +export interface ProjectTemplatesUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +Project.V1 = V1; + +export declare namespace Project { + export { + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; + + export { + V1 as V1, + type V1APIKeysCreateResponse as V1APIKeysCreateResponse, + type V1APIKeysListResponse as V1APIKeysListResponse, + type V1APIKeysRetrieveResponse as V1APIKeysRetrieveResponse, + type V1APIKeysUpdateResponse as V1APIKeysUpdateResponse, + type V1CurrentListResponse as V1CurrentListResponse, + type V1DomainsCreateResponse as V1DomainsCreateResponse, + type V1DomainsListResponse as V1DomainsListResponse, + type V1DomainsRetrieveResponse as V1DomainsRetrieveResponse, + type V1DomainsUpdateResponse as V1DomainsUpdateResponse, + type V1TemplatesCreateResponse as V1TemplatesCreateResponse, + type V1TemplatesListResponse as V1TemplatesListResponse, + type V1TemplatesRetrieveResponse as V1TemplatesRetrieveResponse, + type V1TemplatesUpdateResponse as V1TemplatesUpdateResponse, + type V1APIKeysCreateParams as V1APIKeysCreateParams, + type V1APIKeysUpdateParams as V1APIKeysUpdateParams, + type V1DomainsCreateParams as V1DomainsCreateParams, + type V1DomainsUpdateParams as V1DomainsUpdateParams, + type V1TemplatesCreateParams as V1TemplatesCreateParams, + type V1TemplatesUpdateParams as V1TemplatesUpdateParams, + }; +} diff --git a/src/resources/project-v1.ts b/src/resources/project/v1.ts similarity index 54% rename from src/resources/project-v1.ts rename to src/resources/project/v1.ts index d10168d..b9a7602 100644 --- a/src/resources/project-v1.ts +++ b/src/resources/project/v1.ts @@ -1,19 +1,16 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { buildHeaders } from '../internal/headers'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; -export class ProjectV1 extends APIResource { +export class V1 extends APIResource { /** * Create a new API key for the project. */ - apiKeysCreate( - body: ProjectV1APIKeysCreateParams, - options?: RequestOptions, - ): APIPromise { + apiKeysCreate(body: V1APIKeysCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/project/v1/api-keys', { body, ...options }); } @@ -30,14 +27,14 @@ export class ProjectV1 extends APIResource { /** * List all API keys for the project. */ - apiKeysList(options?: RequestOptions): APIPromise { + apiKeysList(options?: RequestOptions): APIPromise { return this._client.get('/project/v1/api-keys', options); } /** * Get API key details by ID. */ - apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { + apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/project/v1/api-keys/${id}`, options); } @@ -46,26 +43,23 @@ export class ProjectV1 extends APIResource { */ apiKeysUpdate( id: string, - body: ProjectV1APIKeysUpdateParams | null | undefined = {}, + body: V1APIKeysUpdateParams | null | undefined = {}, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); } /** * Get project details for the authenticated project. */ - currentList(options?: RequestOptions): APIPromise { + currentList(options?: RequestOptions): APIPromise { return this._client.get('/project/v1/current', options); } /** * Add a new domain to the project. */ - domainsCreate( - body: ProjectV1DomainsCreateParams, - options?: RequestOptions, - ): APIPromise { + domainsCreate(body: V1DomainsCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/project/v1/domains', { body, ...options }); } @@ -82,14 +76,14 @@ export class ProjectV1 extends APIResource { /** * List all domains for the project. */ - domainsList(options?: RequestOptions): APIPromise { + domainsList(options?: RequestOptions): APIPromise { return this._client.get('/project/v1/domains', options); } /** * Get domain details by ID. */ - domainsRetrieve(id: string, options?: RequestOptions): APIPromise { + domainsRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/project/v1/domains/${id}`, options); } @@ -98,9 +92,9 @@ export class ProjectV1 extends APIResource { */ domainsUpdate( id: string, - body: ProjectV1DomainsUpdateParams | null | undefined = {}, + body: V1DomainsUpdateParams | null | undefined = {}, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); } @@ -108,9 +102,9 @@ export class ProjectV1 extends APIResource { * Create a new project template. */ templatesCreate( - body: ProjectV1TemplatesCreateParams, + body: V1TemplatesCreateParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.post('/project/v1/templates', { body, ...options }); } @@ -127,14 +121,14 @@ export class ProjectV1 extends APIResource { /** * Get all project templates. */ - templatesList(options?: RequestOptions): APIPromise { + templatesList(options?: RequestOptions): APIPromise { return this._client.get('/project/v1/templates', options); } /** * Get project template by ID. */ - templatesRetrieve(id: string, options?: RequestOptions): APIPromise { + templatesRetrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/project/v1/templates/${id}`, options); } @@ -143,18 +137,18 @@ export class ProjectV1 extends APIResource { */ templatesUpdate( id: string, - body: ProjectV1TemplatesUpdateParams | null | undefined = {}, + body: V1TemplatesUpdateParams | null | undefined = {}, options?: RequestOptions, - ): APIPromise { + ): APIPromise { return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); } } -export interface ProjectV1APIKeysCreateResponse { - data?: ProjectV1APIKeysCreateResponse.Data; +export interface V1APIKeysCreateResponse { + data?: V1APIKeysCreateResponse.Data; } -export namespace ProjectV1APIKeysCreateResponse { +export namespace V1APIKeysCreateResponse { export interface Data { id?: string; @@ -170,11 +164,11 @@ export namespace ProjectV1APIKeysCreateResponse { } } -export interface ProjectV1APIKeysListResponse { - data?: Array; +export interface V1APIKeysListResponse { + data?: Array; } -export namespace ProjectV1APIKeysListResponse { +export namespace V1APIKeysListResponse { export interface Data { id?: string; @@ -192,11 +186,11 @@ export namespace ProjectV1APIKeysListResponse { } } -export interface ProjectV1APIKeysRetrieveResponse { - data?: ProjectV1APIKeysRetrieveResponse.Data; +export interface V1APIKeysRetrieveResponse { + data?: V1APIKeysRetrieveResponse.Data; } -export namespace ProjectV1APIKeysRetrieveResponse { +export namespace V1APIKeysRetrieveResponse { export interface Data { id?: string; @@ -214,11 +208,11 @@ export namespace ProjectV1APIKeysRetrieveResponse { } } -export interface ProjectV1APIKeysUpdateResponse { - data?: ProjectV1APIKeysUpdateResponse.Data; +export interface V1APIKeysUpdateResponse { + data?: V1APIKeysUpdateResponse.Data; } -export namespace ProjectV1APIKeysUpdateResponse { +export namespace V1APIKeysUpdateResponse { export interface Data { id?: string; @@ -236,11 +230,11 @@ export namespace ProjectV1APIKeysUpdateResponse { } } -export interface ProjectV1CurrentListResponse { - data?: ProjectV1CurrentListResponse.Data; +export interface V1CurrentListResponse { + data?: V1CurrentListResponse.Data; } -export namespace ProjectV1CurrentListResponse { +export namespace V1CurrentListResponse { export interface Data { id?: number; @@ -262,11 +256,11 @@ export namespace ProjectV1CurrentListResponse { } } -export interface ProjectV1DomainsCreateResponse { - data?: ProjectV1DomainsCreateResponse.Data; +export interface V1DomainsCreateResponse { + data?: V1DomainsCreateResponse.Data; } -export namespace ProjectV1DomainsCreateResponse { +export namespace V1DomainsCreateResponse { export interface Data { id?: string; @@ -280,11 +274,11 @@ export namespace ProjectV1DomainsCreateResponse { } } -export interface ProjectV1DomainsListResponse { - data?: Array; +export interface V1DomainsListResponse { + data?: Array; } -export namespace ProjectV1DomainsListResponse { +export namespace V1DomainsListResponse { export interface Data { id?: string; @@ -298,11 +292,11 @@ export namespace ProjectV1DomainsListResponse { } } -export interface ProjectV1DomainsRetrieveResponse { - data?: ProjectV1DomainsRetrieveResponse.Data; +export interface V1DomainsRetrieveResponse { + data?: V1DomainsRetrieveResponse.Data; } -export namespace ProjectV1DomainsRetrieveResponse { +export namespace V1DomainsRetrieveResponse { export interface Data { id?: string; @@ -316,11 +310,11 @@ export namespace ProjectV1DomainsRetrieveResponse { } } -export interface ProjectV1DomainsUpdateResponse { - data?: ProjectV1DomainsUpdateResponse.Data; +export interface V1DomainsUpdateResponse { + data?: V1DomainsUpdateResponse.Data; } -export namespace ProjectV1DomainsUpdateResponse { +export namespace V1DomainsUpdateResponse { export interface Data { id?: string; @@ -334,11 +328,11 @@ export namespace ProjectV1DomainsUpdateResponse { } } -export interface ProjectV1TemplatesCreateResponse { - data?: ProjectV1TemplatesCreateResponse.Data; +export interface V1TemplatesCreateResponse { + data?: V1TemplatesCreateResponse.Data; } -export namespace ProjectV1TemplatesCreateResponse { +export namespace V1TemplatesCreateResponse { export interface Data { id?: string; @@ -354,11 +348,11 @@ export namespace ProjectV1TemplatesCreateResponse { } } -export interface ProjectV1TemplatesListResponse { - data?: Array; +export interface V1TemplatesListResponse { + data?: Array; } -export namespace ProjectV1TemplatesListResponse { +export namespace V1TemplatesListResponse { export interface Data { id?: string; @@ -374,11 +368,11 @@ export namespace ProjectV1TemplatesListResponse { } } -export interface ProjectV1TemplatesRetrieveResponse { - data?: ProjectV1TemplatesRetrieveResponse.Data; +export interface V1TemplatesRetrieveResponse { + data?: V1TemplatesRetrieveResponse.Data; } -export namespace ProjectV1TemplatesRetrieveResponse { +export namespace V1TemplatesRetrieveResponse { export interface Data { id?: string; @@ -394,11 +388,11 @@ export namespace ProjectV1TemplatesRetrieveResponse { } } -export interface ProjectV1TemplatesUpdateResponse { - data?: ProjectV1TemplatesUpdateResponse.Data; +export interface V1TemplatesUpdateResponse { + data?: V1TemplatesUpdateResponse.Data; } -export namespace ProjectV1TemplatesUpdateResponse { +export namespace V1TemplatesUpdateResponse { export interface Data { id?: string; @@ -414,7 +408,7 @@ export namespace ProjectV1TemplatesUpdateResponse { } } -export interface ProjectV1APIKeysCreateParams { +export interface V1APIKeysCreateParams { /** * Name for the API key */ @@ -426,7 +420,7 @@ export interface ProjectV1APIKeysCreateParams { domains?: Array; } -export interface ProjectV1APIKeysUpdateParams { +export interface V1APIKeysUpdateParams { /** * Whether the API key is active */ @@ -443,21 +437,21 @@ export interface ProjectV1APIKeysUpdateParams { name?: string; } -export interface ProjectV1DomainsCreateParams { +export interface V1DomainsCreateParams { /** * Domain name to add */ domain: string; } -export interface ProjectV1DomainsUpdateParams { +export interface V1DomainsUpdateParams { /** * Updated domain name */ domain?: string; } -export interface ProjectV1TemplatesCreateParams { +export interface V1TemplatesCreateParams { /** * Template name */ @@ -474,7 +468,7 @@ export interface ProjectV1TemplatesCreateParams { subject?: string; } -export interface ProjectV1TemplatesUpdateParams { +export interface V1TemplatesUpdateParams { /** * Updated email body content */ @@ -491,26 +485,26 @@ export interface ProjectV1TemplatesUpdateParams { subject?: string; } -export declare namespace ProjectV1 { +export declare namespace V1 { export { - type ProjectV1APIKeysCreateResponse as ProjectV1APIKeysCreateResponse, - type ProjectV1APIKeysListResponse as ProjectV1APIKeysListResponse, - type ProjectV1APIKeysRetrieveResponse as ProjectV1APIKeysRetrieveResponse, - type ProjectV1APIKeysUpdateResponse as ProjectV1APIKeysUpdateResponse, - type ProjectV1CurrentListResponse as ProjectV1CurrentListResponse, - type ProjectV1DomainsCreateResponse as ProjectV1DomainsCreateResponse, - type ProjectV1DomainsListResponse as ProjectV1DomainsListResponse, - type ProjectV1DomainsRetrieveResponse as ProjectV1DomainsRetrieveResponse, - type ProjectV1DomainsUpdateResponse as ProjectV1DomainsUpdateResponse, - type ProjectV1TemplatesCreateResponse as ProjectV1TemplatesCreateResponse, - type ProjectV1TemplatesListResponse as ProjectV1TemplatesListResponse, - type ProjectV1TemplatesRetrieveResponse as ProjectV1TemplatesRetrieveResponse, - type ProjectV1TemplatesUpdateResponse as ProjectV1TemplatesUpdateResponse, - type ProjectV1APIKeysCreateParams as ProjectV1APIKeysCreateParams, - type ProjectV1APIKeysUpdateParams as ProjectV1APIKeysUpdateParams, - type ProjectV1DomainsCreateParams as ProjectV1DomainsCreateParams, - type ProjectV1DomainsUpdateParams as ProjectV1DomainsUpdateParams, - type ProjectV1TemplatesCreateParams as ProjectV1TemplatesCreateParams, - type ProjectV1TemplatesUpdateParams as ProjectV1TemplatesUpdateParams, + type V1APIKeysCreateResponse as V1APIKeysCreateResponse, + type V1APIKeysListResponse as V1APIKeysListResponse, + type V1APIKeysRetrieveResponse as V1APIKeysRetrieveResponse, + type V1APIKeysUpdateResponse as V1APIKeysUpdateResponse, + type V1CurrentListResponse as V1CurrentListResponse, + type V1DomainsCreateResponse as V1DomainsCreateResponse, + type V1DomainsListResponse as V1DomainsListResponse, + type V1DomainsRetrieveResponse as V1DomainsRetrieveResponse, + type V1DomainsUpdateResponse as V1DomainsUpdateResponse, + type V1TemplatesCreateResponse as V1TemplatesCreateResponse, + type V1TemplatesListResponse as V1TemplatesListResponse, + type V1TemplatesRetrieveResponse as V1TemplatesRetrieveResponse, + type V1TemplatesUpdateResponse as V1TemplatesUpdateResponse, + type V1APIKeysCreateParams as V1APIKeysCreateParams, + type V1APIKeysUpdateParams as V1APIKeysUpdateParams, + type V1DomainsCreateParams as V1DomainsCreateParams, + type V1DomainsUpdateParams as V1DomainsUpdateParams, + type V1TemplatesCreateParams as V1TemplatesCreateParams, + type V1TemplatesUpdateParams as V1TemplatesUpdateParams, }; } diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents/documents.test.ts similarity index 100% rename from tests/api-resources/documents.test.ts rename to tests/api-resources/documents/documents.test.ts diff --git a/tests/api-resources/documents-v1.test.ts b/tests/api-resources/documents/v1.test.ts similarity index 81% rename from tests/api-resources/documents-v1.test.ts rename to tests/api-resources/documents/v1.test.ts index dcd865c..950c539 100644 --- a/tests/api-resources/documents-v1.test.ts +++ b/tests/api-resources/documents/v1.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource documentsV1', () => { +describe('resource v1', () => { test('documentsRetrieve', async () => { - const responsePromise = client.documentsV1.documentsRetrieve('id'); + const responsePromise = client.documents.v1.documentsRetrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource documentsV1', () => { }); test('generateCreate: only required params', async () => { - const responsePromise = client.documentsV1.generateCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.documents.v1.generateCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -31,7 +31,7 @@ describe('resource documentsV1', () => { }); test('generateCreate: required and optional params', async () => { - const response = await client.documentsV1.generateCreate({ + const response = await client.documents.v1.generateCreate({ design: { counters: 'bar', body: 'bar' }, filename: 'filename', html: 'html', @@ -41,7 +41,7 @@ describe('resource documentsV1', () => { }); test('generateTemplateTemplate: only required params', async () => { - const responsePromise = client.documentsV1.generateTemplateTemplate({ templateId: 'templateId' }); + const responsePromise = client.documents.v1.generateTemplateTemplate({ templateId: 'templateId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -52,7 +52,7 @@ describe('resource documentsV1', () => { }); test('generateTemplateTemplate: required and optional params', async () => { - const response = await client.documentsV1.generateTemplateTemplate({ + const response = await client.documents.v1.generateTemplateTemplate({ templateId: 'templateId', filename: 'filename', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails/emails.test.ts similarity index 100% rename from tests/api-resources/emails.test.ts rename to tests/api-resources/emails/emails.test.ts diff --git a/tests/api-resources/emails-v1.test.ts b/tests/api-resources/emails/v1.test.ts similarity index 84% rename from tests/api-resources/emails-v1.test.ts rename to tests/api-resources/emails/v1.test.ts index 35e657d..02ab495 100644 --- a/tests/api-resources/emails-v1.test.ts +++ b/tests/api-resources/emails/v1.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource emailsV1', () => { +describe('resource v1', () => { test('emailsRetrieve', async () => { - const responsePromise = client.emailsV1.emailsRetrieve('id'); + const responsePromise = client.emails.v1.emailsRetrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource emailsV1', () => { }); test('renderCreate: only required params', async () => { - const responsePromise = client.emailsV1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.emails.v1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -31,14 +31,14 @@ describe('resource emailsV1', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.emailsV1.renderCreate({ + const response = await client.emails.v1.renderCreate({ design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); }); test('sendCreate: only required params', async () => { - const responsePromise = client.emailsV1.sendCreate({ + const responsePromise = client.emails.v1.sendCreate({ design: { counters: 'bar', body: 'bar' }, to: 'test@example.com', }); @@ -52,7 +52,7 @@ describe('resource emailsV1', () => { }); test('sendCreate: required and optional params', async () => { - const response = await client.emailsV1.sendCreate({ + const response = await client.emails.v1.sendCreate({ design: { counters: 'bar', body: 'bar' }, to: 'test@example.com', html: 'html', @@ -62,7 +62,7 @@ describe('resource emailsV1', () => { }); test('sendTemplateTemplate: only required params', async () => { - const responsePromise = client.emailsV1.sendTemplateTemplate({ + const responsePromise = client.emails.v1.sendTemplateTemplate({ templateId: 'templateId', to: 'dev@stainless.com', }); @@ -76,7 +76,7 @@ describe('resource emailsV1', () => { }); test('sendTemplateTemplate: required and optional params', async () => { - const response = await client.emailsV1.sendTemplateTemplate({ + const response = await client.emails.v1.sendTemplateTemplate({ templateId: 'templateId', to: 'dev@stainless.com', mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages/pages.test.ts similarity index 100% rename from tests/api-resources/pages.test.ts rename to tests/api-resources/pages/pages.test.ts diff --git a/tests/api-resources/pages-v1.test.ts b/tests/api-resources/pages/v1.test.ts similarity index 81% rename from tests/api-resources/pages-v1.test.ts rename to tests/api-resources/pages/v1.test.ts index db9031c..60abfeb 100644 --- a/tests/api-resources/pages-v1.test.ts +++ b/tests/api-resources/pages/v1.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource pagesV1', () => { +describe('resource v1', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pagesV1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.pages.v1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource pagesV1', () => { }); test('renderCreate: required and optional params', async () => { - const response = await client.pagesV1.renderCreate({ + const response = await client.pages.v1.renderCreate({ design: { counters: 'bar', body: 'bar' }, mergeTags: { foo: 'string' }, }); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project/project.test.ts similarity index 100% rename from tests/api-resources/project.test.ts rename to tests/api-resources/project/project.test.ts diff --git a/tests/api-resources/project-v1.test.ts b/tests/api-resources/project/v1.test.ts similarity index 84% rename from tests/api-resources/project-v1.test.ts rename to tests/api-resources/project/v1.test.ts index 8ec008d..809df1e 100644 --- a/tests/api-resources/project-v1.test.ts +++ b/tests/api-resources/project/v1.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource projectV1', () => { +describe('resource v1', () => { test('apiKeysCreate: only required params', async () => { - const responsePromise = client.projectV1.apiKeysCreate({ name: 'name' }); + const responsePromise = client.project.v1.apiKeysCreate({ name: 'name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,11 +20,11 @@ describe('resource projectV1', () => { }); test('apiKeysCreate: required and optional params', async () => { - const response = await client.projectV1.apiKeysCreate({ name: 'name', domains: ['string'] }); + const response = await client.project.v1.apiKeysCreate({ name: 'name', domains: ['string'] }); }); test('apiKeysDelete', async () => { - const responsePromise = client.projectV1.apiKeysDelete('id'); + const responsePromise = client.project.v1.apiKeysDelete('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -35,7 +35,7 @@ describe('resource projectV1', () => { }); test('apiKeysList', async () => { - const responsePromise = client.projectV1.apiKeysList(); + const responsePromise = client.project.v1.apiKeysList(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -46,7 +46,7 @@ describe('resource projectV1', () => { }); test('apiKeysRetrieve', async () => { - const responsePromise = client.projectV1.apiKeysRetrieve('id'); + const responsePromise = client.project.v1.apiKeysRetrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -57,7 +57,7 @@ describe('resource projectV1', () => { }); test('apiKeysUpdate', async () => { - const responsePromise = client.projectV1.apiKeysUpdate('id'); + const responsePromise = client.project.v1.apiKeysUpdate('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -70,7 +70,7 @@ describe('resource projectV1', () => { test('apiKeysUpdate: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.projectV1.apiKeysUpdate( + client.project.v1.apiKeysUpdate( 'id', { active: true, domains: ['string'], name: 'name' }, { path: '/_stainless_unknown_path' }, @@ -79,7 +79,7 @@ describe('resource projectV1', () => { }); test('currentList', async () => { - const responsePromise = client.projectV1.currentList(); + const responsePromise = client.project.v1.currentList(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -90,7 +90,7 @@ describe('resource projectV1', () => { }); test('domainsCreate: only required params', async () => { - const responsePromise = client.projectV1.domainsCreate({ domain: 'domain' }); + const responsePromise = client.project.v1.domainsCreate({ domain: 'domain' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -101,11 +101,11 @@ describe('resource projectV1', () => { }); test('domainsCreate: required and optional params', async () => { - const response = await client.projectV1.domainsCreate({ domain: 'domain' }); + const response = await client.project.v1.domainsCreate({ domain: 'domain' }); }); test('domainsDelete', async () => { - const responsePromise = client.projectV1.domainsDelete('id'); + const responsePromise = client.project.v1.domainsDelete('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -116,7 +116,7 @@ describe('resource projectV1', () => { }); test('domainsList', async () => { - const responsePromise = client.projectV1.domainsList(); + const responsePromise = client.project.v1.domainsList(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -127,7 +127,7 @@ describe('resource projectV1', () => { }); test('domainsRetrieve', async () => { - const responsePromise = client.projectV1.domainsRetrieve('id'); + const responsePromise = client.project.v1.domainsRetrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -138,7 +138,7 @@ describe('resource projectV1', () => { }); test('domainsUpdate', async () => { - const responsePromise = client.projectV1.domainsUpdate('id'); + const responsePromise = client.project.v1.domainsUpdate('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -151,12 +151,12 @@ describe('resource projectV1', () => { test('domainsUpdate: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.projectV1.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), + client.project.v1.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), ).rejects.toThrow(Unlayer.NotFoundError); }); test('templatesCreate: only required params', async () => { - const responsePromise = client.projectV1.templatesCreate({ name: 'name' }); + const responsePromise = client.project.v1.templatesCreate({ name: 'name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -167,7 +167,7 @@ describe('resource projectV1', () => { }); test('templatesCreate: required and optional params', async () => { - const response = await client.projectV1.templatesCreate({ + const response = await client.project.v1.templatesCreate({ name: 'name', body: 'body', subject: 'subject', @@ -175,7 +175,7 @@ describe('resource projectV1', () => { }); test('templatesDelete', async () => { - const responsePromise = client.projectV1.templatesDelete('id'); + const responsePromise = client.project.v1.templatesDelete('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -186,7 +186,7 @@ describe('resource projectV1', () => { }); test('templatesList', async () => { - const responsePromise = client.projectV1.templatesList(); + const responsePromise = client.project.v1.templatesList(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -197,7 +197,7 @@ describe('resource projectV1', () => { }); test('templatesRetrieve', async () => { - const responsePromise = client.projectV1.templatesRetrieve('id'); + const responsePromise = client.project.v1.templatesRetrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -208,7 +208,7 @@ describe('resource projectV1', () => { }); test('templatesUpdate', async () => { - const responsePromise = client.projectV1.templatesUpdate('id'); + const responsePromise = client.project.v1.templatesUpdate('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -221,7 +221,7 @@ describe('resource projectV1', () => { test('templatesUpdate: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.projectV1.templatesUpdate( + client.project.v1.templatesUpdate( 'id', { body: 'body', name: 'name', subject: 'subject' }, { path: '/_stainless_unknown_path' }, From 9dbbd3a33d9858a5bcb27113c80137ff5f92e0d2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 19:13:27 +0000 Subject: [PATCH 025/118] feat(api): api update --- .stats.yml | 2 +- api.md | 8 ++++---- src/client.ts | 4 ++-- src/resources/emails/emails.ts | 12 ++++++------ src/resources/emails/index.ts | 4 ++-- src/resources/emails/v1.ts | 10 ++++------ src/resources/index.ts | 2 +- tests/api-resources/emails/emails.test.ts | 4 ++-- tests/api-resources/emails/v1.test.ts | 4 ++-- 9 files changed, 24 insertions(+), 26 deletions(-) diff --git a/.stats.yml b/.stats.yml index b7a5fc0..27cd530 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d746e93c3c920dca97596edec38c9ec25feef644db419156ae1b538bb54b6d72.yml openapi_spec_hash: 437dce81b84c463ef9cc84dafa2ca92a -config_hash: 355cc7936ae5249f192357f93dab04c8 +config_hash: 89910371aa6d40f1ed85ee933924cf2e diff --git a/api.md b/api.md index e24871e..7231072 100644 --- a/api.md +++ b/api.md @@ -76,14 +76,14 @@ Methods: Types: -- EmailEmailsRetrieveResponse +- EmailRetrieveResponse - EmailRenderCreateResponse - EmailSendCreateResponse - EmailSendTemplateTemplateResponse Methods: -- client.emails.emailsRetrieve(id) -> EmailEmailsRetrieveResponse +- client.emails.retrieve(id) -> EmailRetrieveResponse - client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse - client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse - client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse @@ -92,14 +92,14 @@ Methods: Types: -- V1EmailsRetrieveResponse +- V1RetrieveResponse - V1RenderCreateResponse - V1SendCreateResponse - V1SendTemplateTemplateResponse Methods: -- client.emails.v1.emailsRetrieve(id) -> V1EmailsRetrieveResponse +- client.emails.v1.retrieve(id) -> V1RetrieveResponse - client.emails.v1.renderCreate({ ...params }) -> V1RenderCreateResponse - client.emails.v1.sendCreate({ ...params }) -> V1SendCreateResponse - client.emails.v1.sendTemplateTemplate({ ...params }) -> V1SendTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index c04de55..075a4a8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -25,9 +25,9 @@ import { Documents, } from './resources/documents/documents'; import { - EmailEmailsRetrieveResponse, EmailRenderCreateParams, EmailRenderCreateResponse, + EmailRetrieveResponse, EmailSendCreateParams, EmailSendCreateResponse, EmailSendTemplateTemplateParams, @@ -793,7 +793,7 @@ export declare namespace Unlayer { export { Emails as Emails, - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRetrieveResponse as EmailRetrieveResponse, type EmailRenderCreateResponse as EmailRenderCreateResponse, type EmailSendCreateResponse as EmailSendCreateResponse, type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts index fd0404f..f6796ce 100644 --- a/src/resources/emails/emails.ts +++ b/src/resources/emails/emails.ts @@ -4,9 +4,9 @@ import { APIResource } from '../../core/resource'; import * as V1API from './v1'; import { V1, - V1EmailsRetrieveResponse, V1RenderCreateParams, V1RenderCreateResponse, + V1RetrieveResponse, V1SendCreateParams, V1SendCreateResponse, V1SendTemplateTemplateParams, @@ -24,10 +24,10 @@ export class Emails extends APIResource { * * @example * ```ts - * const response = await client.emails.emailsRetrieve('id'); + * const email = await client.emails.retrieve('id'); * ``` */ - emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, options); } @@ -121,7 +121,7 @@ export class Emails extends APIResource { } } -export interface EmailEmailsRetrieveResponse { +export interface EmailRetrieveResponse { /** * Email message ID */ @@ -243,7 +243,7 @@ Emails.V1 = V1; export declare namespace Emails { export { - type EmailEmailsRetrieveResponse as EmailEmailsRetrieveResponse, + type EmailRetrieveResponse as EmailRetrieveResponse, type EmailRenderCreateResponse as EmailRenderCreateResponse, type EmailSendCreateResponse as EmailSendCreateResponse, type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, @@ -254,7 +254,7 @@ export declare namespace Emails { export { V1 as V1, - type V1EmailsRetrieveResponse as V1EmailsRetrieveResponse, + type V1RetrieveResponse as V1RetrieveResponse, type V1RenderCreateResponse as V1RenderCreateResponse, type V1SendCreateResponse as V1SendCreateResponse, type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts index e2e4c91..112875e 100644 --- a/src/resources/emails/index.ts +++ b/src/resources/emails/index.ts @@ -2,7 +2,7 @@ export { Emails, - type EmailEmailsRetrieveResponse, + type EmailRetrieveResponse, type EmailRenderCreateResponse, type EmailSendCreateResponse, type EmailSendTemplateTemplateResponse, @@ -12,7 +12,7 @@ export { } from './emails'; export { V1, - type V1EmailsRetrieveResponse, + type V1RetrieveResponse, type V1RenderCreateResponse, type V1SendCreateResponse, type V1SendTemplateTemplateResponse, diff --git a/src/resources/emails/v1.ts b/src/resources/emails/v1.ts index e35ba39..fe7b209 100644 --- a/src/resources/emails/v1.ts +++ b/src/resources/emails/v1.ts @@ -11,12 +11,10 @@ export class V1 extends APIResource { * * @example * ```ts - * const response = await client.emails.v1.emailsRetrieve( - * 'id', - * ); + * const v1 = await client.emails.v1.retrieve('id'); * ``` */ - emailsRetrieve(id: string, options?: RequestOptions): APIPromise { + retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, options); } @@ -108,7 +106,7 @@ export class V1 extends APIResource { } } -export interface V1EmailsRetrieveResponse { +export interface V1RetrieveResponse { /** * Email message ID */ @@ -228,7 +226,7 @@ export interface V1SendTemplateTemplateParams { export declare namespace V1 { export { - type V1EmailsRetrieveResponse as V1EmailsRetrieveResponse, + type V1RetrieveResponse as V1RetrieveResponse, type V1RenderCreateResponse as V1RenderCreateResponse, type V1SendCreateResponse as V1SendCreateResponse, type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index aee9e9e..6dbbf5f 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -10,7 +10,7 @@ export { } from './documents/documents'; export { Emails, - type EmailEmailsRetrieveResponse, + type EmailRetrieveResponse, type EmailRenderCreateResponse, type EmailSendCreateResponse, type EmailSendTemplateTemplateResponse, diff --git a/tests/api-resources/emails/emails.test.ts b/tests/api-resources/emails/emails.test.ts index 30a3ffd..6bed6cc 100644 --- a/tests/api-resources/emails/emails.test.ts +++ b/tests/api-resources/emails/emails.test.ts @@ -8,8 +8,8 @@ const client = new Unlayer({ }); describe('resource emails', () => { - test('emailsRetrieve', async () => { - const responsePromise = client.emails.emailsRetrieve('id'); + test('retrieve', async () => { + const responsePromise = client.emails.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/emails/v1.test.ts b/tests/api-resources/emails/v1.test.ts index 02ab495..a5b4a59 100644 --- a/tests/api-resources/emails/v1.test.ts +++ b/tests/api-resources/emails/v1.test.ts @@ -8,8 +8,8 @@ const client = new Unlayer({ }); describe('resource v1', () => { - test('emailsRetrieve', async () => { - const responsePromise = client.emails.v1.emailsRetrieve('id'); + test('retrieve', async () => { + const responsePromise = client.emails.v1.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; From ab92ed79ea49c58bf0474869bc8e8866085e542a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 08:08:06 +0000 Subject: [PATCH 026/118] feat(api): api update --- .stats.yml | 6 +- api.md | 169 ++---- src/client.ts | 34 +- src/resources/documents.ts | 209 ++++++- src/resources/documents/documents.ts | 232 ------- src/resources/documents/index.ts | 18 - src/resources/documents/v1.ts | 209 ------- src/resources/emails.ts | 238 +++++++- src/resources/emails/emails.ts | 265 -------- src/resources/emails/index.ts | 22 - src/resources/emails/v1.ts | 237 -------- src/resources/index.ts | 8 +- src/resources/pages.ts | 65 +- src/resources/pages/index.ts | 4 - src/resources/pages/pages.ts | 78 --- src/resources/pages/v1.ts | 66 -- src/resources/project.ts | 515 +++++++++++++++- src/resources/project/index.ts | 46 -- src/resources/project/project.ts | 566 ------------------ src/resources/project/v1.ts | 510 ---------------- .../{documents => }/documents.test.ts | 0 tests/api-resources/documents/v1.test.ts | 61 -- .../api-resources/{emails => }/emails.test.ts | 0 tests/api-resources/emails/v1.test.ts | 86 --- tests/api-resources/{pages => }/pages.test.ts | 0 tests/api-resources/pages/v1.test.ts | 28 - .../{project => }/project.test.ts | 0 tests/api-resources/project/v1.test.ts | 231 ------- 28 files changed, 1093 insertions(+), 2810 deletions(-) delete mode 100644 src/resources/documents/documents.ts delete mode 100644 src/resources/documents/index.ts delete mode 100644 src/resources/documents/v1.ts delete mode 100644 src/resources/emails/emails.ts delete mode 100644 src/resources/emails/index.ts delete mode 100644 src/resources/emails/v1.ts delete mode 100644 src/resources/pages/index.ts delete mode 100644 src/resources/pages/pages.ts delete mode 100644 src/resources/pages/v1.ts delete mode 100644 src/resources/project/index.ts delete mode 100644 src/resources/project/project.ts delete mode 100644 src/resources/project/v1.ts rename tests/api-resources/{documents => }/documents.test.ts (100%) delete mode 100644 tests/api-resources/documents/v1.test.ts rename tests/api-resources/{emails => }/emails.test.ts (100%) delete mode 100644 tests/api-resources/emails/v1.test.ts rename tests/api-resources/{pages => }/pages.test.ts (100%) delete mode 100644 tests/api-resources/pages/v1.test.ts rename tests/api-resources/{project => }/project.test.ts (100%) delete mode 100644 tests/api-resources/project/v1.test.ts diff --git a/.stats.yml b/.stats.yml index 27cd530..3b76cc0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d746e93c3c920dca97596edec38c9ec25feef644db419156ae1b538bb54b6d72.yml -openapi_spec_hash: 437dce81b84c463ef9cc84dafa2ca92a -config_hash: 89910371aa6d40f1ed85ee933924cf2e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-9942f4da50a072ed2feb0c1aa835272455da6a6e9a22b23d51f75c6002c9da64.yml +openapi_spec_hash: 19ba50f4ff2d2bb8b2a16a6083d1e1e9 +config_hash: 6d277064312d0ee93ce6df0eee354fa6 diff --git a/api.md b/api.md index 7231072..6b12218 100644 --- a/api.md +++ b/api.md @@ -2,152 +2,75 @@ Types: -- ProjectAPIKeysCreateResponse -- ProjectAPIKeysListResponse -- ProjectAPIKeysRetrieveResponse -- ProjectAPIKeysUpdateResponse -- ProjectCurrentListResponse -- ProjectDomainsCreateResponse -- ProjectDomainsListResponse -- ProjectDomainsRetrieveResponse -- ProjectDomainsUpdateResponse -- ProjectTemplatesCreateResponse -- ProjectTemplatesListResponse -- ProjectTemplatesRetrieveResponse -- ProjectTemplatesUpdateResponse +- ProjectAPIKeysCreateResponse +- ProjectAPIKeysListResponse +- ProjectAPIKeysRetrieveResponse +- ProjectAPIKeysUpdateResponse +- ProjectCurrentListResponse +- ProjectDomainsCreateResponse +- ProjectDomainsListResponse +- ProjectDomainsRetrieveResponse +- ProjectDomainsUpdateResponse +- ProjectTemplatesCreateResponse +- ProjectTemplatesListResponse +- ProjectTemplatesRetrieveResponse +- ProjectTemplatesUpdateResponse Methods: -- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse -- client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList() -> ProjectAPIKeysListResponse -- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse -- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse -- client.project.currentList() -> ProjectCurrentListResponse -- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse -- client.project.domainsDelete(id) -> void -- client.project.domainsList() -> ProjectDomainsListResponse -- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse -- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse -- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse -- client.project.templatesDelete(id) -> void -- client.project.templatesList() -> ProjectTemplatesListResponse -- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse -- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse - -## V1 - -Types: - -- V1APIKeysCreateResponse -- V1APIKeysListResponse -- V1APIKeysRetrieveResponse -- V1APIKeysUpdateResponse -- V1CurrentListResponse -- V1DomainsCreateResponse -- V1DomainsListResponse -- V1DomainsRetrieveResponse -- V1DomainsUpdateResponse -- V1TemplatesCreateResponse -- V1TemplatesListResponse -- V1TemplatesRetrieveResponse -- V1TemplatesUpdateResponse - -Methods: - -- client.project.v1.apiKeysCreate({ ...params }) -> V1APIKeysCreateResponse -- client.project.v1.apiKeysDelete(id) -> void -- client.project.v1.apiKeysList() -> V1APIKeysListResponse -- client.project.v1.apiKeysRetrieve(id) -> V1APIKeysRetrieveResponse -- client.project.v1.apiKeysUpdate(id, { ...params }) -> V1APIKeysUpdateResponse -- client.project.v1.currentList() -> V1CurrentListResponse -- client.project.v1.domainsCreate({ ...params }) -> V1DomainsCreateResponse -- client.project.v1.domainsDelete(id) -> void -- client.project.v1.domainsList() -> V1DomainsListResponse -- client.project.v1.domainsRetrieve(id) -> V1DomainsRetrieveResponse -- client.project.v1.domainsUpdate(id, { ...params }) -> V1DomainsUpdateResponse -- client.project.v1.templatesCreate({ ...params }) -> V1TemplatesCreateResponse -- client.project.v1.templatesDelete(id) -> void -- client.project.v1.templatesList() -> V1TemplatesListResponse -- client.project.v1.templatesRetrieve(id) -> V1TemplatesRetrieveResponse -- client.project.v1.templatesUpdate(id, { ...params }) -> V1TemplatesUpdateResponse - -# Emails - -Types: - -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - -## V1 - -Types: - -- V1RetrieveResponse -- V1RenderCreateResponse -- V1SendCreateResponse -- V1SendTemplateTemplateResponse - -Methods: - -- client.emails.v1.retrieve(id) -> V1RetrieveResponse -- client.emails.v1.renderCreate({ ...params }) -> V1RenderCreateResponse -- client.emails.v1.sendCreate({ ...params }) -> V1SendCreateResponse -- client.emails.v1.sendTemplateTemplate({ ...params }) -> V1SendTemplateTemplateResponse +- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse +- client.project.apiKeysDelete(id) -> void +- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse +- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse +- client.project.currentList() -> ProjectCurrentListResponse +- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse +- client.project.domainsDelete(id) -> void +- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse +- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse +- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse +- client.project.templatesDelete(id) -> void +- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse +- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse # Documents Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - -## V1 - -Types: - -- V1DocumentsRetrieveResponse -- V1GenerateCreateResponse -- V1GenerateTemplateTemplateResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.documents.v1.documentsRetrieve(id) -> V1DocumentsRetrieveResponse -- client.documents.v1.generateCreate({ ...params }) -> V1GenerateCreateResponse -- client.documents.v1.generateTemplateTemplate({ ...params }) -> V1GenerateTemplateTemplateResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse # Pages Types: -- PageRenderCreateResponse +- PageRenderCreateResponse Methods: -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse -## V1 +# Emails Types: -- V1RenderCreateResponse +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.pages.v1.renderCreate({ ...params }) -> V1RenderCreateResponse +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 075a4a8..83067e2 100644 --- a/src/client.ts +++ b/src/client.ts @@ -23,7 +23,7 @@ import { DocumentGenerateTemplateTemplateParams, DocumentGenerateTemplateTemplateResponse, Documents, -} from './resources/documents/documents'; +} from './resources/documents'; import { EmailRenderCreateParams, EmailRenderCreateResponse, @@ -33,8 +33,8 @@ import { EmailSendTemplateTemplateParams, EmailSendTemplateTemplateResponse, Emails, -} from './resources/emails/emails'; -import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages/pages'; +} from './resources/emails'; +import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages'; import { Project, ProjectAPIKeysCreateParams, @@ -56,7 +56,7 @@ import { ProjectTemplatesRetrieveResponse, ProjectTemplatesUpdateParams, ProjectTemplatesUpdateResponse, -} from './resources/project/project'; +} from './resources/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -755,15 +755,15 @@ export class Unlayer { static toFile = Uploads.toFile; project: API.Project = new API.Project(this); - emails: API.Emails = new API.Emails(this); documents: API.Documents = new API.Documents(this); pages: API.Pages = new API.Pages(this); + emails: API.Emails = new API.Emails(this); } Unlayer.Project = Project; -Unlayer.Emails = Emails; Unlayer.Documents = Documents; Unlayer.Pages = Pages; +Unlayer.Emails = Emails; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; @@ -791,17 +791,6 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { Documents as Documents, type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, @@ -816,4 +805,15 @@ export declare namespace Unlayer { type PageRenderCreateResponse as PageRenderCreateResponse, type PageRenderCreateParams as PageRenderCreateParams, }; + + export { + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; } diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 6dcfade..bb6b135 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -1,3 +1,210 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './documents/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Documents extends APIResource { + /** + * Retrieve details of a previously generated document. + * + * @example + * ```ts + * const response = await client.documents.documentsRetrieve( + * 'id', + * ); + * ``` + */ + documentsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, options); + } + + /** + * Generate PDF document from JSON design, HTML content, or URL. + * + * @example + * ```ts + * const response = await client.documents.generateCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + generateCreate( + body: DocumentGenerateCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate', { body, ...options }); + } + + /** + * Generate PDF document from an existing template with merge tags. + * + * @example + * ```ts + * const response = + * await client.documents.generateTemplateTemplate({ + * templateId: 'templateId', + * }); + * ``` + */ + generateTemplateTemplate( + body: DocumentGenerateTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/documents/v1/generate/template', { body, ...options }); + } +} + +export interface DocumentDocumentsRetrieveResponse { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateTemplateTemplateResponse { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; +} + +export interface DocumentGenerateCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * HTML content to convert to PDF + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * URL to convert to PDF + */ + url?: string; +} + +export interface DocumentGenerateTemplateTemplateParams { + /** + * ID of the template to use for generation + */ + templateId: string; + + /** + * Optional filename for the generated PDF + */ + filename?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Documents { + export { + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; +} diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts deleted file mode 100644 index ff05f41..0000000 --- a/src/resources/documents/documents.ts +++ /dev/null @@ -1,232 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1'; -import { - V1, - V1DocumentsRetrieveResponse, - V1GenerateCreateParams, - V1GenerateCreateResponse, - V1GenerateTemplateTemplateParams, - V1GenerateTemplateTemplateResponse, -} from './v1'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Documents extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); - - /** - * Retrieve details of a previously generated document. - * - * @example - * ```ts - * const response = await client.documents.documentsRetrieve( - * 'id', - * ); - * ``` - */ - documentsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, options); - } - - /** - * Generate PDF document from JSON design, HTML content, or URL. - * - * @example - * ```ts - * const response = await client.documents.generateCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - generateCreate( - body: DocumentGenerateCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate', { body, ...options }); - } - - /** - * Generate PDF document from an existing template with merge tags. - * - * @example - * ```ts - * const response = - * await client.documents.generateTemplateTemplate({ - * templateId: 'templateId', - * }); - * ``` - */ - generateTemplateTemplate( - body: DocumentGenerateTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate/template', { body, ...options }); - } -} - -export interface DocumentDocumentsRetrieveResponse { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateCreateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateTemplateTemplateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface DocumentGenerateCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * HTML content to convert to PDF - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * URL to convert to PDF - */ - url?: string; -} - -export interface DocumentGenerateTemplateTemplateParams { - /** - * ID of the template to use for generation - */ - templateId: string; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -Documents.V1 = V1; - -export declare namespace Documents { - export { - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; - - export { - V1 as V1, - type V1DocumentsRetrieveResponse as V1DocumentsRetrieveResponse, - type V1GenerateCreateResponse as V1GenerateCreateResponse, - type V1GenerateTemplateTemplateResponse as V1GenerateTemplateTemplateResponse, - type V1GenerateCreateParams as V1GenerateCreateParams, - type V1GenerateTemplateTemplateParams as V1GenerateTemplateTemplateParams, - }; -} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts deleted file mode 100644 index 5bbd657..0000000 --- a/src/resources/documents/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Documents, - type DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams, -} from './documents'; -export { - V1, - type V1DocumentsRetrieveResponse, - type V1GenerateCreateResponse, - type V1GenerateTemplateTemplateResponse, - type V1GenerateCreateParams, - type V1GenerateTemplateTemplateParams, -} from './v1'; diff --git a/src/resources/documents/v1.ts b/src/resources/documents/v1.ts deleted file mode 100644 index 85e4605..0000000 --- a/src/resources/documents/v1.ts +++ /dev/null @@ -1,209 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class V1 extends APIResource { - /** - * Retrieve details of a previously generated document. - * - * @example - * ```ts - * const response = - * await client.documents.v1.documentsRetrieve('id'); - * ``` - */ - documentsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, options); - } - - /** - * Generate PDF document from JSON design, HTML content, or URL. - * - * @example - * ```ts - * const response = await client.documents.v1.generateCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - generateCreate( - body: V1GenerateCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate', { body, ...options }); - } - - /** - * Generate PDF document from an existing template with merge tags. - * - * @example - * ```ts - * const response = - * await client.documents.v1.generateTemplateTemplate({ - * templateId: 'templateId', - * }); - * ``` - */ - generateTemplateTemplate( - body: V1GenerateTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/documents/v1/generate/template', { body, ...options }); - } -} - -export interface V1DocumentsRetrieveResponse { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; -} - -export interface V1GenerateCreateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface V1GenerateTemplateTemplateResponse { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; -} - -export interface V1GenerateCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * HTML content to convert to PDF - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * URL to convert to PDF - */ - url?: string; -} - -export interface V1GenerateTemplateTemplateParams { - /** - * ID of the template to use for generation - */ - templateId: string; - - /** - * Optional filename for the generated PDF - */ - filename?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace V1 { - export { - type V1DocumentsRetrieveResponse as V1DocumentsRetrieveResponse, - type V1GenerateCreateResponse as V1GenerateCreateResponse, - type V1GenerateTemplateTemplateResponse as V1GenerateTemplateTemplateResponse, - type V1GenerateCreateParams as V1GenerateCreateParams, - type V1GenerateTemplateTemplateParams as V1GenerateTemplateTemplateParams, - }; -} diff --git a/src/resources/emails.ts b/src/resources/emails.ts index bd0ec59..2bf993d 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -1,3 +1,239 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './emails/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Emails extends APIResource { + /** + * Retrieve details of a previously sent email. + * + * @example + * ```ts + * const email = await client.emails.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, options); + } + + /** + * Convert design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.emails.renderCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + renderCreate( + body: EmailRenderCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/render', { body, ...options }); + } + + /** + * Send email with design JSON or HTML content. + * + * @example + * ```ts + * const response = await client.emails.sendCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * to: 'test@example.com', + * subject: 'Test', + * }); + * ``` + */ + sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/emails/v1/send', { body, ...options }); + } + + /** + * Send email using an existing template with merge tags. + * + * @example + * ```ts + * const response = await client.emails.sendTemplateTemplate({ + * templateId: 'templateId', + * to: 'dev@stainless.com', + * }); + * ``` + */ + sendTemplateTemplate( + body: EmailSendTemplateTemplateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/emails/v1/send/template', { body, ...options }); + } +} + +export interface EmailRetrieveResponse { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; +} + +export interface EmailRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface EmailSendCreateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailSendTemplateTemplateResponse { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; +} + +export interface EmailRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export interface EmailSendCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Recipient email address + */ + to: string; + + /** + * HTML content to send + */ + html?: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line + */ + subject?: string; +} + +export interface EmailSendTemplateTemplateParams { + /** + * ID of the template to use + */ + templateId: string; + + /** + * Recipient email address + */ + to: string; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +export declare namespace Emails { + export { + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; +} diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts deleted file mode 100644 index f6796ce..0000000 --- a/src/resources/emails/emails.ts +++ /dev/null @@ -1,265 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1'; -import { - V1, - V1RenderCreateParams, - V1RenderCreateResponse, - V1RetrieveResponse, - V1SendCreateParams, - V1SendCreateResponse, - V1SendTemplateTemplateParams, - V1SendTemplateTemplateResponse, -} from './v1'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Emails extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); - - /** - * Retrieve details of a previously sent email. - * - * @example - * ```ts - * const email = await client.emails.retrieve('id'); - * ``` - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, options); - } - - /** - * Convert design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.emails.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate( - body: EmailRenderCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/render', { body, ...options }); - } - - /** - * Send email with design JSON or HTML content. - * - * @example - * ```ts - * const response = await client.emails.sendCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * to: 'test@example.com', - * subject: 'Test', - * }); - * ``` - */ - sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/send', { body, ...options }); - } - - /** - * Send email using an existing template with merge tags. - * - * @example - * ```ts - * const response = await client.emails.sendTemplateTemplate({ - * templateId: 'templateId', - * to: 'dev@stainless.com', - * }); - * ``` - */ - sendTemplateTemplate( - body: EmailSendTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/send/template', { body, ...options }); - } -} - -export interface EmailRetrieveResponse { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; -} - -export interface EmailRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface EmailSendCreateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface EmailSendTemplateTemplateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface EmailRenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export interface EmailSendCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Recipient email address - */ - to: string; - - /** - * HTML content to send - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line - */ - subject?: string; -} - -export interface EmailSendTemplateTemplateParams { - /** - * ID of the template to use - */ - templateId: string; - - /** - * Recipient email address - */ - to: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -Emails.V1 = V1; - -export declare namespace Emails { - export { - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - - export { - V1 as V1, - type V1RetrieveResponse as V1RetrieveResponse, - type V1RenderCreateResponse as V1RenderCreateResponse, - type V1SendCreateResponse as V1SendCreateResponse, - type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, - type V1RenderCreateParams as V1RenderCreateParams, - type V1SendCreateParams as V1SendCreateParams, - type V1SendTemplateTemplateParams as V1SendTemplateTemplateParams, - }; -} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts deleted file mode 100644 index 112875e..0000000 --- a/src/resources/emails/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Emails, - type EmailRetrieveResponse, - type EmailRenderCreateResponse, - type EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams, - type EmailSendCreateParams, - type EmailSendTemplateTemplateParams, -} from './emails'; -export { - V1, - type V1RetrieveResponse, - type V1RenderCreateResponse, - type V1SendCreateResponse, - type V1SendTemplateTemplateResponse, - type V1RenderCreateParams, - type V1SendCreateParams, - type V1SendTemplateTemplateParams, -} from './v1'; diff --git a/src/resources/emails/v1.ts b/src/resources/emails/v1.ts deleted file mode 100644 index fe7b209..0000000 --- a/src/resources/emails/v1.ts +++ /dev/null @@ -1,237 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class V1 extends APIResource { - /** - * Retrieve details of a previously sent email. - * - * @example - * ```ts - * const v1 = await client.emails.v1.retrieve('id'); - * ``` - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, options); - } - - /** - * Convert design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.emails.v1.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate(body: V1RenderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/render', { body, ...options }); - } - - /** - * Send email with design JSON or HTML content. - * - * @example - * ```ts - * const response = await client.emails.v1.sendCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * to: 'test@example.com', - * subject: 'Test', - * }); - * ``` - */ - sendCreate(body: V1SendCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/send', { body, ...options }); - } - - /** - * Send email using an existing template with merge tags. - * - * @example - * ```ts - * const response = - * await client.emails.v1.sendTemplateTemplate({ - * templateId: 'templateId', - * to: 'dev@stainless.com', - * }); - * ``` - */ - sendTemplateTemplate( - body: V1SendTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/emails/v1/send/template', { body, ...options }); - } -} - -export interface V1RetrieveResponse { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; -} - -export interface V1RenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface V1SendCreateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface V1SendTemplateTemplateResponse { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; -} - -export interface V1RenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export interface V1SendCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Recipient email address - */ - to: string; - - /** - * HTML content to send - */ - html?: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line - */ - subject?: string; -} - -export interface V1SendTemplateTemplateParams { - /** - * ID of the template to use - */ - templateId: string; - - /** - * Recipient email address - */ - to: string; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -export declare namespace V1 { - export { - type V1RetrieveResponse as V1RetrieveResponse, - type V1RenderCreateResponse as V1RenderCreateResponse, - type V1SendCreateResponse as V1SendCreateResponse, - type V1SendTemplateTemplateResponse as V1SendTemplateTemplateResponse, - type V1RenderCreateParams as V1RenderCreateParams, - type V1SendCreateParams as V1SendCreateParams, - type V1SendTemplateTemplateParams as V1SendTemplateTemplateParams, - }; -} diff --git a/src/resources/index.ts b/src/resources/index.ts index 6dbbf5f..2303117 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -7,7 +7,7 @@ export { type DocumentGenerateTemplateTemplateResponse, type DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams, -} from './documents/documents'; +} from './documents'; export { Emails, type EmailRetrieveResponse, @@ -17,8 +17,8 @@ export { type EmailRenderCreateParams, type EmailSendCreateParams, type EmailSendTemplateTemplateParams, -} from './emails/emails'; -export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages/pages'; +} from './emails'; +export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; export { Project, type ProjectAPIKeysCreateResponse, @@ -40,4 +40,4 @@ export { type ProjectDomainsUpdateParams, type ProjectTemplatesCreateParams, type ProjectTemplatesUpdateParams, -} from './project/project'; +} from './project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts index c218cbe..05af321 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -1,3 +1,66 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './pages/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class Pages extends APIResource { + /** + * Convert page design JSON to HTML with optional merge tags. + * + * @example + * ```ts + * const response = await client.pages.renderCreate({ + * design: { + * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * body: { + * rows: [ + * { + * cells: [1], + * columns: [ + * { + * contents: [ + * { + * type: 'text', + * values: { text: 'Hello World' }, + * }, + * ], + * }, + * ], + * }, + * ], + * }, + * }, + * }); + * ``` + */ + renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/pages/v1/render', { body, ...options }); + } +} + +export interface PageRenderCreateResponse { + /** + * Rendered HTML content + */ + html?: string; +} + +export interface PageRenderCreateParams { + /** + * Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Pages { + export { + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; +} diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts deleted file mode 100644 index 25cc7af..0000000 --- a/src/resources/pages/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; -export { V1, type V1RenderCreateResponse, type V1RenderCreateParams } from './v1'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts deleted file mode 100644 index 549a81a..0000000 --- a/src/resources/pages/pages.ts +++ /dev/null @@ -1,78 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1'; -import { V1, V1RenderCreateParams, V1RenderCreateResponse } from './v1'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Pages extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); - - /** - * Convert page design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.pages.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/pages/v1/render', { body, ...options }); - } -} - -export interface PageRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface PageRenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -Pages.V1 = V1; - -export declare namespace Pages { - export { - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - - export { - V1 as V1, - type V1RenderCreateResponse as V1RenderCreateResponse, - type V1RenderCreateParams as V1RenderCreateParams, - }; -} diff --git a/src/resources/pages/v1.ts b/src/resources/pages/v1.ts deleted file mode 100644 index d841749..0000000 --- a/src/resources/pages/v1.ts +++ /dev/null @@ -1,66 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class V1 extends APIResource { - /** - * Convert page design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.pages.v1.renderCreate({ - * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` - */ - renderCreate(body: V1RenderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/pages/v1/render', { body, ...options }); - } -} - -export interface V1RenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; -} - -export interface V1RenderCreateParams { - /** - * Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace V1 { - export { - type V1RenderCreateResponse as V1RenderCreateResponse, - type V1RenderCreateParams as V1RenderCreateParams, - }; -} diff --git a/src/resources/project.ts b/src/resources/project.ts index 60fc38d..70418cb 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -1,3 +1,516 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './project/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Project extends APIResource { + /** + * Create a new API key for the project. + */ + apiKeysCreate( + body: ProjectAPIKeysCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/api-keys', { body, ...options }); + } + + /** + * Revoke API key. + */ + apiKeysDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/api-keys/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all API keys for the project. + */ + apiKeysList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/api-keys', options); + } + + /** + * Get API key details by ID. + */ + apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/api-keys/${id}`, options); + } + + /** + * Update API key settings. + */ + apiKeysUpdate( + id: string, + body: ProjectAPIKeysUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); + } + + /** + * Get project details for the authenticated project. + */ + currentList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current', options); + } + + /** + * Add a new domain to the project. + */ + domainsCreate( + body: ProjectDomainsCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/domains', { body, ...options }); + } + + /** + * Remove domain from project. + */ + domainsDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * List all domains for the project. + */ + domainsList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains', options); + } + + /** + * Get domain details by ID. + */ + domainsRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}`, options); + } + + /** + * Update domain settings. + */ + domainsUpdate( + id: string, + body: ProjectDomainsUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); + } + + /** + * Create a new project template. + */ + templatesCreate( + body: ProjectTemplatesCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/project/v1/templates', { body, ...options }); + } + + /** + * Delete project template. + */ + templatesDelete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Get all project templates. + */ + templatesList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates', options); + } + + /** + * Get project template by ID. + */ + templatesRetrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}`, options); + } + + /** + * Update project template. + */ + templatesUpdate( + id: string, + body: ProjectTemplatesUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + } +} + +export interface ProjectAPIKeysCreateResponse { + data?: ProjectAPIKeysCreateResponse.Data; +} + +export namespace ProjectAPIKeysCreateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysListResponse { + data?: Array; +} + +export namespace ProjectAPIKeysListResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysRetrieveResponse { + data?: ProjectAPIKeysRetrieveResponse.Data; +} + +export namespace ProjectAPIKeysRetrieveResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectAPIKeysUpdateResponse { + data?: ProjectAPIKeysUpdateResponse.Data; +} + +export namespace ProjectAPIKeysUpdateResponse { + export interface Data { + id?: string; + + active?: boolean; + + createdAt?: string; + + domains?: Array; + + key?: string; + + lastUsed?: string; + + name?: string; + } +} + +export interface ProjectCurrentListResponse { + data?: ProjectCurrentListResponse.Data; +} + +export namespace ProjectCurrentListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectDomainsCreateResponse { + data?: ProjectDomainsCreateResponse.Data; +} + +export namespace ProjectDomainsCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsListResponse { + data?: Array; +} + +export namespace ProjectDomainsListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface ProjectDomainsRetrieveResponse { + data?: ProjectDomainsRetrieveResponse.Data; +} + +export namespace ProjectDomainsRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectDomainsUpdateResponse { + data?: ProjectDomainsUpdateResponse.Data; +} + +export namespace ProjectDomainsUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface ProjectTemplatesCreateResponse { + data?: ProjectTemplatesCreateResponse.Data; +} + +export namespace ProjectTemplatesCreateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesListResponse { + data?: Array; +} + +export namespace ProjectTemplatesListResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesRetrieveResponse { + data?: ProjectTemplatesRetrieveResponse.Data; +} + +export namespace ProjectTemplatesRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectTemplatesUpdateResponse { + data?: ProjectTemplatesUpdateResponse.Data; +} + +export namespace ProjectTemplatesUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface ProjectAPIKeysCreateParams { + /** + * Name for the API key + */ + name: string; + + /** + * Allowed domains for this API key + */ + domains?: Array; +} + +export interface ProjectAPIKeysUpdateParams { + /** + * Whether the API key is active + */ + active?: boolean; + + /** + * Updated allowed domains + */ + domains?: Array; + + /** + * Updated name for the API key + */ + name?: string; +} + +export interface ProjectDomainsCreateParams { + /** + * Domain name to add + */ + domain: string; +} + +export interface ProjectDomainsUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export interface ProjectTemplatesCreateParams { + /** + * Template name + */ + name: string; + + /** + * Email body content + */ + body?: string; + + /** + * Email subject line + */ + subject?: string; +} + +export interface ProjectTemplatesUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +export declare namespace Project { + export { + type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, + type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, + type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, + type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, + type ProjectCurrentListResponse as ProjectCurrentListResponse, + type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, + type ProjectDomainsListResponse as ProjectDomainsListResponse, + type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, + type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, + type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, + type ProjectTemplatesListResponse as ProjectTemplatesListResponse, + type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, + type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, + type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, + }; +} diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts deleted file mode 100644 index 94dc2ba..0000000 --- a/src/resources/project/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Project, - type ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse, - type ProjectCurrentListResponse, - type ProjectDomainsCreateResponse, - type ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse, - type ProjectAPIKeysCreateParams, - type ProjectAPIKeysUpdateParams, - type ProjectDomainsCreateParams, - type ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams, - type ProjectTemplatesUpdateParams, -} from './project'; -export { - V1, - type V1APIKeysCreateResponse, - type V1APIKeysListResponse, - type V1APIKeysRetrieveResponse, - type V1APIKeysUpdateResponse, - type V1CurrentListResponse, - type V1DomainsCreateResponse, - type V1DomainsListResponse, - type V1DomainsRetrieveResponse, - type V1DomainsUpdateResponse, - type V1TemplatesCreateResponse, - type V1TemplatesListResponse, - type V1TemplatesRetrieveResponse, - type V1TemplatesUpdateResponse, - type V1APIKeysCreateParams, - type V1APIKeysUpdateParams, - type V1DomainsCreateParams, - type V1DomainsUpdateParams, - type V1TemplatesCreateParams, - type V1TemplatesUpdateParams, -} from './v1'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts deleted file mode 100644 index 80e0cad..0000000 --- a/src/resources/project/project.ts +++ /dev/null @@ -1,566 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as V1API from './v1'; -import { - V1, - V1APIKeysCreateParams, - V1APIKeysCreateResponse, - V1APIKeysListResponse, - V1APIKeysRetrieveResponse, - V1APIKeysUpdateParams, - V1APIKeysUpdateResponse, - V1CurrentListResponse, - V1DomainsCreateParams, - V1DomainsCreateResponse, - V1DomainsListResponse, - V1DomainsRetrieveResponse, - V1DomainsUpdateParams, - V1DomainsUpdateResponse, - V1TemplatesCreateParams, - V1TemplatesCreateResponse, - V1TemplatesListResponse, - V1TemplatesRetrieveResponse, - V1TemplatesUpdateParams, - V1TemplatesUpdateResponse, -} from './v1'; -import { APIPromise } from '../../core/api-promise'; -import { buildHeaders } from '../../internal/headers'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Project extends APIResource { - v1: V1API.V1 = new V1API.V1(this._client); - - /** - * Create a new API key for the project. - */ - apiKeysCreate( - body: ProjectAPIKeysCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/api-keys', { body, ...options }); - } - - /** - * Revoke API key. - */ - apiKeysDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/api-keys/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all API keys for the project. - */ - apiKeysList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/api-keys', options); - } - - /** - * Get API key details by ID. - */ - apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/api-keys/${id}`, options); - } - - /** - * Update API key settings. - */ - apiKeysUpdate( - id: string, - body: ProjectAPIKeysUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); - } - - /** - * Get project details for the authenticated project. - */ - currentList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current', options); - } - - /** - * Add a new domain to the project. - */ - domainsCreate( - body: ProjectDomainsCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/domains', { body, ...options }); - } - - /** - * Remove domain from project. - */ - domainsDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all domains for the project. - */ - domainsList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains', options); - } - - /** - * Get domain details by ID. - */ - domainsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}`, options); - } - - /** - * Update domain settings. - */ - domainsUpdate( - id: string, - body: ProjectDomainsUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); - } - - /** - * Create a new project template. - */ - templatesCreate( - body: ProjectTemplatesCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/templates', { body, ...options }); - } - - /** - * Delete project template. - */ - templatesDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * Get all project templates. - */ - templatesList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates', options); - } - - /** - * Get project template by ID. - */ - templatesRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}`, options); - } - - /** - * Update project template. - */ - templatesUpdate( - id: string, - body: ProjectTemplatesUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); - } -} - -export interface ProjectAPIKeysCreateResponse { - data?: ProjectAPIKeysCreateResponse.Data; -} - -export namespace ProjectAPIKeysCreateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysListResponse { - data?: Array; -} - -export namespace ProjectAPIKeysListResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysRetrieveResponse { - data?: ProjectAPIKeysRetrieveResponse.Data; -} - -export namespace ProjectAPIKeysRetrieveResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysUpdateResponse { - data?: ProjectAPIKeysUpdateResponse.Data; -} - -export namespace ProjectAPIKeysUpdateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectCurrentListResponse { - data?: ProjectCurrentListResponse.Data; -} - -export namespace ProjectCurrentListResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface ProjectDomainsCreateResponse { - data?: ProjectDomainsCreateResponse.Data; -} - -export namespace ProjectDomainsCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsListResponse { - data?: Array; -} - -export namespace ProjectDomainsListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface ProjectDomainsRetrieveResponse { - data?: ProjectDomainsRetrieveResponse.Data; -} - -export namespace ProjectDomainsRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsUpdateResponse { - data?: ProjectDomainsUpdateResponse.Data; -} - -export namespace ProjectDomainsUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectTemplatesCreateResponse { - data?: ProjectTemplatesCreateResponse.Data; -} - -export namespace ProjectTemplatesCreateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesListResponse { - data?: Array; -} - -export namespace ProjectTemplatesListResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesRetrieveResponse { - data?: ProjectTemplatesRetrieveResponse.Data; -} - -export namespace ProjectTemplatesRetrieveResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesUpdateResponse { - data?: ProjectTemplatesUpdateResponse.Data; -} - -export namespace ProjectTemplatesUpdateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectAPIKeysCreateParams { - /** - * Name for the API key - */ - name: string; - - /** - * Allowed domains for this API key - */ - domains?: Array; -} - -export interface ProjectAPIKeysUpdateParams { - /** - * Whether the API key is active - */ - active?: boolean; - - /** - * Updated allowed domains - */ - domains?: Array; - - /** - * Updated name for the API key - */ - name?: string; -} - -export interface ProjectDomainsCreateParams { - /** - * Domain name to add - */ - domain: string; -} - -export interface ProjectDomainsUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export interface ProjectTemplatesCreateParams { - /** - * Template name - */ - name: string; - - /** - * Email body content - */ - body?: string; - - /** - * Email subject line - */ - subject?: string; -} - -export interface ProjectTemplatesUpdateParams { - /** - * Updated email body content - */ - body?: string; - - /** - * Updated template name - */ - name?: string; - - /** - * Updated email subject line - */ - subject?: string; -} - -Project.V1 = V1; - -export declare namespace Project { - export { - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; - - export { - V1 as V1, - type V1APIKeysCreateResponse as V1APIKeysCreateResponse, - type V1APIKeysListResponse as V1APIKeysListResponse, - type V1APIKeysRetrieveResponse as V1APIKeysRetrieveResponse, - type V1APIKeysUpdateResponse as V1APIKeysUpdateResponse, - type V1CurrentListResponse as V1CurrentListResponse, - type V1DomainsCreateResponse as V1DomainsCreateResponse, - type V1DomainsListResponse as V1DomainsListResponse, - type V1DomainsRetrieveResponse as V1DomainsRetrieveResponse, - type V1DomainsUpdateResponse as V1DomainsUpdateResponse, - type V1TemplatesCreateResponse as V1TemplatesCreateResponse, - type V1TemplatesListResponse as V1TemplatesListResponse, - type V1TemplatesRetrieveResponse as V1TemplatesRetrieveResponse, - type V1TemplatesUpdateResponse as V1TemplatesUpdateResponse, - type V1APIKeysCreateParams as V1APIKeysCreateParams, - type V1APIKeysUpdateParams as V1APIKeysUpdateParams, - type V1DomainsCreateParams as V1DomainsCreateParams, - type V1DomainsUpdateParams as V1DomainsUpdateParams, - type V1TemplatesCreateParams as V1TemplatesCreateParams, - type V1TemplatesUpdateParams as V1TemplatesUpdateParams, - }; -} diff --git a/src/resources/project/v1.ts b/src/resources/project/v1.ts deleted file mode 100644 index b9a7602..0000000 --- a/src/resources/project/v1.ts +++ /dev/null @@ -1,510 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { buildHeaders } from '../../internal/headers'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class V1 extends APIResource { - /** - * Create a new API key for the project. - */ - apiKeysCreate(body: V1APIKeysCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/project/v1/api-keys', { body, ...options }); - } - - /** - * Revoke API key. - */ - apiKeysDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/api-keys/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all API keys for the project. - */ - apiKeysList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/api-keys', options); - } - - /** - * Get API key details by ID. - */ - apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/api-keys/${id}`, options); - } - - /** - * Update API key settings. - */ - apiKeysUpdate( - id: string, - body: V1APIKeysUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); - } - - /** - * Get project details for the authenticated project. - */ - currentList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current', options); - } - - /** - * Add a new domain to the project. - */ - domainsCreate(body: V1DomainsCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/project/v1/domains', { body, ...options }); - } - - /** - * Remove domain from project. - */ - domainsDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all domains for the project. - */ - domainsList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains', options); - } - - /** - * Get domain details by ID. - */ - domainsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}`, options); - } - - /** - * Update domain settings. - */ - domainsUpdate( - id: string, - body: V1DomainsUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); - } - - /** - * Create a new project template. - */ - templatesCreate( - body: V1TemplatesCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/project/v1/templates', { body, ...options }); - } - - /** - * Delete project template. - */ - templatesDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * Get all project templates. - */ - templatesList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates', options); - } - - /** - * Get project template by ID. - */ - templatesRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}`, options); - } - - /** - * Update project template. - */ - templatesUpdate( - id: string, - body: V1TemplatesUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); - } -} - -export interface V1APIKeysCreateResponse { - data?: V1APIKeysCreateResponse.Data; -} - -export namespace V1APIKeysCreateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - name?: string; - } -} - -export interface V1APIKeysListResponse { - data?: Array; -} - -export namespace V1APIKeysListResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface V1APIKeysRetrieveResponse { - data?: V1APIKeysRetrieveResponse.Data; -} - -export namespace V1APIKeysRetrieveResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface V1APIKeysUpdateResponse { - data?: V1APIKeysUpdateResponse.Data; -} - -export namespace V1APIKeysUpdateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface V1CurrentListResponse { - data?: V1CurrentListResponse.Data; -} - -export namespace V1CurrentListResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface V1DomainsCreateResponse { - data?: V1DomainsCreateResponse.Data; -} - -export namespace V1DomainsCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface V1DomainsListResponse { - data?: Array; -} - -export namespace V1DomainsListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface V1DomainsRetrieveResponse { - data?: V1DomainsRetrieveResponse.Data; -} - -export namespace V1DomainsRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface V1DomainsUpdateResponse { - data?: V1DomainsUpdateResponse.Data; -} - -export namespace V1DomainsUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface V1TemplatesCreateResponse { - data?: V1TemplatesCreateResponse.Data; -} - -export namespace V1TemplatesCreateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface V1TemplatesListResponse { - data?: Array; -} - -export namespace V1TemplatesListResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface V1TemplatesRetrieveResponse { - data?: V1TemplatesRetrieveResponse.Data; -} - -export namespace V1TemplatesRetrieveResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface V1TemplatesUpdateResponse { - data?: V1TemplatesUpdateResponse.Data; -} - -export namespace V1TemplatesUpdateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface V1APIKeysCreateParams { - /** - * Name for the API key - */ - name: string; - - /** - * Allowed domains for this API key - */ - domains?: Array; -} - -export interface V1APIKeysUpdateParams { - /** - * Whether the API key is active - */ - active?: boolean; - - /** - * Updated allowed domains - */ - domains?: Array; - - /** - * Updated name for the API key - */ - name?: string; -} - -export interface V1DomainsCreateParams { - /** - * Domain name to add - */ - domain: string; -} - -export interface V1DomainsUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export interface V1TemplatesCreateParams { - /** - * Template name - */ - name: string; - - /** - * Email body content - */ - body?: string; - - /** - * Email subject line - */ - subject?: string; -} - -export interface V1TemplatesUpdateParams { - /** - * Updated email body content - */ - body?: string; - - /** - * Updated template name - */ - name?: string; - - /** - * Updated email subject line - */ - subject?: string; -} - -export declare namespace V1 { - export { - type V1APIKeysCreateResponse as V1APIKeysCreateResponse, - type V1APIKeysListResponse as V1APIKeysListResponse, - type V1APIKeysRetrieveResponse as V1APIKeysRetrieveResponse, - type V1APIKeysUpdateResponse as V1APIKeysUpdateResponse, - type V1CurrentListResponse as V1CurrentListResponse, - type V1DomainsCreateResponse as V1DomainsCreateResponse, - type V1DomainsListResponse as V1DomainsListResponse, - type V1DomainsRetrieveResponse as V1DomainsRetrieveResponse, - type V1DomainsUpdateResponse as V1DomainsUpdateResponse, - type V1TemplatesCreateResponse as V1TemplatesCreateResponse, - type V1TemplatesListResponse as V1TemplatesListResponse, - type V1TemplatesRetrieveResponse as V1TemplatesRetrieveResponse, - type V1TemplatesUpdateResponse as V1TemplatesUpdateResponse, - type V1APIKeysCreateParams as V1APIKeysCreateParams, - type V1APIKeysUpdateParams as V1APIKeysUpdateParams, - type V1DomainsCreateParams as V1DomainsCreateParams, - type V1DomainsUpdateParams as V1DomainsUpdateParams, - type V1TemplatesCreateParams as V1TemplatesCreateParams, - type V1TemplatesUpdateParams as V1TemplatesUpdateParams, - }; -} diff --git a/tests/api-resources/documents/documents.test.ts b/tests/api-resources/documents.test.ts similarity index 100% rename from tests/api-resources/documents/documents.test.ts rename to tests/api-resources/documents.test.ts diff --git a/tests/api-resources/documents/v1.test.ts b/tests/api-resources/documents/v1.test.ts deleted file mode 100644 index 950c539..0000000 --- a/tests/api-resources/documents/v1.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - test('documentsRetrieve', async () => { - const responsePromise = client.documents.v1.documentsRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('generateCreate: only required params', async () => { - const responsePromise = client.documents.v1.generateCreate({ design: { counters: 'bar', body: 'bar' } }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('generateCreate: required and optional params', async () => { - const response = await client.documents.v1.generateCreate({ - design: { counters: 'bar', body: 'bar' }, - filename: 'filename', - html: 'html', - mergeTags: { foo: 'string' }, - url: 'https://example.com', - }); - }); - - test('generateTemplateTemplate: only required params', async () => { - const responsePromise = client.documents.v1.generateTemplateTemplate({ templateId: 'templateId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('generateTemplateTemplate: required and optional params', async () => { - const response = await client.documents.v1.generateTemplateTemplate({ - templateId: 'templateId', - filename: 'filename', - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/emails/emails.test.ts b/tests/api-resources/emails.test.ts similarity index 100% rename from tests/api-resources/emails/emails.test.ts rename to tests/api-resources/emails.test.ts diff --git a/tests/api-resources/emails/v1.test.ts b/tests/api-resources/emails/v1.test.ts deleted file mode 100644 index a5b4a59..0000000 --- a/tests/api-resources/emails/v1.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - test('retrieve', async () => { - const responsePromise = client.emails.v1.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('renderCreate: only required params', async () => { - const responsePromise = client.emails.v1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('renderCreate: required and optional params', async () => { - const response = await client.emails.v1.renderCreate({ - design: { counters: 'bar', body: 'bar' }, - mergeTags: { foo: 'string' }, - }); - }); - - test('sendCreate: only required params', async () => { - const responsePromise = client.emails.v1.sendCreate({ - design: { counters: 'bar', body: 'bar' }, - to: 'test@example.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('sendCreate: required and optional params', async () => { - const response = await client.emails.v1.sendCreate({ - design: { counters: 'bar', body: 'bar' }, - to: 'test@example.com', - html: 'html', - mergeTags: { foo: 'string' }, - subject: 'Test', - }); - }); - - test('sendTemplateTemplate: only required params', async () => { - const responsePromise = client.emails.v1.sendTemplateTemplate({ - templateId: 'templateId', - to: 'dev@stainless.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('sendTemplateTemplate: required and optional params', async () => { - const response = await client.emails.v1.sendTemplateTemplate({ - templateId: 'templateId', - to: 'dev@stainless.com', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); - }); -}); diff --git a/tests/api-resources/pages/pages.test.ts b/tests/api-resources/pages.test.ts similarity index 100% rename from tests/api-resources/pages/pages.test.ts rename to tests/api-resources/pages.test.ts diff --git a/tests/api-resources/pages/v1.test.ts b/tests/api-resources/pages/v1.test.ts deleted file mode 100644 index 60abfeb..0000000 --- a/tests/api-resources/pages/v1.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - test('renderCreate: only required params', async () => { - const responsePromise = client.pages.v1.renderCreate({ design: { counters: 'bar', body: 'bar' } }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('renderCreate: required and optional params', async () => { - const response = await client.pages.v1.renderCreate({ - design: { counters: 'bar', body: 'bar' }, - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/project/project.test.ts b/tests/api-resources/project.test.ts similarity index 100% rename from tests/api-resources/project/project.test.ts rename to tests/api-resources/project.test.ts diff --git a/tests/api-resources/project/v1.test.ts b/tests/api-resources/project/v1.test.ts deleted file mode 100644 index 809df1e..0000000 --- a/tests/api-resources/project/v1.test.ts +++ /dev/null @@ -1,231 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource v1', () => { - test('apiKeysCreate: only required params', async () => { - const responsePromise = client.project.v1.apiKeysCreate({ name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysCreate: required and optional params', async () => { - const response = await client.project.v1.apiKeysCreate({ name: 'name', domains: ['string'] }); - }); - - test('apiKeysDelete', async () => { - const responsePromise = client.project.v1.apiKeysDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysList', async () => { - const responsePromise = client.project.v1.apiKeysList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysRetrieve', async () => { - const responsePromise = client.project.v1.apiKeysRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysUpdate', async () => { - const responsePromise = client.project.v1.apiKeysUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.apiKeysUpdate( - 'id', - { active: true, domains: ['string'], name: 'name' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - test('currentList', async () => { - const responsePromise = client.project.v1.currentList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsCreate: only required params', async () => { - const responsePromise = client.project.v1.domainsCreate({ domain: 'domain' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsCreate: required and optional params', async () => { - const response = await client.project.v1.domainsCreate({ domain: 'domain' }); - }); - - test('domainsDelete', async () => { - const responsePromise = client.project.v1.domainsDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsList', async () => { - const responsePromise = client.project.v1.domainsList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsRetrieve', async () => { - const responsePromise = client.project.v1.domainsRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsUpdate', async () => { - const responsePromise = client.project.v1.domainsUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - test('templatesCreate: only required params', async () => { - const responsePromise = client.project.v1.templatesCreate({ name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesCreate: required and optional params', async () => { - const response = await client.project.v1.templatesCreate({ - name: 'name', - body: 'body', - subject: 'subject', - }); - }); - - test('templatesDelete', async () => { - const responsePromise = client.project.v1.templatesDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesList', async () => { - const responsePromise = client.project.v1.templatesList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesRetrieve', async () => { - const responsePromise = client.project.v1.templatesRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesUpdate', async () => { - const responsePromise = client.project.v1.templatesUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.v1.templatesUpdate( - 'id', - { body: 'body', name: 'name', subject: 'subject' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); -}); From aded65fe44d6a1ee55994f89079154c5ef380378 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:59:58 +0000 Subject: [PATCH 027/118] feat(api): api update --- .stats.yml | 6 ++-- README.md | 2 ++ api.md | 32 ++++++++++----------- src/client.ts | 70 +++++++++++++++++++++++++++++++-------------- tests/index.test.ts | 13 +++++++++ 5 files changed, 82 insertions(+), 41 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3b76cc0..59b1ef8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-9942f4da50a072ed2feb0c1aa835272455da6a6e9a22b23d51f75c6002c9da64.yml -openapi_spec_hash: 19ba50f4ff2d2bb8b2a16a6083d1e1e9 -config_hash: 6d277064312d0ee93ce6df0eee354fa6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-737d922f62f9846af680567f50b999b1cec12674d24ae99e262ab1bcc0cbe311.yml +openapi_spec_hash: e1c7ddabf7b87df222fd4e268193d1dd +config_hash: 69225430c17187a9fea0a90e757affff diff --git a/README.md b/README.md index 2f826bf..4f7017f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted + environment: 'qa', // or 'production' | 'dev'; defaults to 'production' }); const response = await client.project.currentList(); @@ -44,6 +45,7 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted + environment: 'qa', // or 'production' | 'dev'; defaults to 'production' }); const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(); diff --git a/api.md b/api.md index 6b12218..0886115 100644 --- a/api.md +++ b/api.md @@ -35,19 +35,21 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# Documents +# Emails Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse # Pages @@ -59,18 +61,16 @@ Methods: - client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse -# Emails +# Documents Types: -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 83067e2..7c93139 100644 --- a/src/client.ts +++ b/src/client.ts @@ -70,12 +70,29 @@ import { } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; +const environments = { + production: 'https://api.unlayer.com', + qa: 'https://api.qa.unlayer.com', + dev: 'https://api.dev.unlayer.com', +}; +type Environment = keyof typeof environments; + export interface ClientOptions { /** * Defaults to process.env['UNLAYER_API_KEY']. */ apiKey?: string | undefined; + /** + * Specifies the environment to use for the API. + * + * Each environment maps to a different base URL: + * - `production` corresponds to `https://api.unlayer.com` + * - `qa` corresponds to `https://api.qa.unlayer.com` + * - `dev` corresponds to `https://api.dev.unlayer.com` + */ + environment?: Environment | undefined; + /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" * @@ -167,6 +184,7 @@ export class Unlayer { * API Client for interfacing with the Unlayer API. * * @param {string | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? undefined] + * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -189,10 +207,17 @@ export class Unlayer { const options: ClientOptions = { apiKey, ...opts, - baseURL: baseURL || `https://api.unlayer.com`, + baseURL, + environment: opts.environment ?? 'production', }; - this.baseURL = options.baseURL!; + if (baseURL && opts.environment) { + throw new Errors.UnlayerError( + 'Ambiguous URL; The `baseURL` option (or UNLAYER_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null', + ); + } + + this.baseURL = options.baseURL || environments[options.environment || 'production']; this.timeout = options.timeout ?? Unlayer.DEFAULT_TIMEOUT /* 1 minute */; this.logger = options.logger ?? console; const defaultLogLevel = 'warn'; @@ -218,7 +243,8 @@ export class Unlayer { withOptions(options: Partial): this { const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({ ...this._options, - baseURL: this.baseURL, + environment: options.environment ? options.environment : undefined, + baseURL: options.environment ? undefined : this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, @@ -235,7 +261,7 @@ export class Unlayer { * Check whether the base URL is set to its default. */ #baseURLOverridden(): boolean { - return this.baseURL !== 'https://api.unlayer.com'; + return this.baseURL !== environments[this._options.environment || 'production']; } protected defaultQuery(): Record | undefined { @@ -755,15 +781,15 @@ export class Unlayer { static toFile = Uploads.toFile; project: API.Project = new API.Project(this); - documents: API.Documents = new API.Documents(this); - pages: API.Pages = new API.Pages(this); emails: API.Emails = new API.Emails(this); + pages: API.Pages = new API.Pages(this); + documents: API.Documents = new API.Documents(this); } Unlayer.Project = Project; -Unlayer.Documents = Documents; -Unlayer.Pages = Pages; Unlayer.Emails = Emails; +Unlayer.Pages = Pages; +Unlayer.Documents = Documents; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; @@ -792,12 +818,14 @@ export declare namespace Unlayer { }; export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; export { @@ -807,13 +835,11 @@ export declare namespace Unlayer { }; export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; } diff --git a/tests/index.test.ts b/tests/index.test.ts index df8dca4..41ff21b 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -311,6 +311,19 @@ describe('instantiate client', () => { expect(client.baseURL).toEqual('https://api.unlayer.com'); }); + test('env variable with environment', () => { + process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; + + expect( + () => new Unlayer({ apiKey: 'My API Key', environment: 'production' }), + ).toThrowErrorMatchingInlineSnapshot( + `"Ambiguous URL; The \`baseURL\` option (or UNLAYER_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, + ); + + const client = new Unlayer({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); + expect(client.baseURL).toEqual('https://api.unlayer.com'); + }); + test('in request options', () => { const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( From 097175bee95a1ae3b2d9ca2e0e36edc0bfe87226 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 09:14:24 +0000 Subject: [PATCH 028/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 46 +++++++++++++++++++++++----------------------- src/client.ts | 42 +++++++++++++++++++++--------------------- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/.stats.yml b/.stats.yml index 59b1ef8..2e5df92 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-737d922f62f9846af680567f50b999b1cec12674d24ae99e262ab1bcc0cbe311.yml -openapi_spec_hash: e1c7ddabf7b87df222fd4e268193d1dd -config_hash: 69225430c17187a9fea0a90e757affff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml +openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e +config_hash: 4700894a8daff98f13b4480d5d3e2bed diff --git a/api.md b/api.md index 0886115..3f1beb1 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,19 @@ +# Emails + +Types: + +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # Project Types: @@ -35,21 +51,19 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# Emails +# Documents Types: -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse Methods: -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse # Pages @@ -60,17 +74,3 @@ Types: Methods: - client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 7c93139..8431dfb 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,20 +780,31 @@ export class Unlayer { static toFile = Uploads.toFile; - project: API.Project = new API.Project(this); emails: API.Emails = new API.Emails(this); - pages: API.Pages = new API.Pages(this); + project: API.Project = new API.Project(this); documents: API.Documents = new API.Documents(this); + pages: API.Pages = new API.Pages(this); } -Unlayer.Project = Project; Unlayer.Emails = Emails; -Unlayer.Pages = Pages; +Unlayer.Project = Project; Unlayer.Documents = Documents; +Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -817,23 +828,6 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - export { Documents as Documents, type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, @@ -842,4 +836,10 @@ export declare namespace Unlayer { type DocumentGenerateCreateParams as DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; } From 76c09a1646b7a6c231452f9ea158f736a23bb50d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:20:13 +0000 Subject: [PATCH 029/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 48 ++++++++++++++++++++++++------------------------ src/client.ts | 38 +++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2e5df92..8c69178 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml -openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e -config_hash: 4700894a8daff98f13b4480d5d3e2bed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-8e523084a4299d49f71a9dd36232b00a4f3f4c5a94d2b95f118d54a49184595f.yml +openapi_spec_hash: 16e58acb9377ae565449741fce8857ea +config_hash: 6e7ac0b0bf24c892c17a4773cfdfbadc diff --git a/api.md b/api.md index 3f1beb1..56eed0e 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,27 @@ +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse + +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + # Emails Types: @@ -50,27 +74,3 @@ Methods: - client.project.templatesList() -> ProjectTemplatesListResponse - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/src/client.ts b/src/client.ts index 8431dfb..6a9f02d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,20 +780,35 @@ export class Unlayer { static toFile = Uploads.toFile; + pages: API.Pages = new API.Pages(this); + documents: API.Documents = new API.Documents(this); emails: API.Emails = new API.Emails(this); project: API.Project = new API.Project(this); - documents: API.Documents = new API.Documents(this); - pages: API.Pages = new API.Pages(this); } +Unlayer.Pages = Pages; +Unlayer.Documents = Documents; Unlayer.Emails = Emails; Unlayer.Project = Project; -Unlayer.Documents = Documents; -Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + export { Emails as Emails, type EmailRetrieveResponse as EmailRetrieveResponse, @@ -827,19 +842,4 @@ export declare namespace Unlayer { type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - - export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; } From dc31c16938f2257e2be9bd7871039a6b5c21a9e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:31:45 +0000 Subject: [PATCH 030/118] chore(internal): codegen related update --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 42d0669..82bf563 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Unlayer + Copyright 2026 Unlayer Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From bc83a450dd8610ea90ffb91662ef3ba25ec03e2d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 09:00:57 +0000 Subject: [PATCH 031/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 48 ++++++++++++++++++++++++------------------------ src/client.ts | 38 +++++++++++++++++++------------------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8c69178..2e5df92 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-8e523084a4299d49f71a9dd36232b00a4f3f4c5a94d2b95f118d54a49184595f.yml -openapi_spec_hash: 16e58acb9377ae565449741fce8857ea -config_hash: 6e7ac0b0bf24c892c17a4773cfdfbadc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml +openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e +config_hash: 4700894a8daff98f13b4480d5d3e2bed diff --git a/api.md b/api.md index 56eed0e..3f1beb1 100644 --- a/api.md +++ b/api.md @@ -1,27 +1,3 @@ -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - # Emails Types: @@ -74,3 +50,27 @@ Methods: - client.project.templatesList() -> ProjectTemplatesListResponse - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse + +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/src/client.ts b/src/client.ts index 6a9f02d..8431dfb 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,35 +780,20 @@ export class Unlayer { static toFile = Uploads.toFile; - pages: API.Pages = new API.Pages(this); - documents: API.Documents = new API.Documents(this); emails: API.Emails = new API.Emails(this); project: API.Project = new API.Project(this); + documents: API.Documents = new API.Documents(this); + pages: API.Pages = new API.Pages(this); } -Unlayer.Pages = Pages; -Unlayer.Documents = Documents; Unlayer.Emails = Emails; Unlayer.Project = Project; +Unlayer.Documents = Documents; +Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - - export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; - export { Emails as Emails, type EmailRetrieveResponse as EmailRetrieveResponse, @@ -842,4 +827,19 @@ export declare namespace Unlayer { type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; } From ecda66d2cca99d8581de9f2b564f23cbedaf4800 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 03:38:24 +0000 Subject: [PATCH 032/118] chore: break long lines in snippets into multiline --- src/resources/documents.ts | 6 ++- src/resources/emails.ts | 12 ++++- src/resources/pages.ts | 6 ++- tests/api-resources/project.test.ts | 18 ++++++-- tests/index.test.ts | 72 ++++++++++++++++++++++++----- 5 files changed, 95 insertions(+), 19 deletions(-) diff --git a/src/resources/documents.ts b/src/resources/documents.ts index bb6b135..594d3f0 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -27,7 +27,11 @@ export class Documents extends APIResource { * ```ts * const response = await client.documents.generateCreate({ * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * counters: { + * u_row: 1, + * u_column: 1, + * u_content_text: 1, + * }, * body: { * rows: [ * { diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 2bf993d..4972627 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -25,7 +25,11 @@ export class Emails extends APIResource { * ```ts * const response = await client.emails.renderCreate({ * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * counters: { + * u_row: 1, + * u_column: 1, + * u_content_text: 1, + * }, * body: { * rows: [ * { @@ -61,7 +65,11 @@ export class Emails extends APIResource { * ```ts * const response = await client.emails.sendCreate({ * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * counters: { + * u_row: 1, + * u_column: 1, + * u_content_text: 1, + * }, * body: { * rows: [ * { diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 05af321..04ff5cf 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -12,7 +12,11 @@ export class Pages extends APIResource { * ```ts * const response = await client.pages.renderCreate({ * design: { - * counters: { u_row: 1, u_column: 1, u_content_text: 1 }, + * counters: { + * u_row: 1, + * u_column: 1, + * u_content_text: 1, + * }, * body: { * rows: [ * { diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts index c6b96c3..ec5105a 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/project.test.ts @@ -72,7 +72,11 @@ describe('resource project', () => { await expect( client.project.apiKeysUpdate( 'id', - { active: true, domains: ['string'], name: 'name' }, + { + active: true, + domains: ['string'], + name: 'name', + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Unlayer.NotFoundError); @@ -167,7 +171,11 @@ describe('resource project', () => { }); test('templatesCreate: required and optional params', async () => { - const response = await client.project.templatesCreate({ name: 'name', body: 'body', subject: 'subject' }); + const response = await client.project.templatesCreate({ + name: 'name', + body: 'body', + subject: 'subject', + }); }); test('templatesDelete', async () => { @@ -219,7 +227,11 @@ describe('resource project', () => { await expect( client.project.templatesUpdate( 'id', - { body: 'body', name: 'name', subject: 'subject' }, + { + body: 'body', + name: 'name', + subject: 'subject', + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Unlayer.NotFoundError); diff --git a/tests/index.test.ts b/tests/index.test.ts index 41ff21b..c1ab24a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -87,7 +87,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Unlayer({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).toHaveBeenCalled(); @@ -107,7 +111,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Unlayer({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + const client = new Unlayer({ + logger: logger, + logLevel: 'info', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -157,7 +165,11 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + const client = new Unlayer({ + logger: logger, + logLevel: 'off', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -173,7 +185,11 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Unlayer({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); }); @@ -267,7 +283,11 @@ describe('instantiate client', () => { return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: testFetch, + }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -320,7 +340,11 @@ describe('instantiate client', () => { `"Ambiguous URL; The \`baseURL\` option (or UNLAYER_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, ); - const client = new Unlayer({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); + const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: null, + environment: 'production', + }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); @@ -358,7 +382,11 @@ describe('instantiate client', () => { describe('withOptions', () => { test('creates a new client with overridden options', async () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + maxRetries: 3, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ maxRetries: 5, @@ -398,7 +426,11 @@ describe('instantiate client', () => { }); test('respects runtime property changes when creating new client', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/', + timeout: 1000, + apiKey: 'My API Key', + }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -544,7 +576,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + const client = new Unlayer({ + apiKey: 'My API Key', + timeout: 10, + fetch: testFetch, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -574,7 +610,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -598,7 +638,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -660,7 +704,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Unlayer({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ From 03a7570811d4cd286f58757cc5f089036e215c29 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 02:30:28 +0000 Subject: [PATCH 033/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 46 +++++++++++++++++++++++----------------------- src/client.ts | 42 +++++++++++++++++++++--------------------- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2e5df92..59b1ef8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-7b157ae796e7fc651848e8626a9adb4b00614a203c5140530edb0c52f5c82f79.yml -openapi_spec_hash: 00ccd8fc07a13e525a6fc1af6445230e -config_hash: 4700894a8daff98f13b4480d5d3e2bed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-737d922f62f9846af680567f50b999b1cec12674d24ae99e262ab1bcc0cbe311.yml +openapi_spec_hash: e1c7ddabf7b87df222fd4e268193d1dd +config_hash: 69225430c17187a9fea0a90e757affff diff --git a/api.md b/api.md index 3f1beb1..0886115 100644 --- a/api.md +++ b/api.md @@ -1,19 +1,3 @@ -# Emails - -Types: - -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - # Project Types: @@ -51,19 +35,21 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# Documents +# Emails Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse Methods: -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse # Pages @@ -74,3 +60,17 @@ Types: Methods: - client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse + +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 8431dfb..7c93139 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,31 +780,20 @@ export class Unlayer { static toFile = Uploads.toFile; - emails: API.Emails = new API.Emails(this); project: API.Project = new API.Project(this); - documents: API.Documents = new API.Documents(this); + emails: API.Emails = new API.Emails(this); pages: API.Pages = new API.Pages(this); + documents: API.Documents = new API.Documents(this); } -Unlayer.Emails = Emails; Unlayer.Project = Project; -Unlayer.Documents = Documents; +Unlayer.Emails = Emails; Unlayer.Pages = Pages; +Unlayer.Documents = Documents; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -829,12 +818,14 @@ export declare namespace Unlayer { }; export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; export { @@ -842,4 +833,13 @@ export declare namespace Unlayer { type PageRenderCreateResponse as PageRenderCreateResponse, type PageRenderCreateParams as PageRenderCreateParams, }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; } From 493bd0bdd9e369aa19f4b96b5ead65b6497205f4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 22:18:54 +0000 Subject: [PATCH 034/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 52 +++++++++++++++++++++++++-------------------------- src/client.ts | 42 ++++++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/.stats.yml b/.stats.yml index 59b1ef8..5fdc6f9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-737d922f62f9846af680567f50b999b1cec12674d24ae99e262ab1bcc0cbe311.yml -openapi_spec_hash: e1c7ddabf7b87df222fd4e268193d1dd -config_hash: 69225430c17187a9fea0a90e757affff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4d5fbaaec8cf4a1c283a9f901d09ebf13663fec824e68284f3aee09a861eb935.yml +openapi_spec_hash: 080ea72a1cecdca3399da83c5a9bfdd9 +config_hash: 22a4c98e4582bc0dddb1b2ae42fbccd0 diff --git a/api.md b/api.md index 0886115..238476a 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,29 @@ +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse + +# Emails + +Types: + +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # Project Types: @@ -35,32 +61,6 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -# Emails - -Types: - -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - # Documents Types: diff --git a/src/client.ts b/src/client.ts index 7c93139..888b45d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,20 +780,37 @@ export class Unlayer { static toFile = Uploads.toFile; - project: API.Project = new API.Project(this); - emails: API.Emails = new API.Emails(this); pages: API.Pages = new API.Pages(this); + emails: API.Emails = new API.Emails(this); + project: API.Project = new API.Project(this); documents: API.Documents = new API.Documents(this); } -Unlayer.Project = Project; -Unlayer.Emails = Emails; Unlayer.Pages = Pages; +Unlayer.Emails = Emails; +Unlayer.Project = Project; Unlayer.Documents = Documents; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; + + export { + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -817,23 +834,6 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - export { Documents as Documents, type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, From d66fda98bd73eae7a967f85ccd6ad66a1b9473f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:39:06 +0000 Subject: [PATCH 035/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 52 +++++++++++++++++++++++++-------------------------- src/client.ts | 42 ++++++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5fdc6f9..74b0b57 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-4d5fbaaec8cf4a1c283a9f901d09ebf13663fec824e68284f3aee09a861eb935.yml -openapi_spec_hash: 080ea72a1cecdca3399da83c5a9bfdd9 -config_hash: 22a4c98e4582bc0dddb1b2ae42fbccd0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d746e93c3c920dca97596edec38c9ec25feef644db419156ae1b538bb54b6d72.yml +openapi_spec_hash: 437dce81b84c463ef9cc84dafa2ca92a +config_hash: 7495c5f2aebb250bf705cf2e6f4c1205 diff --git a/api.md b/api.md index 238476a..cc088f5 100644 --- a/api.md +++ b/api.md @@ -1,29 +1,3 @@ -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - -# Emails - -Types: - -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse - -Methods: - -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse - # Project Types: @@ -61,6 +35,22 @@ Methods: - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse +# Emails + +Types: + +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # Documents Types: @@ -74,3 +64,13 @@ Methods: - client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse - client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse - client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/src/client.ts b/src/client.ts index 888b45d..e645c47 100644 --- a/src/client.ts +++ b/src/client.ts @@ -780,37 +780,20 @@ export class Unlayer { static toFile = Uploads.toFile; - pages: API.Pages = new API.Pages(this); - emails: API.Emails = new API.Emails(this); project: API.Project = new API.Project(this); + emails: API.Emails = new API.Emails(this); documents: API.Documents = new API.Documents(this); + pages: API.Pages = new API.Pages(this); } -Unlayer.Pages = Pages; -Unlayer.Emails = Emails; Unlayer.Project = Project; +Unlayer.Emails = Emails; Unlayer.Documents = Documents; +Unlayer.Pages = Pages; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - - export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; - export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -834,6 +817,17 @@ export declare namespace Unlayer { type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; + export { + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { Documents as Documents, type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, @@ -842,4 +836,10 @@ export declare namespace Unlayer { type DocumentGenerateCreateParams as DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; + + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; } From e641fe7fb7b3c7ba55cebf386543b14a4c32572c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 21:24:25 +0000 Subject: [PATCH 036/118] feat(api): api update --- .stats.yml | 8 +- README.md | 17 ++- api.md | 56 ++++--- src/client.ts | 56 ++++--- src/resources/documents.ts | 52 +++++-- src/resources/emails.ts | 68 ++++++--- src/resources/index.ts | 10 ++ src/resources/pages.ts | 17 ++- src/resources/project.ts | 205 +++++++++++++++++++++++--- tests/api-resources/documents.test.ts | 13 ++ tests/api-resources/emails.test.ts | 10 ++ tests/api-resources/pages.test.ts | 1 + tests/api-resources/project.test.ts | 91 ++++++++++-- 13 files changed, 480 insertions(+), 124 deletions(-) diff --git a/.stats.yml b/.stats.yml index 74b0b57..dbdb430 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d746e93c3c920dca97596edec38c9ec25feef644db419156ae1b538bb54b6d72.yml -openapi_spec_hash: 437dce81b84c463ef9cc84dafa2ca92a -config_hash: 7495c5f2aebb250bf705cf2e6f4c1205 +configured_endpoints: 28 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-343ccfa7da7d6893c63932be1078248d3ff85dc4b9f11668d1c7f94d90e39565.yml +openapi_spec_hash: f3aeb20bc9ee90ff23b9caed9b8f01bf +config_hash: 901c0ed4f0a8971651e4798bbdee35a3 diff --git a/README.md b/README.md index 4f7017f..47c4687 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ const client = new Unlayer({ environment: 'qa', // or 'production' | 'dev'; defaults to 'production' }); -const response = await client.project.currentList(); +const response = await client.project.currentList({ projectId: 'projectId' }); console.log(response.data); ``` @@ -48,7 +48,8 @@ const client = new Unlayer({ environment: 'qa', // or 'production' | 'dev'; defaults to 'production' }); -const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(); +const params: Unlayer.ProjectCurrentListParams = { projectId: 'projectId' }; +const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -61,7 +62,7 @@ a subclass of `APIError` will be thrown: ```ts -const response = await client.project.currentList().catch(async (err) => { +const response = await client.project.currentList({ projectId: 'projectId' }).catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 console.log(err.name); // BadRequestError @@ -101,7 +102,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.project.currentList({ +await client.project.currentList({ projectId: 'projectId' }, { maxRetries: 5, }); ``` @@ -118,7 +119,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.project.currentList({ +await client.project.currentList({ projectId: 'projectId' }, { timeout: 5 * 1000, }); ``` @@ -141,11 +142,13 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.project.currentList().asResponse(); +const response = await client.project.currentList({ projectId: 'projectId' }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: response, response: raw } = await client.project.currentList().withResponse(); +const { data: response, response: raw } = await client.project + .currentList({ projectId: 'projectId' }) + .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(response.data); ``` diff --git a/api.md b/api.md index cc088f5..8dec2e3 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,19 @@ +# Emails + +Types: + +- EmailRetrieveResponse +- EmailRenderCreateResponse +- EmailSendCreateResponse +- EmailSendTemplateTemplateResponse + +Methods: + +- client.emails.retrieve(id, { ...params }) -> EmailRetrieveResponse +- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse +- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse +- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse + # Project Types: @@ -15,41 +31,43 @@ Types: - ProjectTemplatesListResponse - ProjectTemplatesRetrieveResponse - ProjectTemplatesUpdateResponse +- ProjectTokensDeleteResponse +- ProjectTokensListResponse +- ProjectWorkspacesListResponse +- ProjectWorkspacesRetrieveResponse Methods: - client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse - client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList() -> ProjectAPIKeysListResponse +- client.project.apiKeysList({ ...params }) -> ProjectAPIKeysListResponse - client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse - client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse -- client.project.currentList() -> ProjectCurrentListResponse +- client.project.currentList({ ...params }) -> ProjectCurrentListResponse - client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse - client.project.domainsDelete(id) -> void -- client.project.domainsList() -> ProjectDomainsListResponse +- client.project.domainsList({ ...params }) -> ProjectDomainsListResponse - client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse - client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse - client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse - client.project.templatesDelete(id) -> void -- client.project.templatesList() -> ProjectTemplatesListResponse +- client.project.templatesList({ ...params }) -> ProjectTemplatesListResponse - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse +- client.project.tokensDelete(tokenID) -> ProjectTokensDeleteResponse +- client.project.tokensList() -> ProjectTokensListResponse +- client.project.workspacesList() -> ProjectWorkspacesListResponse +- client.project.workspacesRetrieve(workspaceID) -> ProjectWorkspacesRetrieveResponse -# Emails +# Pages Types: -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- PageRenderCreateResponse Methods: -- client.emails.retrieve(id) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse # Documents @@ -61,16 +79,6 @@ Types: Methods: -- client.documents.documentsRetrieve(id) -> DocumentDocumentsRetrieveResponse +- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse - client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse - client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse - -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse diff --git a/src/client.ts b/src/client.ts index e645c47..1ad19cd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,6 +17,7 @@ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; import { + DocumentDocumentsRetrieveParams, DocumentDocumentsRetrieveResponse, DocumentGenerateCreateParams, DocumentGenerateCreateResponse, @@ -27,6 +28,7 @@ import { import { EmailRenderCreateParams, EmailRenderCreateResponse, + EmailRetrieveParams, EmailRetrieveResponse, EmailSendCreateParams, EmailSendCreateResponse, @@ -39,23 +41,31 @@ import { Project, ProjectAPIKeysCreateParams, ProjectAPIKeysCreateResponse, + ProjectAPIKeysListParams, ProjectAPIKeysListResponse, ProjectAPIKeysRetrieveResponse, ProjectAPIKeysUpdateParams, ProjectAPIKeysUpdateResponse, + ProjectCurrentListParams, ProjectCurrentListResponse, ProjectDomainsCreateParams, ProjectDomainsCreateResponse, + ProjectDomainsListParams, ProjectDomainsListResponse, ProjectDomainsRetrieveResponse, ProjectDomainsUpdateParams, ProjectDomainsUpdateResponse, ProjectTemplatesCreateParams, ProjectTemplatesCreateResponse, + ProjectTemplatesListParams, ProjectTemplatesListResponse, ProjectTemplatesRetrieveResponse, ProjectTemplatesUpdateParams, ProjectTemplatesUpdateResponse, + ProjectTokensDeleteResponse, + ProjectTokensListResponse, + ProjectWorkspacesListResponse, + ProjectWorkspacesRetrieveResponse, } from './resources/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; @@ -780,20 +790,32 @@ export class Unlayer { static toFile = Uploads.toFile; - project: API.Project = new API.Project(this); emails: API.Emails = new API.Emails(this); - documents: API.Documents = new API.Documents(this); + project: API.Project = new API.Project(this); pages: API.Pages = new API.Pages(this); + documents: API.Documents = new API.Documents(this); } -Unlayer.Project = Project; Unlayer.Emails = Emails; -Unlayer.Documents = Documents; +Unlayer.Project = Project; Unlayer.Pages = Pages; +Unlayer.Documents = Documents; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export { + Emails as Emails, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRenderCreateResponse as EmailRenderCreateResponse, + type EmailSendCreateResponse as EmailSendCreateResponse, + type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRetrieveParams as EmailRetrieveParams, + type EmailRenderCreateParams as EmailRenderCreateParams, + type EmailSendCreateParams as EmailSendCreateParams, + type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + }; + export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -809,23 +831,26 @@ export declare namespace Unlayer { type ProjectTemplatesListResponse as ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectTokensDeleteResponse as ProjectTokensDeleteResponse, + type ProjectTokensListResponse as ProjectTokensListResponse, + type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, + type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysListParams as ProjectAPIKeysListParams, type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectCurrentListParams as ProjectCurrentListParams, type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsListParams as ProjectDomainsListParams, type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesListParams as ProjectTemplatesListParams, type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, }; export { @@ -833,13 +858,8 @@ export declare namespace Unlayer { type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, type DocumentGenerateCreateParams as DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; } diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 594d3f0..9d1f621 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -16,8 +16,12 @@ export class Documents extends APIResource { * ); * ``` */ - documentsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, options); + documentsRetrieve( + id: string, + query: DocumentDocumentsRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, { query, ...options }); } /** @@ -54,10 +58,11 @@ export class Documents extends APIResource { * ``` */ generateCreate( - body: DocumentGenerateCreateParams, + params: DocumentGenerateCreateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/documents/v1/generate', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/documents/v1/generate', { query: { projectId }, body, ...options }); } /** @@ -72,10 +77,11 @@ export class Documents extends APIResource { * ``` */ generateTemplateTemplate( - body: DocumentGenerateTemplateTemplateParams, + params: DocumentGenerateTemplateTemplateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/documents/v1/generate/template', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/documents/v1/generate/template', { query: { projectId }, body, ...options }); } } @@ -159,46 +165,63 @@ export interface DocumentGenerateTemplateTemplateResponse { status?: 'generating' | 'completed' | 'failed'; } +export interface DocumentDocumentsRetrieveParams { + /** + * The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; +} + export interface DocumentGenerateCreateParams { /** - * Proprietary design format JSON + * Body param: Proprietary design format JSON */ design: { [key: string]: unknown }; /** - * Optional filename for the generated PDF + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: Optional filename for the generated PDF */ filename?: string; /** - * HTML content to convert to PDF + * Body param: HTML content to convert to PDF */ html?: string; /** - * Optional merge tags for personalization + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; /** - * URL to convert to PDF + * Body param: URL to convert to PDF */ url?: string; } export interface DocumentGenerateTemplateTemplateParams { /** - * ID of the template to use for generation + * Body param: ID of the template to use for generation */ templateId: string; /** - * Optional filename for the generated PDF + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: Optional filename for the generated PDF */ filename?: string; /** - * Optional merge tags for personalization + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; } @@ -208,6 +231,7 @@ export declare namespace Documents { type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, type DocumentGenerateCreateParams as DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, }; diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 4972627..ef19339 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -14,8 +14,12 @@ export class Emails extends APIResource { * const email = await client.emails.retrieve('id'); * ``` */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, options); + retrieve( + id: string, + query: EmailRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, { query, ...options }); } /** @@ -52,10 +56,11 @@ export class Emails extends APIResource { * ``` */ renderCreate( - body: EmailRenderCreateParams, + params: EmailRenderCreateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/emails/v1/render', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/emails/v1/render', { query: { projectId }, body, ...options }); } /** @@ -93,8 +98,9 @@ export class Emails extends APIResource { * }); * ``` */ - sendCreate(body: EmailSendCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/emails/v1/send', { body, ...options }); + sendCreate(params: EmailSendCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/emails/v1/send', { query: { projectId }, body, ...options }); } /** @@ -109,10 +115,11 @@ export class Emails extends APIResource { * ``` */ sendTemplateTemplate( - body: EmailSendTemplateTemplateParams, + params: EmailSendTemplateTemplateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/emails/v1/send/template', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/emails/v1/send/template', { query: { projectId }, body, ...options }); } } @@ -173,63 +180,85 @@ export interface EmailSendTemplateTemplateResponse { status?: 'sent' | 'queued' | 'failed'; } +export interface EmailRetrieveParams { + /** + * The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; +} + export interface EmailRenderCreateParams { /** - * Proprietary design format JSON + * Body param: Proprietary design format JSON */ design: { [key: string]: unknown }; /** - * Optional merge tags for personalization + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; } export interface EmailSendCreateParams { /** - * Proprietary design format JSON + * Body param: Proprietary design format JSON */ design: { [key: string]: unknown }; /** - * Recipient email address + * Body param: Recipient email address */ to: string; /** - * HTML content to send + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: HTML content to send */ html?: string; /** - * Optional merge tags for personalization + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; /** - * Email subject line + * Body param: Email subject line */ subject?: string; } export interface EmailSendTemplateTemplateParams { /** - * ID of the template to use + * Body param: ID of the template to use */ templateId: string; /** - * Recipient email address + * Body param: Recipient email address */ to: string; /** - * Optional merge tags for personalization + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; /** - * Email subject line (optional, uses template default if not provided) + * Body param: Email subject line (optional, uses template default if not provided) */ subject?: string; } @@ -240,6 +269,7 @@ export declare namespace Emails { type EmailRenderCreateResponse as EmailRenderCreateResponse, type EmailSendCreateResponse as EmailSendCreateResponse, type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, + type EmailRetrieveParams as EmailRetrieveParams, type EmailRenderCreateParams as EmailRenderCreateParams, type EmailSendCreateParams as EmailSendCreateParams, type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index 2303117..8d5eb48 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -5,6 +5,7 @@ export { type DocumentDocumentsRetrieveResponse, type DocumentGenerateCreateResponse, type DocumentGenerateTemplateTemplateResponse, + type DocumentDocumentsRetrieveParams, type DocumentGenerateCreateParams, type DocumentGenerateTemplateTemplateParams, } from './documents'; @@ -14,6 +15,7 @@ export { type EmailRenderCreateResponse, type EmailSendCreateResponse, type EmailSendTemplateTemplateResponse, + type EmailRetrieveParams, type EmailRenderCreateParams, type EmailSendCreateParams, type EmailSendTemplateTemplateParams, @@ -34,10 +36,18 @@ export { type ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse, + type ProjectTokensDeleteResponse, + type ProjectTokensListResponse, + type ProjectWorkspacesListResponse, + type ProjectWorkspacesRetrieveResponse, type ProjectAPIKeysCreateParams, + type ProjectAPIKeysListParams, type ProjectAPIKeysUpdateParams, + type ProjectCurrentListParams, type ProjectDomainsCreateParams, + type ProjectDomainsListParams, type ProjectDomainsUpdateParams, type ProjectTemplatesCreateParams, + type ProjectTemplatesListParams, type ProjectTemplatesUpdateParams, } from './project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 04ff5cf..8da1d66 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -38,8 +38,12 @@ export class Pages extends APIResource { * }); * ``` */ - renderCreate(body: PageRenderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/pages/v1/render', { body, ...options }); + renderCreate( + params: PageRenderCreateParams, + options?: RequestOptions, + ): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/pages/v1/render', { query: { projectId }, body, ...options }); } } @@ -52,12 +56,17 @@ export interface PageRenderCreateResponse { export interface PageRenderCreateParams { /** - * Proprietary design format JSON + * Body param: Proprietary design format JSON */ design: { [key: string]: unknown }; /** - * Optional merge tags for personalization + * Query param: The project ID (required for PAT auth, not needed for API Key auth) + */ + projectId?: string; + + /** + * Body param: Optional merge tags for personalization */ mergeTags?: { [key: string]: string }; } diff --git a/src/resources/project.ts b/src/resources/project.ts index 70418cb..b5ea982 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -11,10 +11,11 @@ export class Project extends APIResource { * Create a new API key for the project. */ apiKeysCreate( - body: ProjectAPIKeysCreateParams, + params: ProjectAPIKeysCreateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/project/v1/api-keys', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/project/v1/api-keys', { query: { projectId }, body, ...options }); } /** @@ -30,8 +31,11 @@ export class Project extends APIResource { /** * List all API keys for the project. */ - apiKeysList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/api-keys', options); + apiKeysList( + query: ProjectAPIKeysListParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/project/v1/api-keys', { query, ...options }); } /** @@ -53,20 +57,24 @@ export class Project extends APIResource { } /** - * Get project details for the authenticated project. + * Get project details for the specified project. */ - currentList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current', options); + currentList( + query: ProjectCurrentListParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/project/v1/current', { query, ...options }); } /** * Add a new domain to the project. */ domainsCreate( - body: ProjectDomainsCreateParams, + params: ProjectDomainsCreateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/project/v1/domains', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/project/v1/domains', { query: { projectId }, body, ...options }); } /** @@ -82,8 +90,11 @@ export class Project extends APIResource { /** * List all domains for the project. */ - domainsList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains', options); + domainsList( + query: ProjectDomainsListParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/project/v1/domains', { query, ...options }); } /** @@ -108,10 +119,11 @@ export class Project extends APIResource { * Create a new project template. */ templatesCreate( - body: ProjectTemplatesCreateParams, + params: ProjectTemplatesCreateParams, options?: RequestOptions, ): APIPromise { - return this._client.post('/project/v1/templates', { body, ...options }); + const { projectId, ...body } = params; + return this._client.post('/project/v1/templates', { query: { projectId }, body, ...options }); } /** @@ -127,8 +139,11 @@ export class Project extends APIResource { /** * Get all project templates. */ - templatesList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates', options); + templatesList( + query: ProjectTemplatesListParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/project/v1/templates', { query, ...options }); } /** @@ -148,6 +163,37 @@ export class Project extends APIResource { ): APIPromise { return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); } + + /** + * Delete a personal access token. You can only delete your own tokens. + */ + tokensDelete(tokenID: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/tokens/${tokenID}`, options); + } + + /** + * List all personal access tokens for the authenticated user. + */ + tokensList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/tokens', options); + } + + /** + * Get all workspaces accessible by the current token. + */ + workspacesList(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/workspaces', options); + } + + /** + * Get a specific workspace by ID with its projects. + */ + workspacesRetrieve( + workspaceID: string, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/project/v1/workspaces/${workspaceID}`, options); + } } export interface ProjectAPIKeysCreateResponse { @@ -414,18 +460,96 @@ export namespace ProjectTemplatesUpdateResponse { } } +export interface ProjectTokensDeleteResponse { + message?: string; + + success?: boolean; +} + +export interface ProjectTokensListResponse { + data?: Array; +} + +export namespace ProjectTokensListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + expiresAt?: string | null; + + lastUsedAt?: string | null; + + name?: string; + + scope?: string; + + workspaceId?: number | null; + + workspaceName?: string | null; + } +} + +export interface ProjectWorkspacesListResponse { + data?: Array; +} + +export namespace ProjectWorkspacesListResponse { + export interface Data { + id?: number; + + name?: string; + } +} + +export interface ProjectWorkspacesRetrieveResponse { + data?: ProjectWorkspacesRetrieveResponse.Data; +} + +export namespace ProjectWorkspacesRetrieveResponse { + export interface Data { + id?: number; + + name?: string; + + projects?: Array; + } + + export namespace Data { + export interface Project { + id?: number; + + name?: string; + + status?: string; + } + } +} + export interface ProjectAPIKeysCreateParams { /** - * Name for the API key + * Query param: The project ID to create API key for + */ + projectId: string; + + /** + * Body param: Name for the API key */ name: string; /** - * Allowed domains for this API key + * Body param: Allowed domains for this API key */ domains?: Array; } +export interface ProjectAPIKeysListParams { + /** + * The project ID to get API keys for + */ + projectId: string; +} + export interface ProjectAPIKeysUpdateParams { /** * Whether the API key is active @@ -443,13 +567,32 @@ export interface ProjectAPIKeysUpdateParams { name?: string; } +export interface ProjectCurrentListParams { + /** + * The project ID + */ + projectId: string; +} + export interface ProjectDomainsCreateParams { /** - * Domain name to add + * Query param: The project ID to add domain to + */ + projectId: string; + + /** + * Body param: Domain name to add */ domain: string; } +export interface ProjectDomainsListParams { + /** + * The project ID to get domains for + */ + projectId: string; +} + export interface ProjectDomainsUpdateParams { /** * Updated domain name @@ -459,21 +602,33 @@ export interface ProjectDomainsUpdateParams { export interface ProjectTemplatesCreateParams { /** - * Template name + * Query param: The project ID to create template for + */ + projectId: string; + + /** + * Body param: Template name */ name: string; /** - * Email body content + * Body param: Email body content */ body?: string; /** - * Email subject line + * Body param: Email subject line */ subject?: string; } +export interface ProjectTemplatesListParams { + /** + * The project ID to get templates for + */ + projectId: string; +} + export interface ProjectTemplatesUpdateParams { /** * Updated email body content @@ -506,11 +661,19 @@ export declare namespace Project { type ProjectTemplatesListResponse as ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, + type ProjectTokensDeleteResponse as ProjectTokensDeleteResponse, + type ProjectTokensListResponse as ProjectTokensListResponse, + type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, + type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, + type ProjectAPIKeysListParams as ProjectAPIKeysListParams, type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectCurrentListParams as ProjectCurrentListParams, type ProjectDomainsCreateParams as ProjectDomainsCreateParams, + type ProjectDomainsListParams as ProjectDomainsListParams, type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, + type ProjectTemplatesListParams as ProjectTemplatesListParams, type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; } diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 01a1bdd..6d7dd4b 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -19,6 +19,17 @@ describe('resource documents', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('documentsRetrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.documents.documentsRetrieve( + 'id', + { projectId: 'projectId' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + test('generateCreate: only required params', async () => { const responsePromise = client.documents.generateCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); @@ -33,6 +44,7 @@ describe('resource documents', () => { test('generateCreate: required and optional params', async () => { const response = await client.documents.generateCreate({ design: { counters: 'bar', body: 'bar' }, + projectId: 'projectId', filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, @@ -54,6 +66,7 @@ describe('resource documents', () => { test('generateTemplateTemplate: required and optional params', async () => { const response = await client.documents.generateTemplateTemplate({ templateId: 'templateId', + projectId: 'projectId', filename: 'filename', mergeTags: { foo: 'string' }, }); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index 6bed6cc..ab98cc4 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -19,6 +19,13 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.emails.retrieve('id', { projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + test('renderCreate: only required params', async () => { const responsePromise = client.emails.renderCreate({ design: { counters: 'bar', body: 'bar' } }); const rawResponse = await responsePromise.asResponse(); @@ -33,6 +40,7 @@ describe('resource emails', () => { test('renderCreate: required and optional params', async () => { const response = await client.emails.renderCreate({ design: { counters: 'bar', body: 'bar' }, + projectId: 'projectId', mergeTags: { foo: 'string' }, }); }); @@ -55,6 +63,7 @@ describe('resource emails', () => { const response = await client.emails.sendCreate({ design: { counters: 'bar', body: 'bar' }, to: 'test@example.com', + projectId: 'projectId', html: 'html', mergeTags: { foo: 'string' }, subject: 'Test', @@ -79,6 +88,7 @@ describe('resource emails', () => { const response = await client.emails.sendTemplateTemplate({ templateId: 'templateId', to: 'dev@stainless.com', + projectId: 'projectId', mergeTags: { foo: 'string' }, subject: 'subject', }); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts index 3a817b2..489872e 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/pages.test.ts @@ -22,6 +22,7 @@ describe('resource pages', () => { test('renderCreate: required and optional params', async () => { const response = await client.pages.renderCreate({ design: { counters: 'bar', body: 'bar' }, + projectId: 'projectId', mergeTags: { foo: 'string' }, }); }); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts index ec5105a..f76f5ed 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/project.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource project', () => { test('apiKeysCreate: only required params', async () => { - const responsePromise = client.project.apiKeysCreate({ name: 'name' }); + const responsePromise = client.project.apiKeysCreate({ projectId: 'projectId', name: 'name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,11 @@ describe('resource project', () => { }); test('apiKeysCreate: required and optional params', async () => { - const response = await client.project.apiKeysCreate({ name: 'name', domains: ['string'] }); + const response = await client.project.apiKeysCreate({ + projectId: 'projectId', + name: 'name', + domains: ['string'], + }); }); test('apiKeysDelete', async () => { @@ -34,8 +38,8 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('apiKeysList', async () => { - const responsePromise = client.project.apiKeysList(); + test('apiKeysList: only required params', async () => { + const responsePromise = client.project.apiKeysList({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -45,6 +49,10 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('apiKeysList: required and optional params', async () => { + const response = await client.project.apiKeysList({ projectId: 'projectId' }); + }); + test('apiKeysRetrieve', async () => { const responsePromise = client.project.apiKeysRetrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -82,8 +90,8 @@ describe('resource project', () => { ).rejects.toThrow(Unlayer.NotFoundError); }); - test('currentList', async () => { - const responsePromise = client.project.currentList(); + test('currentList: only required params', async () => { + const responsePromise = client.project.currentList({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -93,8 +101,12 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('currentList: required and optional params', async () => { + const response = await client.project.currentList({ projectId: 'projectId' }); + }); + test('domainsCreate: only required params', async () => { - const responsePromise = client.project.domainsCreate({ domain: 'domain' }); + const responsePromise = client.project.domainsCreate({ projectId: 'projectId', domain: 'domain' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -105,7 +117,7 @@ describe('resource project', () => { }); test('domainsCreate: required and optional params', async () => { - const response = await client.project.domainsCreate({ domain: 'domain' }); + const response = await client.project.domainsCreate({ projectId: 'projectId', domain: 'domain' }); }); test('domainsDelete', async () => { @@ -119,8 +131,8 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('domainsList', async () => { - const responsePromise = client.project.domainsList(); + test('domainsList: only required params', async () => { + const responsePromise = client.project.domainsList({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -130,6 +142,10 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('domainsList: required and optional params', async () => { + const response = await client.project.domainsList({ projectId: 'projectId' }); + }); + test('domainsRetrieve', async () => { const responsePromise = client.project.domainsRetrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -160,7 +176,7 @@ describe('resource project', () => { }); test('templatesCreate: only required params', async () => { - const responsePromise = client.project.templatesCreate({ name: 'name' }); + const responsePromise = client.project.templatesCreate({ projectId: 'projectId', name: 'name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -172,6 +188,7 @@ describe('resource project', () => { test('templatesCreate: required and optional params', async () => { const response = await client.project.templatesCreate({ + projectId: 'projectId', name: 'name', body: 'body', subject: 'subject', @@ -189,8 +206,8 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('templatesList', async () => { - const responsePromise = client.project.templatesList(); + test('templatesList: only required params', async () => { + const responsePromise = client.project.templatesList({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -200,6 +217,10 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('templatesList: required and optional params', async () => { + const response = await client.project.templatesList({ projectId: 'projectId' }); + }); + test('templatesRetrieve', async () => { const responsePromise = client.project.templatesRetrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -236,4 +257,48 @@ describe('resource project', () => { ), ).rejects.toThrow(Unlayer.NotFoundError); }); + + test('tokensDelete', async () => { + const responsePromise = client.project.tokensDelete('tokenId'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('tokensList', async () => { + const responsePromise = client.project.tokensList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('workspacesList', async () => { + const responsePromise = client.project.workspacesList(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('workspacesRetrieve', async () => { + const responsePromise = client.project.workspacesRetrieve('workspaceId'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); }); From 0cf640a12562846afbc10b812adcba489116b0f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:31:15 +0000 Subject: [PATCH 037/118] chore(internal): upgrade babel, qs, js-yaml --- yarn.lock | 556 ++++++++++++++++++++++++------------------------------ 1 file changed, 249 insertions(+), 307 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5f56a20..fc9f262 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,14 +7,6 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - "@andrewbranch/untar.js@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" @@ -46,155 +38,119 @@ typescript "5.6.1-rc" validate-npm-package-name "^5.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== "@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" - integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.6" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.28.6", "@babel/generator@^7.7.2": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== + dependencies: + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" - integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -210,14 +166,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" + integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -232,13 +202,13 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.28.6" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -252,7 +222,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -280,7 +250,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -288,45 +265,41 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.3.3": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" - integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/template@^7.28.6", "@babel/template@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.6", "@babel/types@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -668,31 +641,38 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18": version "0.3.20" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== @@ -700,6 +680,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1116,13 +1104,6 @@ ansi-regex@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -1200,22 +1181,25 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -1230,18 +1214,23 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +baseline-browser-mapping@^2.9.0: + version "2.9.14" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" + integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== + brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -1252,15 +1241,16 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.24.0: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" bs-logger@0.x: version "0.2.6" @@ -1296,19 +1286,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" +caniuse-lite@^1.0.30001759: + version "1.0.30001764" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz#03206c56469f236103b90f9ae10bcb8b9e1f6005" + integrity sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g== chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" @@ -1397,13 +1378,6 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1411,11 +1385,6 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -1507,10 +1476,10 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -electron-to-chromium@^1.4.601: - version "1.4.614" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" - integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== emittery@^0.13.1: version "0.13.1" @@ -1544,10 +1513,10 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^2.0.0: version "2.0.0" @@ -1883,11 +1852,6 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" @@ -1903,11 +1867,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -2459,9 +2418,9 @@ js-tokens@^4.0.0: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -2473,10 +2432,10 @@ js-yaml@^4.1.1: dependencies: argparse "^2.0.1" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== json-buffer@3.0.1: version "3.0.1" @@ -2711,10 +2670,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== normalize-path@^3.0.0: version "3.0.0" @@ -2882,11 +2841,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -3190,13 +3144,6 @@ superstruct@^1.0.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -3259,11 +3206,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3389,13 +3331,13 @@ unicode-emoji-modifier-base@^1.0.0: resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" uri-js@^4.2.2: version "4.4.1" From 4c1ce1ee795171d65193f2edd1f84f84be1dd716 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:47:13 +0000 Subject: [PATCH 038/118] feat(api): api update --- .stats.yml | 6 +++--- api.md | 48 ++++++++++++++++++++++++------------------------ src/client.ts | 36 ++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/.stats.yml b/.stats.yml index dbdb430..97858dc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 28 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-343ccfa7da7d6893c63932be1078248d3ff85dc4b9f11668d1c7f94d90e39565.yml -openapi_spec_hash: f3aeb20bc9ee90ff23b9caed9b8f01bf -config_hash: 901c0ed4f0a8971651e4798bbdee35a3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d89823a559be3efaaedf95ef21523f77342db1eb9bd708015fac22f68bcfd8ae.yml +openapi_spec_hash: fda98646b156fdd53a03d433cbacad20 +config_hash: ad8a4186026c9854e45139d7c4a20090 diff --git a/api.md b/api.md index 8dec2e3..56bcf91 100644 --- a/api.md +++ b/api.md @@ -14,6 +14,30 @@ Methods: - client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse - client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +# Pages + +Types: + +- PageRenderCreateResponse + +Methods: + +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse + +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + # Project Types: @@ -58,27 +82,3 @@ Methods: - client.project.tokensList() -> ProjectTokensListResponse - client.project.workspacesList() -> ProjectWorkspacesListResponse - client.project.workspacesRetrieve(workspaceID) -> ProjectWorkspacesRetrieveResponse - -# Pages - -Types: - -- PageRenderCreateResponse - -Methods: - -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse - -# Documents - -Types: - -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse - -Methods: - -- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse diff --git a/src/client.ts b/src/client.ts index 1ad19cd..666aae9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -791,15 +791,15 @@ export class Unlayer { static toFile = Uploads.toFile; emails: API.Emails = new API.Emails(this); - project: API.Project = new API.Project(this); pages: API.Pages = new API.Pages(this); documents: API.Documents = new API.Documents(this); + project: API.Project = new API.Project(this); } Unlayer.Emails = Emails; -Unlayer.Project = Project; Unlayer.Pages = Pages; Unlayer.Documents = Documents; +Unlayer.Project = Project; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; @@ -816,6 +816,22 @@ export declare namespace Unlayer { type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; + export { + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, + }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + export { Project as Project, type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, @@ -846,20 +862,4 @@ export declare namespace Unlayer { type ProjectTemplatesListParams as ProjectTemplatesListParams, type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, }; - - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; - - export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; } From a6c0da6a796f4b275b24d6ef439a02abf0ba7542 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:06:22 +0000 Subject: [PATCH 039/118] chore(internal): update `actions/checkout` version --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9718f6..e9dba85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -74,7 +74,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 From 49d05ebab08ee493e62e742f3f9753eadc78d303 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:08:53 +0000 Subject: [PATCH 040/118] feat(api): api update --- .stats.yml | 8 +- README.md | 74 ++++-- api.md | 51 +++-- src/client.ts | 117 ++++++---- src/core/pagination.ts | 170 ++++++++++++++ src/index.ts | 1 + src/pagination.ts | 2 + src/resources/documents.ts | 213 ++++++++---------- src/resources/emails.ts | 215 +++++++----------- src/resources/export.ts | 116 ++++++++++ src/resources/index.ts | 21 +- src/resources/pages.ts | 52 ++--- src/resources/project.ts | 310 +++++--------------------- tests/api-resources/documents.test.ts | 28 +-- tests/api-resources/emails.test.ts | 34 ++- tests/api-resources/export.test.ts | 70 ++++++ tests/api-resources/pages.test.ts | 9 +- tests/api-resources/project.test.ts | 117 +--------- tests/index.test.ts | 96 ++++---- 19 files changed, 867 insertions(+), 837 deletions(-) create mode 100644 src/core/pagination.ts create mode 100644 src/pagination.ts create mode 100644 src/resources/export.ts create mode 100644 tests/api-resources/export.test.ts diff --git a/.stats.yml b/.stats.yml index 97858dc..ead84b6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 28 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-d89823a559be3efaaedf95ef21523f77342db1eb9bd708015fac22f68bcfd8ae.yml -openapi_spec_hash: fda98646b156fdd53a03d433cbacad20 -config_hash: ad8a4186026c9854e45139d7c4a20090 +configured_endpoints: 25 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-42ce261f6dec6bdbfe9b98a3835cbb95c67440a58023646fe03ab0aa0745d671.yml +openapi_spec_hash: 0f18f2d5ea38b837ccc0156ea80d85cd +config_hash: ae90f2806448a012e25917d01699b3a5 diff --git a/README.md b/README.md index 47c4687..20bceda 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ The full API of this library can be found in [api.md](api.md). import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted - environment: 'qa', // or 'production' | 'dev'; defaults to 'production' + accessToken: process.env['UNLAYER_ACCESS_TOKEN'], // This is the default and can be omitted + environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const response = await client.project.currentList({ projectId: 'projectId' }); +const response = await client.project.currentList({ projectId: 'your-project-id' }); console.log(response.data); ``` @@ -44,11 +44,11 @@ This library includes TypeScript definitions for all request params and response import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted - environment: 'qa', // or 'production' | 'dev'; defaults to 'production' + accessToken: process.env['UNLAYER_ACCESS_TOKEN'], // This is the default and can be omitted + environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const params: Unlayer.ProjectCurrentListParams = { projectId: 'projectId' }; +const params: Unlayer.ProjectCurrentListParams = { projectId: 'your-project-id' }; const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(params); ``` @@ -62,15 +62,17 @@ a subclass of `APIError` will be thrown: ```ts -const response = await client.project.currentList({ projectId: 'projectId' }).catch(async (err) => { - if (err instanceof Unlayer.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } -}); +const response = await client.project + .currentList({ projectId: 'your-project-id' }) + .catch(async (err) => { + if (err instanceof Unlayer.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); ``` Error codes are as follows: @@ -102,7 +104,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.project.currentList({ projectId: 'projectId' }, { +await client.project.currentList({ projectId: 'your-project-id' }, { maxRetries: 5, }); ``` @@ -119,7 +121,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.project.currentList({ projectId: 'projectId' }, { +await client.project.currentList({ projectId: 'your-project-id' }, { timeout: 5 * 1000, }); ``` @@ -128,6 +130,40 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). +## Auto-pagination + +List methods in the Unlayer API are paginated. +You can use the `for await … of` syntax to iterate through items across all pages: + +```ts +async function fetchAllProjectTemplatesListResponses(params) { + const allProjectTemplatesListResponses = []; + // Automatically fetches more pages as needed. + for await (const projectTemplatesListResponse of client.project.templatesList({ + projectId: 'your-project-id', + limit: 10, + })) { + allProjectTemplatesListResponses.push(projectTemplatesListResponse); + } + return allProjectTemplatesListResponses; +} +``` + +Alternatively, you can request a single page at a time: + +```ts +let page = await client.project.templatesList({ projectId: 'your-project-id', limit: 10 }); +for (const projectTemplatesListResponse of page.data) { + console.log(projectTemplatesListResponse); +} + +// Convenience methods are provided for manually paginating: +while (page.hasNextPage()) { + page = await page.getNextPage(); + // ... +} +``` + ## Advanced Usage ### Accessing raw Response data (e.g., headers) @@ -142,12 +178,12 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.project.currentList({ projectId: 'projectId' }).asResponse(); +const response = await client.project.currentList({ projectId: 'your-project-id' }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object const { data: response, response: raw } = await client.project - .currentList({ projectId: 'projectId' }) + .currentList({ projectId: 'your-project-id' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(response.data); diff --git a/api.md b/api.md index 56bcf91..db34eed 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,17 @@ +# Documents + +Types: + +- DocumentDocumentsRetrieveResponse +- DocumentGenerateCreateResponse +- DocumentGenerateTemplateTemplateResponse + +Methods: + +- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse +- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse +- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse + # Emails Types: @@ -14,38 +28,36 @@ Methods: - client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse - client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse -# Pages +# Export Types: -- PageRenderCreateResponse +- ExportHTMLListResponse +- ExportImageListResponse +- ExportPdfListResponse +- ExportZipListResponse Methods: -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse +- client.export.htmlList({ ...params }) -> ExportHTMLListResponse +- client.export.imageList({ ...params }) -> ExportImageListResponse +- client.export.pdfList({ ...params }) -> ExportPdfListResponse +- client.export.zipList({ ...params }) -> ExportZipListResponse -# Documents +# Pages Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse +- PageRenderCreateResponse Methods: -- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse +- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse # Project Types: -- ProjectAPIKeysCreateResponse -- ProjectAPIKeysListResponse -- ProjectAPIKeysRetrieveResponse -- ProjectAPIKeysUpdateResponse - ProjectCurrentListResponse - ProjectDomainsCreateResponse - ProjectDomainsListResponse @@ -55,18 +67,11 @@ Types: - ProjectTemplatesListResponse - ProjectTemplatesRetrieveResponse - ProjectTemplatesUpdateResponse -- ProjectTokensDeleteResponse -- ProjectTokensListResponse - ProjectWorkspacesListResponse - ProjectWorkspacesRetrieveResponse Methods: -- client.project.apiKeysCreate({ ...params }) -> ProjectAPIKeysCreateResponse -- client.project.apiKeysDelete(id) -> void -- client.project.apiKeysList({ ...params }) -> ProjectAPIKeysListResponse -- client.project.apiKeysRetrieve(id) -> ProjectAPIKeysRetrieveResponse -- client.project.apiKeysUpdate(id, { ...params }) -> ProjectAPIKeysUpdateResponse - client.project.currentList({ ...params }) -> ProjectCurrentListResponse - client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse - client.project.domainsDelete(id) -> void @@ -75,10 +80,8 @@ Methods: - client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse - client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse - client.project.templatesDelete(id) -> void -- client.project.templatesList({ ...params }) -> ProjectTemplatesListResponse +- client.project.templatesList({ ...params }) -> ProjectTemplatesListResponsesCursorPage - client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse - client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -- client.project.tokensDelete(tokenID) -> ProjectTokensDeleteResponse -- client.project.tokensList() -> ProjectTokensListResponse - client.project.workspacesList() -> ProjectWorkspacesListResponse - client.project.workspacesRetrieve(workspaceID) -> ProjectWorkspacesRetrieveResponse diff --git a/src/client.ts b/src/client.ts index 666aae9..a1a0dce 100644 --- a/src/client.ts +++ b/src/client.ts @@ -13,6 +13,8 @@ import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; import { VERSION } from './version'; import * as Errors from './core/error'; +import * as Pagination from './core/pagination'; +import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/pagination'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; @@ -36,16 +38,20 @@ import { EmailSendTemplateTemplateResponse, Emails, } from './resources/emails'; +import { + Export, + ExportHTMLListParams, + ExportHTMLListResponse, + ExportImageListParams, + ExportImageListResponse, + ExportPdfListParams, + ExportPdfListResponse, + ExportZipListParams, + ExportZipListResponse, +} from './resources/export'; import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages'; import { Project, - ProjectAPIKeysCreateParams, - ProjectAPIKeysCreateResponse, - ProjectAPIKeysListParams, - ProjectAPIKeysListResponse, - ProjectAPIKeysRetrieveResponse, - ProjectAPIKeysUpdateParams, - ProjectAPIKeysUpdateResponse, ProjectCurrentListParams, ProjectCurrentListResponse, ProjectDomainsCreateParams, @@ -59,11 +65,10 @@ import { ProjectTemplatesCreateResponse, ProjectTemplatesListParams, ProjectTemplatesListResponse, + ProjectTemplatesListResponsesCursorPage, ProjectTemplatesRetrieveResponse, ProjectTemplatesUpdateParams, ProjectTemplatesUpdateResponse, - ProjectTokensDeleteResponse, - ProjectTokensListResponse, ProjectWorkspacesListResponse, ProjectWorkspacesRetrieveResponse, } from './resources/project'; @@ -82,6 +87,7 @@ import { isEmptyObj } from './internal/utils/values'; const environments = { production: 'https://api.unlayer.com', + stage: 'https://api.stage.unlayer.com', qa: 'https://api.qa.unlayer.com', dev: 'https://api.dev.unlayer.com', }; @@ -89,15 +95,16 @@ type Environment = keyof typeof environments; export interface ClientOptions { /** - * Defaults to process.env['UNLAYER_API_KEY']. + * Defaults to process.env['UNLAYER_ACCESS_TOKEN']. */ - apiKey?: string | undefined; + accessToken?: string | undefined; /** * Specifies the environment to use for the API. * * Each environment maps to a different base URL: * - `production` corresponds to `https://api.unlayer.com` + * - `stage` corresponds to `https://api.stage.unlayer.com` * - `qa` corresponds to `https://api.qa.unlayer.com` * - `dev` corresponds to `https://api.dev.unlayer.com` */ @@ -176,7 +183,7 @@ export interface ClientOptions { * API Client for interfacing with the Unlayer API. */ export class Unlayer { - apiKey: string; + accessToken: string; baseURL: string; maxRetries: number; @@ -193,7 +200,7 @@ export class Unlayer { /** * API Client for interfacing with the Unlayer API. * - * @param {string | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? undefined] + * @param {string | undefined} [opts.accessToken=process.env['UNLAYER_ACCESS_TOKEN'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. @@ -205,17 +212,17 @@ export class Unlayer { */ constructor({ baseURL = readEnv('UNLAYER_BASE_URL'), - apiKey = readEnv('UNLAYER_API_KEY'), + accessToken = readEnv('UNLAYER_ACCESS_TOKEN'), ...opts }: ClientOptions = {}) { - if (apiKey === undefined) { + if (accessToken === undefined) { throw new Errors.UnlayerError( - "The UNLAYER_API_KEY environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an apiKey option, like new Unlayer({ apiKey: 'My API Key' }).", + "The UNLAYER_ACCESS_TOKEN environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an accessToken option, like new Unlayer({ accessToken: 'My Access Token' }).", ); } const options: ClientOptions = { - apiKey, + accessToken, ...opts, baseURL, environment: opts.environment ?? 'production', @@ -244,7 +251,7 @@ export class Unlayer { this._options = options; - this.apiKey = apiKey; + this.accessToken = accessToken; } /** @@ -261,7 +268,7 @@ export class Unlayer { logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, - apiKey: this.apiKey, + accessToken: this.accessToken, ...options, }); return client; @@ -283,7 +290,7 @@ export class Unlayer { } protected async authHeaders(opts: FinalRequestOptions): Promise { - return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); + return buildHeaders([{ Authorization: `Bearer ${this.accessToken}` }]); } /** @@ -558,6 +565,25 @@ export class Unlayer { return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; } + getAPIList = Pagination.AbstractPage>( + path: string, + Page: new (...args: any[]) => PageClass, + opts?: RequestOptions, + ): Pagination.PagePromise { + return this.requestAPIList(Page, { method: 'get', path, ...opts }); + } + + requestAPIList< + Item = unknown, + PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, + >( + Page: new (...args: ConstructorParameters) => PageClass, + options: FinalRequestOptions, + ): Pagination.PagePromise { + const request = this.makeRequest(options, null, undefined); + return new Pagination.PagePromise(this as any as Unlayer, request, Page); + } + async fetchWithTimeout( url: RequestInfo, init: RequestInit | undefined, @@ -790,20 +816,35 @@ export class Unlayer { static toFile = Uploads.toFile; + documents: API.Documents = new API.Documents(this); emails: API.Emails = new API.Emails(this); + export: API.Export = new API.Export(this); pages: API.Pages = new API.Pages(this); - documents: API.Documents = new API.Documents(this); project: API.Project = new API.Project(this); } +Unlayer.Documents = Documents; Unlayer.Emails = Emails; +Unlayer.Export = Export; Unlayer.Pages = Pages; -Unlayer.Documents = Documents; Unlayer.Project = Project; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; + export import CursorPage = Pagination.CursorPage; + export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + + export { + Documents as Documents, + type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, + type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, + type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, + type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, + type DocumentGenerateCreateParams as DocumentGenerateCreateParams, + type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + }; + export { Emails as Emails, type EmailRetrieveResponse as EmailRetrieveResponse, @@ -817,27 +858,25 @@ export declare namespace Unlayer { }; export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, + Export as Export, + type ExportHTMLListResponse as ExportHTMLListResponse, + type ExportImageListResponse as ExportImageListResponse, + type ExportPdfListResponse as ExportPdfListResponse, + type ExportZipListResponse as ExportZipListResponse, + type ExportHTMLListParams as ExportHTMLListParams, + type ExportImageListParams as ExportImageListParams, + type ExportPdfListParams as ExportPdfListParams, + type ExportZipListParams as ExportZipListParams, }; export { - Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + Pages as Pages, + type PageRenderCreateResponse as PageRenderCreateResponse, + type PageRenderCreateParams as PageRenderCreateParams, }; export { Project as Project, - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, type ProjectCurrentListResponse as ProjectCurrentListResponse, type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, type ProjectDomainsListResponse as ProjectDomainsListResponse, @@ -847,13 +886,9 @@ export declare namespace Unlayer { type ProjectTemplatesListResponse as ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectTokensDeleteResponse as ProjectTokensDeleteResponse, - type ProjectTokensListResponse as ProjectTokensListResponse, type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysListParams as ProjectAPIKeysListParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectTemplatesListResponsesCursorPage as ProjectTemplatesListResponsesCursorPage, type ProjectCurrentListParams as ProjectCurrentListParams, type ProjectDomainsCreateParams as ProjectDomainsCreateParams, type ProjectDomainsListParams as ProjectDomainsListParams, diff --git a/src/core/pagination.ts b/src/core/pagination.ts new file mode 100644 index 0000000..2d31c86 --- /dev/null +++ b/src/core/pagination.ts @@ -0,0 +1,170 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { UnlayerError } from './error'; +import { FinalRequestOptions } from '../internal/request-options'; +import { defaultParseResponse } from '../internal/parse'; +import { type Unlayer } from '../client'; +import { APIPromise } from './api-promise'; +import { type APIResponseProps } from '../internal/parse'; +import { maybeObj } from '../internal/utils/values'; + +export type PageRequestOptions = Pick; + +export abstract class AbstractPage implements AsyncIterable { + #client: Unlayer; + protected options: FinalRequestOptions; + + protected response: Response; + protected body: unknown; + + constructor(client: Unlayer, response: Response, body: unknown, options: FinalRequestOptions) { + this.#client = client; + this.options = options; + this.response = response; + this.body = body; + } + + abstract nextPageRequestOptions(): PageRequestOptions | null; + + abstract getPaginatedItems(): Item[]; + + hasNextPage(): boolean { + const items = this.getPaginatedItems(); + if (!items.length) return false; + return this.nextPageRequestOptions() != null; + } + + async getNextPage(): Promise { + const nextOptions = this.nextPageRequestOptions(); + if (!nextOptions) { + throw new UnlayerError( + 'No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.', + ); + } + + return await this.#client.requestAPIList(this.constructor as any, nextOptions); + } + + async *iterPages(): AsyncGenerator { + let page: this = this; + yield page; + while (page.hasNextPage()) { + page = await page.getNextPage(); + yield page; + } + } + + async *[Symbol.asyncIterator](): AsyncGenerator { + for await (const page of this.iterPages()) { + for (const item of page.getPaginatedItems()) { + yield item; + } + } + } +} + +/** + * This subclass of Promise will resolve to an instantiated Page once the request completes. + * + * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ +export class PagePromise< + PageClass extends AbstractPage, + Item = ReturnType[number], + > + extends APIPromise + implements AsyncIterable +{ + constructor( + client: Unlayer, + request: Promise, + Page: new (...args: ConstructorParameters) => PageClass, + ) { + super( + client, + request, + async (client, props) => + new Page(client, props.response, await defaultParseResponse(client, props), props.options), + ); + } + + /** + * Allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ + async *[Symbol.asyncIterator](): AsyncGenerator { + const page = await this; + for await (const item of page) { + yield item; + } + } +} + +export interface CursorPageResponse { + data: Array; + + next_cursor: string | null; + + has_more: boolean; +} + +export interface CursorPageParams { + cursor?: string; + + limit?: number; +} + +export class CursorPage extends AbstractPage implements CursorPageResponse { + data: Array; + + next_cursor: string | null; + + has_more: boolean; + + constructor( + client: Unlayer, + response: Response, + body: CursorPageResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.data = body.data || []; + this.next_cursor = body.next_cursor || null; + this.has_more = body.has_more || false; + } + + getPaginatedItems(): Item[] { + return this.data ?? []; + } + + override hasNextPage(): boolean { + if (this.has_more === false) { + return false; + } + + return super.hasNextPage(); + } + + nextPageRequestOptions(): PageRequestOptions | null { + const cursor = this.next_cursor; + if (!cursor) { + return null; + } + + return { + ...this.options, + query: { + ...maybeObj(this.options.query), + cursor, + }, + }; + } +} diff --git a/src/index.ts b/src/index.ts index e635759..2a2ff83 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export { Unlayer as default } from './client'; export { type Uploadable, toFile } from './core/uploads'; export { APIPromise } from './core/api-promise'; export { Unlayer, type ClientOptions } from './client'; +export { PagePromise } from './core/pagination'; export { UnlayerError, APIError, diff --git a/src/pagination.ts b/src/pagination.ts new file mode 100644 index 0000000..90bf015 --- /dev/null +++ b/src/pagination.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/pagination instead */ +export * from './core/pagination'; diff --git a/src/resources/documents.ts b/src/resources/documents.ts index 9d1f621..fdd66ac 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -8,17 +8,10 @@ import { path } from '../internal/utils/path'; export class Documents extends APIResource { /** * Retrieve details of a previously generated document. - * - * @example - * ```ts - * const response = await client.documents.documentsRetrieve( - * 'id', - * ); - * ``` */ documentsRetrieve( id: string, - query: DocumentDocumentsRetrieveParams | null | undefined = {}, + query: DocumentDocumentsRetrieveParams, options?: RequestOptions, ): APIPromise { return this._client.get(path`/documents/v1/documents/${id}`, { query, ...options }); @@ -26,36 +19,6 @@ export class Documents extends APIResource { /** * Generate PDF document from JSON design, HTML content, or URL. - * - * @example - * ```ts - * const response = await client.documents.generateCreate({ - * design: { - * counters: { - * u_row: 1, - * u_column: 1, - * u_content_text: 1, - * }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` */ generateCreate( params: DocumentGenerateCreateParams, @@ -67,14 +30,6 @@ export class Documents extends APIResource { /** * Generate PDF document from an existing template with merge tags. - * - * @example - * ```ts - * const response = - * await client.documents.generateTemplateTemplate({ - * templateId: 'templateId', - * }); - * ``` */ generateTemplateTemplate( params: DocumentGenerateTemplateTemplateParams, @@ -86,102 +41,120 @@ export class Documents extends APIResource { } export interface DocumentDocumentsRetrieveResponse { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; + data?: DocumentDocumentsRetrieveResponse.Data; +} - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; +export namespace DocumentDocumentsRetrieveResponse { + export interface Data { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; + } } export interface DocumentGenerateCreateResponse { - /** - * Unique document identifier - */ - documentId?: string; + data?: DocumentGenerateCreateResponse.Data; +} - /** - * Generated filename - */ - filename?: string; +export namespace DocumentGenerateCreateResponse { + export interface Data { + /** + * Unique document identifier + */ + documentId?: string; - /** - * URL to download the generated PDF - */ - pdfUrl?: string; + /** + * Generated filename + */ + filename?: string; - status?: 'generating' | 'completed' | 'failed'; + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; + } } export interface DocumentGenerateTemplateTemplateResponse { - /** - * Unique document identifier - */ - documentId?: string; + data?: DocumentGenerateTemplateTemplateResponse.Data; +} - /** - * Generated filename - */ - filename?: string; +export namespace DocumentGenerateTemplateTemplateResponse { + export interface Data { + /** + * Unique document identifier + */ + documentId?: string; - /** - * URL to download the generated PDF - */ - pdfUrl?: string; + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; - status?: 'generating' | 'completed' | 'failed'; + status?: 'generating' | 'completed' | 'failed'; + } } export interface DocumentDocumentsRetrieveParams { /** - * The project ID (required for PAT auth, not needed for API Key auth) + * The project ID */ - projectId?: string; + projectId: string; } export interface DocumentGenerateCreateParams { /** - * Body param: Proprietary design format JSON + * Query param: The project ID */ - design: { [key: string]: unknown }; + projectId: string; /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) + * Body param: Proprietary design format JSON */ - projectId?: string; + design?: { [key: string]: unknown }; /** * Body param: Optional filename for the generated PDF @@ -206,14 +179,14 @@ export interface DocumentGenerateCreateParams { export interface DocumentGenerateTemplateTemplateParams { /** - * Body param: ID of the template to use for generation + * Query param: The project ID */ - templateId: string; + projectId: string; /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) + * Body param: ID of the template to use for generation */ - projectId?: string; + templateId: string; /** * Body param: Optional filename for the generated PDF diff --git a/src/resources/emails.ts b/src/resources/emails.ts index ef19339..5c3d4bf 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -8,15 +8,10 @@ import { path } from '../internal/utils/path'; export class Emails extends APIResource { /** * Retrieve details of a previously sent email. - * - * @example - * ```ts - * const email = await client.emails.retrieve('id'); - * ``` */ retrieve( id: string, - query: EmailRetrieveParams | null | undefined = {}, + query: EmailRetrieveParams, options?: RequestOptions, ): APIPromise { return this._client.get(path`/emails/v1/emails/${id}`, { query, ...options }); @@ -24,36 +19,6 @@ export class Emails extends APIResource { /** * Convert design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.emails.renderCreate({ - * design: { - * counters: { - * u_row: 1, - * u_column: 1, - * u_content_text: 1, - * }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` */ renderCreate( params: EmailRenderCreateParams, @@ -65,38 +30,6 @@ export class Emails extends APIResource { /** * Send email with design JSON or HTML content. - * - * @example - * ```ts - * const response = await client.emails.sendCreate({ - * design: { - * counters: { - * u_row: 1, - * u_column: 1, - * u_content_text: 1, - * }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * to: 'test@example.com', - * subject: 'Test', - * }); - * ``` */ sendCreate(params: EmailSendCreateParams, options?: RequestOptions): APIPromise { const { projectId, ...body } = params; @@ -105,14 +38,6 @@ export class Emails extends APIResource { /** * Send email using an existing template with merge tags. - * - * @example - * ```ts - * const response = await client.emails.sendTemplateTemplate({ - * templateId: 'templateId', - * to: 'dev@stainless.com', - * }); - * ``` */ sendTemplateTemplate( params: EmailSendTemplateTemplateParams, @@ -124,79 +49,103 @@ export class Emails extends APIResource { } export interface EmailRetrieveResponse { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; + data?: EmailRetrieveResponse.Data; +} - /** - * Recipient email address - */ - to?: string; +export namespace EmailRetrieveResponse { + export interface Data { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; + } } export interface EmailRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; + data?: EmailRenderCreateResponse.Data; +} + +export namespace EmailRenderCreateResponse { + export interface Data { + /** + * Rendered HTML content + */ + html?: string; + } } export interface EmailSendCreateResponse { - /** - * Unique message identifier - */ - messageId?: string; + data?: EmailSendCreateResponse.Data; +} + +export namespace EmailSendCreateResponse { + export interface Data { + /** + * Unique message identifier + */ + messageId?: string; - status?: 'sent' | 'queued' | 'failed'; + status?: 'sent' | 'queued' | 'failed'; + } } export interface EmailSendTemplateTemplateResponse { - /** - * Unique message identifier - */ - messageId?: string; + data?: EmailSendTemplateTemplateResponse.Data; +} - status?: 'sent' | 'queued' | 'failed'; +export namespace EmailSendTemplateTemplateResponse { + export interface Data { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; + } } export interface EmailRetrieveParams { /** - * The project ID (required for PAT auth, not needed for API Key auth) + * The project ID */ - projectId?: string; + projectId: string; } export interface EmailRenderCreateParams { /** - * Body param: Proprietary design format JSON + * Query param: The project ID */ - design: { [key: string]: unknown }; + projectId: string; /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) + * Body param: Proprietary design format JSON */ - projectId?: string; + design: { [key: string]: unknown }; /** * Body param: Optional merge tags for personalization @@ -206,9 +155,9 @@ export interface EmailRenderCreateParams { export interface EmailSendCreateParams { /** - * Body param: Proprietary design format JSON + * Query param: The project ID */ - design: { [key: string]: unknown }; + projectId: string; /** * Body param: Recipient email address @@ -216,9 +165,9 @@ export interface EmailSendCreateParams { to: string; /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) + * Body param: Proprietary design format JSON */ - projectId?: string; + design?: { [key: string]: unknown }; /** * Body param: HTML content to send @@ -237,6 +186,11 @@ export interface EmailSendCreateParams { } export interface EmailSendTemplateTemplateParams { + /** + * Query param: The project ID + */ + projectId: string; + /** * Body param: ID of the template to use */ @@ -247,11 +201,6 @@ export interface EmailSendTemplateTemplateParams { */ to: string; - /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) - */ - projectId?: string; - /** * Body param: Optional merge tags for personalization */ diff --git a/src/resources/export.ts b/src/resources/export.ts new file mode 100644 index 0000000..a32bee5 --- /dev/null +++ b/src/resources/export.ts @@ -0,0 +1,116 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class Export extends APIResource { + /** + * Export design to HTML. + */ + htmlList(query: ExportHTMLListParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/html', { query, ...options }); + } + + /** + * Export design to image. + */ + imageList(query: ExportImageListParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/image', { query, ...options }); + } + + /** + * Export design to PDF. + */ + pdfList(query: ExportPdfListParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/pdf', { query, ...options }); + } + + /** + * Export design to ZIP archive. + */ + zipList(query: ExportZipListParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/zip', { query, ...options }); + } +} + +export interface ExportHTMLListResponse { + data?: ExportHTMLListResponse.Data; +} + +export namespace ExportHTMLListResponse { + export interface Data { + success?: boolean; + } +} + +export interface ExportImageListResponse { + data?: ExportImageListResponse.Data; +} + +export namespace ExportImageListResponse { + export interface Data { + success?: boolean; + } +} + +export interface ExportPdfListResponse { + data?: ExportPdfListResponse.Data; +} + +export namespace ExportPdfListResponse { + export interface Data { + success?: boolean; + } +} + +export interface ExportZipListResponse { + data?: ExportZipListResponse.Data; +} + +export namespace ExportZipListResponse { + export interface Data { + success?: boolean; + } +} + +export interface ExportHTMLListParams { + /** + * The project ID + */ + projectId: string; +} + +export interface ExportImageListParams { + /** + * The project ID + */ + projectId: string; +} + +export interface ExportPdfListParams { + /** + * The project ID + */ + projectId: string; +} + +export interface ExportZipListParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Export { + export { + type ExportHTMLListResponse as ExportHTMLListResponse, + type ExportImageListResponse as ExportImageListResponse, + type ExportPdfListResponse as ExportPdfListResponse, + type ExportZipListResponse as ExportZipListResponse, + type ExportHTMLListParams as ExportHTMLListParams, + type ExportImageListParams as ExportImageListParams, + type ExportPdfListParams as ExportPdfListParams, + type ExportZipListParams as ExportZipListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 8d5eb48..a26d88e 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -20,13 +20,20 @@ export { type EmailSendCreateParams, type EmailSendTemplateTemplateParams, } from './emails'; +export { + Export, + type ExportHTMLListResponse, + type ExportImageListResponse, + type ExportPdfListResponse, + type ExportZipListResponse, + type ExportHTMLListParams, + type ExportImageListParams, + type ExportPdfListParams, + type ExportZipListParams, +} from './export'; export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; export { Project, - type ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse, type ProjectCurrentListResponse, type ProjectDomainsCreateResponse, type ProjectDomainsListResponse, @@ -36,13 +43,8 @@ export { type ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse, - type ProjectTokensDeleteResponse, - type ProjectTokensListResponse, type ProjectWorkspacesListResponse, type ProjectWorkspacesRetrieveResponse, - type ProjectAPIKeysCreateParams, - type ProjectAPIKeysListParams, - type ProjectAPIKeysUpdateParams, type ProjectCurrentListParams, type ProjectDomainsCreateParams, type ProjectDomainsListParams, @@ -50,4 +52,5 @@ export { type ProjectTemplatesCreateParams, type ProjectTemplatesListParams, type ProjectTemplatesUpdateParams, + type ProjectTemplatesListResponsesCursorPage, } from './project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 8da1d66..067aa07 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -7,36 +7,6 @@ import { RequestOptions } from '../internal/request-options'; export class Pages extends APIResource { /** * Convert page design JSON to HTML with optional merge tags. - * - * @example - * ```ts - * const response = await client.pages.renderCreate({ - * design: { - * counters: { - * u_row: 1, - * u_column: 1, - * u_content_text: 1, - * }, - * body: { - * rows: [ - * { - * cells: [1], - * columns: [ - * { - * contents: [ - * { - * type: 'text', - * values: { text: 'Hello World' }, - * }, - * ], - * }, - * ], - * }, - * ], - * }, - * }, - * }); - * ``` */ renderCreate( params: PageRenderCreateParams, @@ -48,22 +18,28 @@ export class Pages extends APIResource { } export interface PageRenderCreateResponse { - /** - * Rendered HTML content - */ - html?: string; + data?: PageRenderCreateResponse.Data; +} + +export namespace PageRenderCreateResponse { + export interface Data { + /** + * Rendered HTML content + */ + html?: string; + } } export interface PageRenderCreateParams { /** - * Body param: Proprietary design format JSON + * Query param: The project ID */ - design: { [key: string]: unknown }; + projectId: string; /** - * Query param: The project ID (required for PAT auth, not needed for API Key auth) + * Body param: Proprietary design format JSON */ - projectId?: string; + design: { [key: string]: unknown }; /** * Body param: Optional merge tags for personalization diff --git a/src/resources/project.ts b/src/resources/project.ts index b5ea982..20fe5e6 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -2,60 +2,12 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; export class Project extends APIResource { - /** - * Create a new API key for the project. - */ - apiKeysCreate( - params: ProjectAPIKeysCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/project/v1/api-keys', { query: { projectId }, body, ...options }); - } - - /** - * Revoke API key. - */ - apiKeysDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/api-keys/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all API keys for the project. - */ - apiKeysList( - query: ProjectAPIKeysListParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/project/v1/api-keys', { query, ...options }); - } - - /** - * Get API key details by ID. - */ - apiKeysRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/api-keys/${id}`, options); - } - - /** - * Update API key settings. - */ - apiKeysUpdate( - id: string, - body: ProjectAPIKeysUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/api-keys/${id}`, { body, ...options }); - } - /** * Get project details for the specified project. */ @@ -137,13 +89,17 @@ export class Project extends APIResource { } /** - * Get all project templates. + * List project templates with cursor-based pagination. Returns templates in + * descending order by update time. */ templatesList( query: ProjectTemplatesListParams, options?: RequestOptions, - ): APIPromise { - return this._client.get('/project/v1/templates', { query, ...options }); + ): PagePromise { + return this._client.getAPIList('/project/v1/templates', CursorPage, { + query, + ...options, + }); } /** @@ -164,20 +120,6 @@ export class Project extends APIResource { return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); } - /** - * Delete a personal access token. You can only delete your own tokens. - */ - tokensDelete(tokenID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/tokens/${tokenID}`, options); - } - - /** - * List all personal access tokens for the authenticated user. - */ - tokensList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/tokens', options); - } - /** * Get all workspaces accessible by the current token. */ @@ -196,91 +138,7 @@ export class Project extends APIResource { } } -export interface ProjectAPIKeysCreateResponse { - data?: ProjectAPIKeysCreateResponse.Data; -} - -export namespace ProjectAPIKeysCreateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysListResponse { - data?: Array; -} - -export namespace ProjectAPIKeysListResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysRetrieveResponse { - data?: ProjectAPIKeysRetrieveResponse.Data; -} - -export namespace ProjectAPIKeysRetrieveResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} - -export interface ProjectAPIKeysUpdateResponse { - data?: ProjectAPIKeysUpdateResponse.Data; -} - -export namespace ProjectAPIKeysUpdateResponse { - export interface Data { - id?: string; - - active?: boolean; - - createdAt?: string; - - domains?: Array; - - key?: string; - - lastUsed?: string; - - name?: string; - } -} +export type ProjectTemplatesListResponsesCursorPage = CursorPage; export interface ProjectCurrentListResponse { data?: ProjectCurrentListResponse.Data; @@ -386,38 +244,46 @@ export interface ProjectTemplatesCreateResponse { export namespace ProjectTemplatesCreateResponse { export interface Data { + /** + * Template ID + */ id?: string; - body?: string; - createdAt?: string; - name?: string; + /** + * Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; - subject?: string; + /** + * Template name + */ + name?: string; updatedAt?: string; } } export interface ProjectTemplatesListResponse { - data?: Array; -} - -export namespace ProjectTemplatesListResponse { - export interface Data { - id?: string; - - body?: string; + /** + * Template ID + */ + id?: string; - createdAt?: string; + createdAt?: string; - name?: string; + /** + * Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; - subject?: string; + /** + * Template name + */ + name?: string; - updatedAt?: string; - } + updatedAt?: string; } export interface ProjectTemplatesRetrieveResponse { @@ -460,36 +326,6 @@ export namespace ProjectTemplatesUpdateResponse { } } -export interface ProjectTokensDeleteResponse { - message?: string; - - success?: boolean; -} - -export interface ProjectTokensListResponse { - data?: Array; -} - -export namespace ProjectTokensListResponse { - export interface Data { - id?: number; - - createdAt?: string; - - expiresAt?: string | null; - - lastUsedAt?: string | null; - - name?: string; - - scope?: string; - - workspaceId?: number | null; - - workspaceName?: string | null; - } -} - export interface ProjectWorkspacesListResponse { data?: Array; } @@ -526,47 +362,6 @@ export namespace ProjectWorkspacesRetrieveResponse { } } -export interface ProjectAPIKeysCreateParams { - /** - * Query param: The project ID to create API key for - */ - projectId: string; - - /** - * Body param: Name for the API key - */ - name: string; - - /** - * Body param: Allowed domains for this API key - */ - domains?: Array; -} - -export interface ProjectAPIKeysListParams { - /** - * The project ID to get API keys for - */ - projectId: string; -} - -export interface ProjectAPIKeysUpdateParams { - /** - * Whether the API key is active - */ - active?: boolean; - - /** - * Updated allowed domains - */ - domains?: Array; - - /** - * Updated name for the API key - */ - name?: string; -} - export interface ProjectCurrentListParams { /** * The project ID @@ -576,7 +371,7 @@ export interface ProjectCurrentListParams { export interface ProjectDomainsCreateParams { /** - * Query param: The project ID to add domain to + * Query param: The project ID */ projectId: string; @@ -588,7 +383,7 @@ export interface ProjectDomainsCreateParams { export interface ProjectDomainsListParams { /** - * The project ID to get domains for + * The project ID */ projectId: string; } @@ -602,7 +397,7 @@ export interface ProjectDomainsUpdateParams { export interface ProjectTemplatesCreateParams { /** - * Query param: The project ID to create template for + * Query param: The project ID to create the template in */ projectId: string; @@ -612,21 +407,26 @@ export interface ProjectTemplatesCreateParams { name: string; /** - * Body param: Email body content + * Body param: Template type/display mode */ - body?: string; + displayMode?: 'email' | 'web' | 'document'; +} +export interface ProjectTemplatesListParams extends CursorPageParams { /** - * Body param: Email subject line + * The project ID to list templates for */ - subject?: string; -} + projectId: string; -export interface ProjectTemplatesListParams { /** - * The project ID to get templates for + * Filter by template type */ - projectId: string; + displayMode?: 'email' | 'web' | 'document'; + + /** + * Filter by name (case-insensitive search) + */ + name?: string; } export interface ProjectTemplatesUpdateParams { @@ -648,10 +448,6 @@ export interface ProjectTemplatesUpdateParams { export declare namespace Project { export { - type ProjectAPIKeysCreateResponse as ProjectAPIKeysCreateResponse, - type ProjectAPIKeysListResponse as ProjectAPIKeysListResponse, - type ProjectAPIKeysRetrieveResponse as ProjectAPIKeysRetrieveResponse, - type ProjectAPIKeysUpdateResponse as ProjectAPIKeysUpdateResponse, type ProjectCurrentListResponse as ProjectCurrentListResponse, type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, type ProjectDomainsListResponse as ProjectDomainsListResponse, @@ -661,13 +457,9 @@ export declare namespace Project { type ProjectTemplatesListResponse as ProjectTemplatesListResponse, type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectTokensDeleteResponse as ProjectTokensDeleteResponse, - type ProjectTokensListResponse as ProjectTokensListResponse, type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, - type ProjectAPIKeysCreateParams as ProjectAPIKeysCreateParams, - type ProjectAPIKeysListParams as ProjectAPIKeysListParams, - type ProjectAPIKeysUpdateParams as ProjectAPIKeysUpdateParams, + type ProjectTemplatesListResponsesCursorPage as ProjectTemplatesListResponsesCursorPage, type ProjectCurrentListParams as ProjectCurrentListParams, type ProjectDomainsCreateParams as ProjectDomainsCreateParams, type ProjectDomainsListParams as ProjectDomainsListParams, diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 6d7dd4b..4453628 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -3,13 +3,13 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource documents', () => { - test('documentsRetrieve', async () => { - const responsePromise = client.documents.documentsRetrieve('id'); + test('documentsRetrieve: only required params', async () => { + const responsePromise = client.documents.documentsRetrieve('id', { projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,19 +19,12 @@ describe('resource documents', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('documentsRetrieve: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.documents.documentsRetrieve( - 'id', - { projectId: 'projectId' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); + test('documentsRetrieve: required and optional params', async () => { + const response = await client.documents.documentsRetrieve('id', { projectId: 'projectId' }); }); test('generateCreate: only required params', async () => { - const responsePromise = client.documents.generateCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.documents.generateCreate({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -43,8 +36,8 @@ describe('resource documents', () => { test('generateCreate: required and optional params', async () => { const response = await client.documents.generateCreate({ - design: { counters: 'bar', body: 'bar' }, projectId: 'projectId', + design: { foo: 'bar' }, filename: 'filename', html: 'html', mergeTags: { foo: 'string' }, @@ -53,7 +46,10 @@ describe('resource documents', () => { }); test('generateTemplateTemplate: only required params', async () => { - const responsePromise = client.documents.generateTemplateTemplate({ templateId: 'templateId' }); + const responsePromise = client.documents.generateTemplateTemplate({ + projectId: 'projectId', + templateId: 'templateId', + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -65,8 +61,8 @@ describe('resource documents', () => { test('generateTemplateTemplate: required and optional params', async () => { const response = await client.documents.generateTemplateTemplate({ - templateId: 'templateId', projectId: 'projectId', + templateId: 'templateId', filename: 'filename', mergeTags: { foo: 'string' }, }); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/emails.test.ts index ab98cc4..210fea6 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/emails.test.ts @@ -3,13 +3,13 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource emails', () => { - test('retrieve', async () => { - const responsePromise = client.emails.retrieve('id'); + test('retrieve: only required params', async () => { + const responsePromise = client.emails.retrieve('id', { projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,15 +19,15 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('retrieve: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.emails.retrieve('id', { projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); + test('retrieve: required and optional params', async () => { + const response = await client.emails.retrieve('id', { projectId: 'projectId' }); }); test('renderCreate: only required params', async () => { - const responsePromise = client.emails.renderCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.emails.renderCreate({ + projectId: 'projectId', + design: { foo: 'bar' }, + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -39,17 +39,14 @@ describe('resource emails', () => { test('renderCreate: required and optional params', async () => { const response = await client.emails.renderCreate({ - design: { counters: 'bar', body: 'bar' }, projectId: 'projectId', + design: { foo: 'bar' }, mergeTags: { foo: 'string' }, }); }); test('sendCreate: only required params', async () => { - const responsePromise = client.emails.sendCreate({ - design: { counters: 'bar', body: 'bar' }, - to: 'test@example.com', - }); + const responsePromise = client.emails.sendCreate({ projectId: 'projectId', to: 'dev@stainless.com' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -61,17 +58,18 @@ describe('resource emails', () => { test('sendCreate: required and optional params', async () => { const response = await client.emails.sendCreate({ - design: { counters: 'bar', body: 'bar' }, - to: 'test@example.com', projectId: 'projectId', + to: 'dev@stainless.com', + design: { foo: 'bar' }, html: 'html', mergeTags: { foo: 'string' }, - subject: 'Test', + subject: 'subject', }); }); test('sendTemplateTemplate: only required params', async () => { const responsePromise = client.emails.sendTemplateTemplate({ + projectId: 'projectId', templateId: 'templateId', to: 'dev@stainless.com', }); @@ -86,9 +84,9 @@ describe('resource emails', () => { test('sendTemplateTemplate: required and optional params', async () => { const response = await client.emails.sendTemplateTemplate({ + projectId: 'projectId', templateId: 'templateId', to: 'dev@stainless.com', - projectId: 'projectId', mergeTags: { foo: 'string' }, subject: 'subject', }); diff --git a/tests/api-resources/export.test.ts b/tests/api-resources/export.test.ts new file mode 100644 index 0000000..30efddd --- /dev/null +++ b/tests/api-resources/export.test.ts @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource export', () => { + test('htmlList: only required params', async () => { + const responsePromise = client.export.htmlList({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('htmlList: required and optional params', async () => { + const response = await client.export.htmlList({ projectId: 'projectId' }); + }); + + test('imageList: only required params', async () => { + const responsePromise = client.export.imageList({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('imageList: required and optional params', async () => { + const response = await client.export.imageList({ projectId: 'projectId' }); + }); + + test('pdfList: only required params', async () => { + const responsePromise = client.export.pdfList({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('pdfList: required and optional params', async () => { + const response = await client.export.pdfList({ projectId: 'projectId' }); + }); + + test('zipList: only required params', async () => { + const responsePromise = client.export.zipList({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('zipList: required and optional params', async () => { + const response = await client.export.zipList({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/pages.test.ts index 489872e..b343b11 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/pages.test.ts @@ -3,13 +3,16 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource pages', () => { test('renderCreate: only required params', async () => { - const responsePromise = client.pages.renderCreate({ design: { counters: 'bar', body: 'bar' } }); + const responsePromise = client.pages.renderCreate({ + projectId: 'projectId', + design: { foo: 'bar' }, + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,8 +24,8 @@ describe('resource pages', () => { test('renderCreate: required and optional params', async () => { const response = await client.pages.renderCreate({ - design: { counters: 'bar', body: 'bar' }, projectId: 'projectId', + design: { foo: 'bar' }, mergeTags: { foo: 'string' }, }); }); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts index f76f5ed..62f3eca 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/project.test.ts @@ -3,93 +3,11 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource project', () => { - test('apiKeysCreate: only required params', async () => { - const responsePromise = client.project.apiKeysCreate({ projectId: 'projectId', name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysCreate: required and optional params', async () => { - const response = await client.project.apiKeysCreate({ - projectId: 'projectId', - name: 'name', - domains: ['string'], - }); - }); - - test('apiKeysDelete', async () => { - const responsePromise = client.project.apiKeysDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysList: only required params', async () => { - const responsePromise = client.project.apiKeysList({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysList: required and optional params', async () => { - const response = await client.project.apiKeysList({ projectId: 'projectId' }); - }); - - test('apiKeysRetrieve', async () => { - const responsePromise = client.project.apiKeysRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysUpdate', async () => { - const responsePromise = client.project.apiKeysUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('apiKeysUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.apiKeysUpdate( - 'id', - { - active: true, - domains: ['string'], - name: 'name', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - test('currentList: only required params', async () => { const responsePromise = client.project.currentList({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); @@ -190,8 +108,7 @@ describe('resource project', () => { const response = await client.project.templatesCreate({ projectId: 'projectId', name: 'name', - body: 'body', - subject: 'subject', + displayMode: 'email', }); }); @@ -218,7 +135,13 @@ describe('resource project', () => { }); test('templatesList: required and optional params', async () => { - const response = await client.project.templatesList({ projectId: 'projectId' }); + const response = await client.project.templatesList({ + projectId: 'projectId', + cursor: 'cursor', + displayMode: 'email', + limit: 1, + name: 'name', + }); }); test('templatesRetrieve', async () => { @@ -258,28 +181,6 @@ describe('resource project', () => { ).rejects.toThrow(Unlayer.NotFoundError); }); - test('tokensDelete', async () => { - const responsePromise = client.project.tokensDelete('tokenId'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('tokensList', async () => { - const responsePromise = client.project.tokensList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - test('workspacesList', async () => { const responsePromise = client.project.workspacesList(); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/index.test.ts b/tests/index.test.ts index c1ab24a..553cc61 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -23,7 +23,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-My-Default-Header': '2' }, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); test('they are used in the request', async () => { @@ -90,7 +90,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'debug', - apiKey: 'My API Key', + accessToken: 'My Access Token', }); await forceAPIResponseForClient(client); @@ -98,7 +98,7 @@ describe('instantiate client', () => { }); test('default logLevel is warn', async () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.logLevel).toBe('warn'); }); @@ -114,7 +114,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'info', - apiKey: 'My API Key', + accessToken: 'My Access Token', }); await forceAPIResponseForClient(client); @@ -131,7 +131,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, accessToken: 'My Access Token' }); expect(client.logLevel).toBe('debug'); await forceAPIResponseForClient(client); @@ -148,7 +148,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); + const client = new Unlayer({ logger: logger, accessToken: 'My Access Token' }); expect(client.logLevel).toBe('warn'); expect(warnMock).toHaveBeenCalledWith( 'process.env[\'UNLAYER_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', @@ -168,7 +168,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'off', - apiKey: 'My API Key', + accessToken: 'My Access Token', }); await forceAPIResponseForClient(client); @@ -188,7 +188,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'debug', - apiKey: 'My API Key', + accessToken: 'My Access Token', }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); @@ -200,7 +200,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' }, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); @@ -209,7 +209,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo', hello: 'world' }, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); @@ -218,7 +218,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' }, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); @@ -227,7 +227,7 @@ describe('instantiate client', () => { test('custom fetch', async () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: (url) => { return Promise.resolve( new Response(JSON.stringify({ url, custom: true }), { @@ -245,7 +245,7 @@ describe('instantiate client', () => { // make sure the global fetch type is assignable to our Fetch type const client = new Unlayer({ baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: defaultFetch, }); }); @@ -253,7 +253,7 @@ describe('instantiate client', () => { test('custom signal', async () => { const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: (...args) => { return new Promise((resolve, reject) => setTimeout( @@ -285,7 +285,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: testFetch, }); @@ -295,12 +295,18 @@ describe('instantiate client', () => { describe('baseUrl', () => { test('trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/custom/path/', + accessToken: 'My Access Token', + }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); test('no trailing slash', () => { - const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); + const client = new Unlayer({ + baseURL: 'http://localhost:5000/custom/path', + accessToken: 'My Access Token', + }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); @@ -309,25 +315,25 @@ describe('instantiate client', () => { }); test('explicit option', () => { - const client = new Unlayer({ baseURL: 'https://example.com', apiKey: 'My API Key' }); + const client = new Unlayer({ baseURL: 'https://example.com', accessToken: 'My Access Token' }); expect(client.baseURL).toEqual('https://example.com'); }); test('env variable', () => { process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.baseURL).toEqual('https://example.com/from_env'); }); test('empty env variable', () => { process.env['UNLAYER_BASE_URL'] = ''; // empty - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('blank env variable', () => { process.env['UNLAYER_BASE_URL'] = ' '; // blank - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); @@ -335,13 +341,13 @@ describe('instantiate client', () => { process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; expect( - () => new Unlayer({ apiKey: 'My API Key', environment: 'production' }), + () => new Unlayer({ accessToken: 'My Access Token', environment: 'production' }), ).toThrowErrorMatchingInlineSnapshot( `"Ambiguous URL; The \`baseURL\` option (or UNLAYER_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, ); const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', baseURL: null, environment: 'production', }); @@ -349,14 +355,14 @@ describe('instantiate client', () => { }); test('in request options', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/option/foo', ); }); test('in request options overridden by client options', () => { - const client = new Unlayer({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + const client = new Unlayer({ accessToken: 'My Access Token', baseURL: 'http://localhost:5000/client' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/client/foo', ); @@ -364,7 +370,7 @@ describe('instantiate client', () => { test('in request options overridden by env variable', () => { process.env['UNLAYER_BASE_URL'] = 'http://localhost:5000/env'; - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/env/foo', ); @@ -372,11 +378,11 @@ describe('instantiate client', () => { }); test('maxRetries option is correctly set', () => { - const client = new Unlayer({ maxRetries: 4, apiKey: 'My API Key' }); + const client = new Unlayer({ maxRetries: 4, accessToken: 'My Access Token' }); expect(client.maxRetries).toEqual(4); // default - const client2 = new Unlayer({ apiKey: 'My API Key' }); + const client2 = new Unlayer({ accessToken: 'My Access Token' }); expect(client2.maxRetries).toEqual(2); }); @@ -385,7 +391,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); const newClient = client.withOptions({ @@ -411,7 +417,7 @@ describe('instantiate client', () => { baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-Test-Header': 'test-value' }, defaultQuery: { 'test-param': 'test-value' }, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); const newClient = client.withOptions({ @@ -429,7 +435,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, - apiKey: 'My API Key', + accessToken: 'My Access Token', }); // Modify the client properties directly after creation @@ -458,21 +464,21 @@ describe('instantiate client', () => { test('with environment variable arguments', () => { // set options via env var - process.env['UNLAYER_API_KEY'] = 'My API Key'; + process.env['UNLAYER_ACCESS_TOKEN'] = 'My Access Token'; const client = new Unlayer(); - expect(client.apiKey).toBe('My API Key'); + expect(client.accessToken).toBe('My Access Token'); }); test('with overridden environment variable arguments', () => { // set options via env var - process.env['UNLAYER_API_KEY'] = 'another My API Key'; - const client = new Unlayer({ apiKey: 'My API Key' }); - expect(client.apiKey).toBe('My API Key'); + process.env['UNLAYER_ACCESS_TOKEN'] = 'another My Access Token'; + const client = new Unlayer({ accessToken: 'My Access Token' }); + expect(client.accessToken).toBe('My Access Token'); }); }); describe('request building', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); describe('custom headers', () => { test('handles undefined', async () => { @@ -491,7 +497,7 @@ describe('request building', () => { }); describe('default encoder', () => { - const client = new Unlayer({ apiKey: 'My API Key' }); + const client = new Unlayer({ accessToken: 'My Access Token' }); class Serializable { toJSON() { @@ -577,7 +583,7 @@ describe('retries', () => { }; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', timeout: 10, fetch: testFetch, }); @@ -611,7 +617,7 @@ describe('retries', () => { }; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: testFetch, maxRetries: 4, }); @@ -639,7 +645,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: testFetch, maxRetries: 4, }); @@ -672,7 +678,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: testFetch, maxRetries: 4, defaultHeaders: { 'X-Stainless-Retry-Count': null }, @@ -705,7 +711,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - apiKey: 'My API Key', + accessToken: 'My Access Token', fetch: testFetch, maxRetries: 4, }); @@ -738,7 +744,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ accessToken: 'My Access Token', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -768,7 +774,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Unlayer({ accessToken: 'My Access Token', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); From 56e8ec70aa3f6668f42f924f8db2ce6c8de2d4e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 03:50:03 +0000 Subject: [PATCH 041/118] chore(ci): upgrade `actions/github-script` --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9dba85..746dabb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/unlayer-typescript' id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); From 8a164ea3aa7096e9580ce2a855a3ef7d388e5cce Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 Jan 2026 16:24:41 +0000 Subject: [PATCH 042/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ead84b6..2bb500f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 25 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-42ce261f6dec6bdbfe9b98a3835cbb95c67440a58023646fe03ab0aa0745d671.yml -openapi_spec_hash: 0f18f2d5ea38b837ccc0156ea80d85cd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-077d753eb6d4f805b2f84bf887289213f91c1da5f5a3a4e1e36e1da3689efb46.yml +openapi_spec_hash: b210022cf72d9a38fe1baee599054518 config_hash: ae90f2806448a012e25917d01699b3a5 From dab1092a82676c78a4ceb46b178ddecedb7285bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 04:14:00 +0000 Subject: [PATCH 043/118] fix(client): avoid memory leak with abort signals --- src/client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index a1a0dce..0397e27 100644 --- a/src/client.ts +++ b/src/client.ts @@ -591,9 +591,10 @@ export class Unlayer { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - if (signal) signal.addEventListener('abort', () => controller.abort()); + const abort = controller.abort.bind(controller); + if (signal) signal.addEventListener('abort', abort, { once: true }); - const timeout = setTimeout(() => controller.abort(), ms); + const timeout = setTimeout(abort, ms); const isReadableBody = ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || From 7c68756f53ca5a4dcb0b6c31a836b3038032f5be Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 04:16:22 +0000 Subject: [PATCH 044/118] chore(client): do not parse responses with empty content-length --- src/internal/parse.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/internal/parse.ts b/src/internal/parse.ts index a2edd58..2af5769 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -29,6 +29,12 @@ export async function defaultParseResponse(client: Unlayer, props: APIRespons const mediaType = contentType?.split(';')[0]?.trim(); const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined as T; + } + const json = await response.json(); return json as T; } From ee78663052838a52bc2bef94816ed0a5378dfd7e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 03:41:08 +0000 Subject: [PATCH 045/118] chore(client): restructure abort controller binding --- src/client.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 0397e27..a860abd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -591,7 +591,7 @@ export class Unlayer { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - const abort = controller.abort.bind(controller); + const abort = this._makeAbort(controller); if (signal) signal.addEventListener('abort', abort, { once: true }); const timeout = setTimeout(abort, ms); @@ -617,6 +617,7 @@ export class Unlayer { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); + if (signal) signal.removeEventListener('abort', abort); } } @@ -761,6 +762,12 @@ export class Unlayer { return headers.values; } + private _makeAbort(controller: AbortController) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; From 779cbec0731764603e578e1b4160e2c8be4e2f78 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:12:09 +0000 Subject: [PATCH 046/118] fix(client): avoid removing abort listener too early --- src/client.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index a860abd..920876a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -617,7 +617,6 @@ export class Unlayer { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); - if (signal) signal.removeEventListener('abort', abort); } } From 0a6168a6cb89a07c0bb392688bf488c6c99224ca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:13:02 +0000 Subject: [PATCH 047/118] chore(internal): fix pagination internals not accepting option promises --- src/client.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 920876a..1d5f58c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -568,9 +568,14 @@ export class Unlayer { getAPIList = Pagination.AbstractPage>( path: string, Page: new (...args: any[]) => PageClass, - opts?: RequestOptions, + opts?: PromiseOrValue, ): Pagination.PagePromise { - return this.requestAPIList(Page, { method: 'get', path, ...opts }); + return this.requestAPIList( + Page, + opts && 'then' in opts ? + opts.then((opts) => ({ method: 'get', path, ...opts })) + : { method: 'get', path, ...opts }, + ); } requestAPIList< @@ -578,7 +583,7 @@ export class Unlayer { PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, >( Page: new (...args: ConstructorParameters) => PageClass, - options: FinalRequestOptions, + options: PromiseOrValue, ): Pagination.PagePromise { const request = this.makeRequest(options, null, undefined); return new Pagination.PagePromise(this as any as Unlayer, request, Page); From d4738c26d5bb53aecf85b3e1c793fa930816e569 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 04:05:00 +0000 Subject: [PATCH 048/118] chore(internal): avoid type checking errors with ts-reset --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 1d5f58c..1d3ac41 100644 --- a/src/client.ts +++ b/src/client.ts @@ -531,7 +531,7 @@ export class Unlayer { loggerFor(this).info(`${responseInfo} - ${retryMessage}`); const errText = await response.text().catch((err: any) => castToError(err).message); - const errJSON = safeJSON(errText); + const errJSON = safeJSON(errText) as any; const errMessage = errJSON ? undefined : errText; loggerFor(this).debug( From aab6c8b084d5e6aa0eb31f4a402645b8eb46819c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:23:43 +0000 Subject: [PATCH 049/118] feat(api): api update --- .stats.yml | 4 +- README.md | 61 +-- api.md | 218 ++++++-- src/client.ts | 119 +---- src/resources/convert.ts | 3 + src/resources/convert/convert.ts | 29 ++ src/resources/convert/full-to-simple.ts | 53 ++ src/resources/convert/index.ts | 13 + src/resources/convert/simple-to-full.ts | 63 +++ src/resources/documents.ts | 210 +------- src/resources/documents/documents.ts | 109 ++++ src/resources/documents/generate-template.ts | 72 +++ src/resources/documents/generate.ts | 79 +++ src/resources/documents/index.ts | 9 + src/resources/emails.ts | 225 +-------- src/resources/emails/emails.ts | 103 ++++ src/resources/emails/index.ts | 10 + src/resources/emails/render.ts | 49 ++ src/resources/emails/send-template.ts | 64 +++ src/resources/emails/send.ts | 66 +++ src/resources/export.ts | 115 +---- src/resources/export/export.ts | 49 ++ src/resources/export/html.ts | 35 ++ src/resources/export/image.ts | 38 ++ src/resources/export/index.ts | 7 + src/resources/export/pdf.ts | 35 ++ src/resources/export/zip.ts | 35 ++ src/resources/index.ts | 60 +-- src/resources/pages.ts | 54 +- src/resources/pages/index.ts | 4 + src/resources/pages/pages.ts | 19 + src/resources/pages/render.ts | 49 ++ src/resources/project.ts | 470 +----------------- src/resources/project/current.ts | 54 ++ src/resources/project/domains.ts | 162 ++++++ src/resources/project/index.ts | 25 + src/resources/project/project.ts | 77 +++ src/resources/project/templates.ts | 230 +++++++++ src/resources/project/workspaces.ts | 65 +++ .../convert/full-to-simple.test.ts | 33 ++ .../convert/simple-to-full.test.ts | 34 ++ tests/api-resources/documents.test.ts | 70 --- .../api-resources/documents/documents.test.ts | 25 + .../documents/generate-template.test.ts | 33 ++ .../api-resources/documents/generate.test.ts | 32 ++ tests/api-resources/emails/emails.test.ts | 25 + .../{pages.test.ts => emails/render.test.ts} | 10 +- .../emails/send-template.test.ts | 35 ++ tests/api-resources/emails/send.test.ts | 32 ++ tests/api-resources/export/html.test.ts | 25 + tests/api-resources/export/image.test.ts | 25 + tests/api-resources/export/pdf.test.ts | 25 + tests/api-resources/export/zip.test.ts | 25 + tests/api-resources/pages/render.test.ts | 32 ++ tests/api-resources/project.test.ts | 205 -------- tests/api-resources/project/current.test.ts | 25 + .../domains.test.ts} | 48 +- .../templates.test.ts} | 86 ++-- .../api-resources/project/workspaces.test.ts | 32 ++ 59 files changed, 2332 insertions(+), 1667 deletions(-) create mode 100644 src/resources/convert.ts create mode 100644 src/resources/convert/convert.ts create mode 100644 src/resources/convert/full-to-simple.ts create mode 100644 src/resources/convert/index.ts create mode 100644 src/resources/convert/simple-to-full.ts create mode 100644 src/resources/documents/documents.ts create mode 100644 src/resources/documents/generate-template.ts create mode 100644 src/resources/documents/generate.ts create mode 100644 src/resources/documents/index.ts create mode 100644 src/resources/emails/emails.ts create mode 100644 src/resources/emails/index.ts create mode 100644 src/resources/emails/render.ts create mode 100644 src/resources/emails/send-template.ts create mode 100644 src/resources/emails/send.ts create mode 100644 src/resources/export/export.ts create mode 100644 src/resources/export/html.ts create mode 100644 src/resources/export/image.ts create mode 100644 src/resources/export/index.ts create mode 100644 src/resources/export/pdf.ts create mode 100644 src/resources/export/zip.ts create mode 100644 src/resources/pages/index.ts create mode 100644 src/resources/pages/pages.ts create mode 100644 src/resources/pages/render.ts create mode 100644 src/resources/project/current.ts create mode 100644 src/resources/project/domains.ts create mode 100644 src/resources/project/index.ts create mode 100644 src/resources/project/project.ts create mode 100644 src/resources/project/templates.ts create mode 100644 src/resources/project/workspaces.ts create mode 100644 tests/api-resources/convert/full-to-simple.test.ts create mode 100644 tests/api-resources/convert/simple-to-full.test.ts delete mode 100644 tests/api-resources/documents.test.ts create mode 100644 tests/api-resources/documents/documents.test.ts create mode 100644 tests/api-resources/documents/generate-template.test.ts create mode 100644 tests/api-resources/documents/generate.test.ts create mode 100644 tests/api-resources/emails/emails.test.ts rename tests/api-resources/{pages.test.ts => emails/render.test.ts} (75%) create mode 100644 tests/api-resources/emails/send-template.test.ts create mode 100644 tests/api-resources/emails/send.test.ts create mode 100644 tests/api-resources/export/html.test.ts create mode 100644 tests/api-resources/export/image.test.ts create mode 100644 tests/api-resources/export/pdf.test.ts create mode 100644 tests/api-resources/export/zip.test.ts create mode 100644 tests/api-resources/pages/render.test.ts delete mode 100644 tests/api-resources/project.test.ts create mode 100644 tests/api-resources/project/current.test.ts rename tests/api-resources/{export.test.ts => project/domains.test.ts} (52%) rename tests/api-resources/{emails.test.ts => project/templates.test.ts} (50%) create mode 100644 tests/api-resources/project/workspaces.test.ts diff --git a/.stats.yml b/.stats.yml index 2bb500f..c33024a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 25 +configured_endpoints: 27 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-077d753eb6d4f805b2f84bf887289213f91c1da5f5a3a4e1e36e1da3689efb46.yml openapi_spec_hash: b210022cf72d9a38fe1baee599054518 -config_hash: ae90f2806448a012e25917d01699b3a5 +config_hash: 15a2f2b4c1b498b9b314d587d6a331d0 diff --git a/README.md b/README.md index 20bceda..9739903 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ const client = new Unlayer({ environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const response = await client.project.currentList({ projectId: 'your-project-id' }); +const fullToSimple = await client.convert.fullToSimple.create({ design: { body: {} } }); -console.log(response.data); +console.log(fullToSimple.data); ``` ### Request & Response types @@ -48,8 +48,9 @@ const client = new Unlayer({ environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const params: Unlayer.ProjectCurrentListParams = { projectId: 'your-project-id' }; -const response: Unlayer.ProjectCurrentListResponse = await client.project.currentList(params); +const params: Unlayer.Convert.FullToSimpleCreateParams = { design: { body: {} } }; +const fullToSimple: Unlayer.Convert.FullToSimpleCreateResponse = + await client.convert.fullToSimple.create(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -62,8 +63,8 @@ a subclass of `APIError` will be thrown: ```ts -const response = await client.project - .currentList({ projectId: 'your-project-id' }) +const fullToSimple = await client.convert.fullToSimple + .create({ design: { body: {} } }) .catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 @@ -104,7 +105,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.project.currentList({ projectId: 'your-project-id' }, { +await client.convert.fullToSimple.create({ design: { body: {} } }, { maxRetries: 5, }); ``` @@ -121,7 +122,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.project.currentList({ projectId: 'your-project-id' }, { +await client.convert.fullToSimple.create({ design: { body: {} } }, { timeout: 5 * 1000, }); ``` @@ -130,40 +131,6 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). -## Auto-pagination - -List methods in the Unlayer API are paginated. -You can use the `for await … of` syntax to iterate through items across all pages: - -```ts -async function fetchAllProjectTemplatesListResponses(params) { - const allProjectTemplatesListResponses = []; - // Automatically fetches more pages as needed. - for await (const projectTemplatesListResponse of client.project.templatesList({ - projectId: 'your-project-id', - limit: 10, - })) { - allProjectTemplatesListResponses.push(projectTemplatesListResponse); - } - return allProjectTemplatesListResponses; -} -``` - -Alternatively, you can request a single page at a time: - -```ts -let page = await client.project.templatesList({ projectId: 'your-project-id', limit: 10 }); -for (const projectTemplatesListResponse of page.data) { - console.log(projectTemplatesListResponse); -} - -// Convenience methods are provided for manually paginating: -while (page.hasNextPage()) { - page = await page.getNextPage(); - // ... -} -``` - ## Advanced Usage ### Accessing raw Response data (e.g., headers) @@ -178,15 +145,15 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.project.currentList({ projectId: 'your-project-id' }).asResponse(); +const response = await client.convert.fullToSimple.create({ design: { body: {} } }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: response, response: raw } = await client.project - .currentList({ projectId: 'your-project-id' }) +const { data: fullToSimple, response: raw } = await client.convert.fullToSimple + .create({ design: { body: {} } }) .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(response.data); +console.log(fullToSimple.data); ``` ### Logging @@ -266,7 +233,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.project.currentList({ +client.convert.fullToSimple.create({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index db34eed..eaccee5 100644 --- a/api.md +++ b/api.md @@ -1,87 +1,203 @@ +# Convert + +## FullToSimple + +Types: + +- FullToSimpleCreateResponse + +Methods: + +- client.convert.fullToSimple.create({ ...params }) -> FullToSimpleCreateResponse + +## SimpleToFull + +Types: + +- SimpleToFullCreateResponse + +Methods: + +- client.convert.simpleToFull.create({ ...params }) -> SimpleToFullCreateResponse + # Documents Types: -- DocumentDocumentsRetrieveResponse -- DocumentGenerateCreateResponse -- DocumentGenerateTemplateTemplateResponse +- DocumentRetrieveResponse + +Methods: + +- client.documents.retrieve(id, { ...params }) -> DocumentRetrieveResponse + +## Generate + +Types: + +- GenerateCreateResponse Methods: -- client.documents.documentsRetrieve(id, { ...params }) -> DocumentDocumentsRetrieveResponse -- client.documents.generateCreate({ ...params }) -> DocumentGenerateCreateResponse -- client.documents.generateTemplateTemplate({ ...params }) -> DocumentGenerateTemplateTemplateResponse +- client.documents.generate.create({ ...params }) -> GenerateCreateResponse + +## GenerateTemplate + +Types: + +- GenerateTemplateCreateResponse + +Methods: + +- client.documents.generateTemplate.create({ ...params }) -> GenerateTemplateCreateResponse # Emails Types: -- EmailRetrieveResponse -- EmailRenderCreateResponse -- EmailSendCreateResponse -- EmailSendTemplateTemplateResponse +- EmailRetrieveResponse + +Methods: + +- client.emails.retrieve(id, { ...params }) -> EmailRetrieveResponse + +## Render + +Types: + +- RenderCreateResponse + +Methods: + +- client.emails.render.create({ ...params }) -> RenderCreateResponse + +## Send + +Types: + +- SendCreateResponse + +Methods: + +- client.emails.send.create({ ...params }) -> SendCreateResponse + +## SendTemplate + +Types: + +- SendTemplateCreateResponse Methods: -- client.emails.retrieve(id, { ...params }) -> EmailRetrieveResponse -- client.emails.renderCreate({ ...params }) -> EmailRenderCreateResponse -- client.emails.sendCreate({ ...params }) -> EmailSendCreateResponse -- client.emails.sendTemplateTemplate({ ...params }) -> EmailSendTemplateTemplateResponse +- client.emails.sendTemplate.create({ ...params }) -> SendTemplateCreateResponse # Export +## HTML + Types: -- ExportHTMLListResponse -- ExportImageListResponse -- ExportPdfListResponse -- ExportZipListResponse +- HTMLRetrieveResponse Methods: -- client.export.htmlList({ ...params }) -> ExportHTMLListResponse -- client.export.imageList({ ...params }) -> ExportImageListResponse -- client.export.pdfList({ ...params }) -> ExportPdfListResponse -- client.export.zipList({ ...params }) -> ExportZipListResponse +- client.export.html.retrieve({ ...params }) -> HTMLRetrieveResponse + +## Image + +Types: + +- ImageRetrieveResponse + +Methods: + +- client.export.image.retrieve({ ...params }) -> ImageRetrieveResponse + +## Pdf + +Types: + +- PdfRetrieveResponse + +Methods: + +- client.export.pdf.retrieve({ ...params }) -> PdfRetrieveResponse + +## Zip + +Types: + +- ZipRetrieveResponse + +Methods: + +- client.export.zip.retrieve({ ...params }) -> ZipRetrieveResponse # Pages +## Render + Types: -- PageRenderCreateResponse +- RenderCreateResponse Methods: -- client.pages.renderCreate({ ...params }) -> PageRenderCreateResponse +- client.pages.render.create({ ...params }) -> RenderCreateResponse # Project +## Current + Types: -- ProjectCurrentListResponse -- ProjectDomainsCreateResponse -- ProjectDomainsListResponse -- ProjectDomainsRetrieveResponse -- ProjectDomainsUpdateResponse -- ProjectTemplatesCreateResponse -- ProjectTemplatesListResponse -- ProjectTemplatesRetrieveResponse -- ProjectTemplatesUpdateResponse -- ProjectWorkspacesListResponse -- ProjectWorkspacesRetrieveResponse - -Methods: - -- client.project.currentList({ ...params }) -> ProjectCurrentListResponse -- client.project.domainsCreate({ ...params }) -> ProjectDomainsCreateResponse -- client.project.domainsDelete(id) -> void -- client.project.domainsList({ ...params }) -> ProjectDomainsListResponse -- client.project.domainsRetrieve(id) -> ProjectDomainsRetrieveResponse -- client.project.domainsUpdate(id, { ...params }) -> ProjectDomainsUpdateResponse -- client.project.templatesCreate({ ...params }) -> ProjectTemplatesCreateResponse -- client.project.templatesDelete(id) -> void -- client.project.templatesList({ ...params }) -> ProjectTemplatesListResponsesCursorPage -- client.project.templatesRetrieve(id) -> ProjectTemplatesRetrieveResponse -- client.project.templatesUpdate(id, { ...params }) -> ProjectTemplatesUpdateResponse -- client.project.workspacesList() -> ProjectWorkspacesListResponse -- client.project.workspacesRetrieve(workspaceID) -> ProjectWorkspacesRetrieveResponse +- CurrentRetrieveResponse + +Methods: + +- client.project.current.retrieve({ ...params }) -> CurrentRetrieveResponse + +## Domains + +Types: + +- DomainCreateResponse +- DomainRetrieveResponse +- DomainUpdateResponse +- DomainListResponse + +Methods: + +- client.project.domains.create({ ...params }) -> DomainCreateResponse +- client.project.domains.retrieve(id) -> DomainRetrieveResponse +- client.project.domains.update(id, { ...params }) -> DomainUpdateResponse +- client.project.domains.list({ ...params }) -> DomainListResponse +- client.project.domains.delete(id) -> void + +## Templates + +Types: + +- TemplateCreateResponse +- TemplateRetrieveResponse +- TemplateUpdateResponse +- TemplateListResponse + +Methods: + +- client.project.templates.create({ ...params }) -> TemplateCreateResponse +- client.project.templates.retrieve(id) -> TemplateRetrieveResponse +- client.project.templates.update(id, { ...params }) -> TemplateUpdateResponse +- client.project.templates.list({ ...params }) -> TemplateListResponse +- client.project.templates.delete(id) -> void + +## Workspaces + +Types: + +- WorkspaceRetrieveResponse +- WorkspaceListResponse + +Methods: + +- client.project.workspaces.retrieve(workspaceID) -> WorkspaceRetrieveResponse +- client.project.workspaces.list() -> WorkspaceListResponse diff --git a/src/client.ts b/src/client.ts index 1d3ac41..ce8e792 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,60 +18,12 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { - DocumentDocumentsRetrieveParams, - DocumentDocumentsRetrieveResponse, - DocumentGenerateCreateParams, - DocumentGenerateCreateResponse, - DocumentGenerateTemplateTemplateParams, - DocumentGenerateTemplateTemplateResponse, - Documents, -} from './resources/documents'; -import { - EmailRenderCreateParams, - EmailRenderCreateResponse, - EmailRetrieveParams, - EmailRetrieveResponse, - EmailSendCreateParams, - EmailSendCreateResponse, - EmailSendTemplateTemplateParams, - EmailSendTemplateTemplateResponse, - Emails, -} from './resources/emails'; -import { - Export, - ExportHTMLListParams, - ExportHTMLListResponse, - ExportImageListParams, - ExportImageListResponse, - ExportPdfListParams, - ExportPdfListResponse, - ExportZipListParams, - ExportZipListResponse, -} from './resources/export'; -import { PageRenderCreateParams, PageRenderCreateResponse, Pages } from './resources/pages'; -import { - Project, - ProjectCurrentListParams, - ProjectCurrentListResponse, - ProjectDomainsCreateParams, - ProjectDomainsCreateResponse, - ProjectDomainsListParams, - ProjectDomainsListResponse, - ProjectDomainsRetrieveResponse, - ProjectDomainsUpdateParams, - ProjectDomainsUpdateResponse, - ProjectTemplatesCreateParams, - ProjectTemplatesCreateResponse, - ProjectTemplatesListParams, - ProjectTemplatesListResponse, - ProjectTemplatesListResponsesCursorPage, - ProjectTemplatesRetrieveResponse, - ProjectTemplatesUpdateParams, - ProjectTemplatesUpdateResponse, - ProjectWorkspacesListResponse, - ProjectWorkspacesRetrieveResponse, -} from './resources/project'; +import { Convert } from './resources/convert/convert'; +import { DocumentRetrieveParams, DocumentRetrieveResponse, Documents } from './resources/documents/documents'; +import { EmailRetrieveParams, EmailRetrieveResponse, Emails } from './resources/emails/emails'; +import { Export } from './resources/export/export'; +import { Pages } from './resources/pages/pages'; +import { Project } from './resources/project/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -828,6 +780,7 @@ export class Unlayer { static toFile = Uploads.toFile; + convert: API.Convert = new API.Convert(this); documents: API.Documents = new API.Documents(this); emails: API.Emails = new API.Emails(this); export: API.Export = new API.Export(this); @@ -835,6 +788,7 @@ export class Unlayer { project: API.Project = new API.Project(this); } +Unlayer.Convert = Convert; Unlayer.Documents = Documents; Unlayer.Emails = Emails; Unlayer.Export = Export; @@ -847,66 +801,23 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { Convert as Convert }; + export { Documents as Documents, - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, + type DocumentRetrieveResponse as DocumentRetrieveResponse, + type DocumentRetrieveParams as DocumentRetrieveParams, }; export { Emails as Emails, type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, type EmailRetrieveParams as EmailRetrieveParams, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, }; - export { - Export as Export, - type ExportHTMLListResponse as ExportHTMLListResponse, - type ExportImageListResponse as ExportImageListResponse, - type ExportPdfListResponse as ExportPdfListResponse, - type ExportZipListResponse as ExportZipListResponse, - type ExportHTMLListParams as ExportHTMLListParams, - type ExportImageListParams as ExportImageListParams, - type ExportPdfListParams as ExportPdfListParams, - type ExportZipListParams as ExportZipListParams, - }; + export { Export as Export }; - export { - Pages as Pages, - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; + export { Pages as Pages }; - export { - Project as Project, - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, - type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, - type ProjectTemplatesListResponsesCursorPage as ProjectTemplatesListResponsesCursorPage, - type ProjectCurrentListParams as ProjectCurrentListParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsListParams as ProjectDomainsListParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesListParams as ProjectTemplatesListParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; + export { Project as Project }; } diff --git a/src/resources/convert.ts b/src/resources/convert.ts new file mode 100644 index 0000000..1334f91 --- /dev/null +++ b/src/resources/convert.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './convert/index'; diff --git a/src/resources/convert/convert.ts b/src/resources/convert/convert.ts new file mode 100644 index 0000000..d7930c4 --- /dev/null +++ b/src/resources/convert/convert.ts @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as FullToSimpleAPI from './full-to-simple'; +import { FullToSimple, FullToSimpleCreateParams, FullToSimpleCreateResponse } from './full-to-simple'; +import * as SimpleToFullAPI from './simple-to-full'; +import { SimpleToFull, SimpleToFullCreateParams, SimpleToFullCreateResponse } from './simple-to-full'; + +export class Convert extends APIResource { + fullToSimple: FullToSimpleAPI.FullToSimple = new FullToSimpleAPI.FullToSimple(this._client); + simpleToFull: SimpleToFullAPI.SimpleToFull = new SimpleToFullAPI.SimpleToFull(this._client); +} + +Convert.FullToSimple = FullToSimple; +Convert.SimpleToFull = SimpleToFull; + +export declare namespace Convert { + export { + FullToSimple as FullToSimple, + type FullToSimpleCreateResponse as FullToSimpleCreateResponse, + type FullToSimpleCreateParams as FullToSimpleCreateParams, + }; + + export { + SimpleToFull as SimpleToFull, + type SimpleToFullCreateResponse as SimpleToFullCreateResponse, + type SimpleToFullCreateParams as SimpleToFullCreateParams, + }; +} diff --git a/src/resources/convert/full-to-simple.ts b/src/resources/convert/full-to-simple.ts new file mode 100644 index 0000000..da8cf22 --- /dev/null +++ b/src/resources/convert/full-to-simple.ts @@ -0,0 +1,53 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class FullToSimple extends APIResource { + /** + * Convert design json from Full to Simple schema. + */ + create(body: FullToSimpleCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/convert/full-to-simple', { body, ...options }); + } +} + +export interface FullToSimpleCreateResponse { + data?: FullToSimpleCreateResponse.Data; + + success?: true; +} + +export namespace FullToSimpleCreateResponse { + export interface Data { + design?: { [key: string]: unknown }; + } +} + +export interface FullToSimpleCreateParams { + design: FullToSimpleCreateParams.Design; + + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + includeDefaultValues?: boolean; +} + +export namespace FullToSimpleCreateParams { + export interface Design { + body: unknown; + + counters?: unknown; + + schemaVersion?: number; + + [k: string]: unknown; + } +} + +export declare namespace FullToSimple { + export { + type FullToSimpleCreateResponse as FullToSimpleCreateResponse, + type FullToSimpleCreateParams as FullToSimpleCreateParams, + }; +} diff --git a/src/resources/convert/index.ts b/src/resources/convert/index.ts new file mode 100644 index 0000000..833a9fc --- /dev/null +++ b/src/resources/convert/index.ts @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Convert } from './convert'; +export { + FullToSimple, + type FullToSimpleCreateResponse, + type FullToSimpleCreateParams, +} from './full-to-simple'; +export { + SimpleToFull, + type SimpleToFullCreateResponse, + type SimpleToFullCreateParams, +} from './simple-to-full'; diff --git a/src/resources/convert/simple-to-full.ts b/src/resources/convert/simple-to-full.ts new file mode 100644 index 0000000..24d1681 --- /dev/null +++ b/src/resources/convert/simple-to-full.ts @@ -0,0 +1,63 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class SimpleToFull extends APIResource { + /** + * Convert design json from Simple to Full schema. + */ + create(body: SimpleToFullCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/convert/simple-to-full', { body, ...options }); + } +} + +export interface SimpleToFullCreateResponse { + data?: SimpleToFullCreateResponse.Data; + + success?: true; +} + +export namespace SimpleToFullCreateResponse { + export interface Data { + design?: { [key: string]: unknown }; + } +} + +export interface SimpleToFullCreateParams { + design: SimpleToFullCreateParams.Design; + + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + includeDefaultValues?: boolean; +} + +export namespace SimpleToFullCreateParams { + export interface Design { + body: unknown; + + _conversion?: Design._Conversion; + + counters?: unknown; + + schemaVersion?: number; + + [k: string]: unknown; + } + + export namespace Design { + export interface _Conversion { + data?: string; + + version?: number; + } + } +} + +export declare namespace SimpleToFull { + export { + type SimpleToFullCreateResponse as SimpleToFullCreateResponse, + type SimpleToFullCreateParams as SimpleToFullCreateParams, + }; +} diff --git a/src/resources/documents.ts b/src/resources/documents.ts index fdd66ac..6dcfade 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -1,211 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Documents extends APIResource { - /** - * Retrieve details of a previously generated document. - */ - documentsRetrieve( - id: string, - query: DocumentDocumentsRetrieveParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, { query, ...options }); - } - - /** - * Generate PDF document from JSON design, HTML content, or URL. - */ - generateCreate( - params: DocumentGenerateCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/documents/v1/generate', { query: { projectId }, body, ...options }); - } - - /** - * Generate PDF document from an existing template with merge tags. - */ - generateTemplateTemplate( - params: DocumentGenerateTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/documents/v1/generate/template', { query: { projectId }, body, ...options }); - } -} - -export interface DocumentDocumentsRetrieveResponse { - data?: DocumentDocumentsRetrieveResponse.Data; -} - -export namespace DocumentDocumentsRetrieveResponse { - export interface Data { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface DocumentGenerateCreateResponse { - data?: DocumentGenerateCreateResponse.Data; -} - -export namespace DocumentGenerateCreateResponse { - export interface Data { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface DocumentGenerateTemplateTemplateResponse { - data?: DocumentGenerateTemplateTemplateResponse.Data; -} - -export namespace DocumentGenerateTemplateTemplateResponse { - export interface Data { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface DocumentDocumentsRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export interface DocumentGenerateCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design?: { [key: string]: unknown }; - - /** - * Body param: Optional filename for the generated PDF - */ - filename?: string; - - /** - * Body param: HTML content to convert to PDF - */ - html?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: URL to convert to PDF - */ - url?: string; -} - -export interface DocumentGenerateTemplateTemplateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: ID of the template to use for generation - */ - templateId: string; - - /** - * Body param: Optional filename for the generated PDF - */ - filename?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Documents { - export { - type DocumentDocumentsRetrieveResponse as DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse as DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse as DocumentGenerateTemplateTemplateResponse, - type DocumentDocumentsRetrieveParams as DocumentDocumentsRetrieveParams, - type DocumentGenerateCreateParams as DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams as DocumentGenerateTemplateTemplateParams, - }; -} +export * from './documents/index'; diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts new file mode 100644 index 0000000..515b005 --- /dev/null +++ b/src/resources/documents/documents.ts @@ -0,0 +1,109 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as GenerateAPI from './generate'; +import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; +import * as GenerateTemplateAPI from './generate-template'; +import { + GenerateTemplate, + GenerateTemplateCreateParams, + GenerateTemplateCreateResponse, +} from './generate-template'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Documents extends APIResource { + generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); + generateTemplate: GenerateTemplateAPI.GenerateTemplate = new GenerateTemplateAPI.GenerateTemplate( + this._client, + ); + + /** + * Retrieve details of a previously generated document. + */ + retrieve( + id: string, + query: DocumentRetrieveParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/documents/v1/documents/${id}`, { query, ...options }); + } +} + +export interface DocumentRetrieveResponse { + data?: DocumentRetrieveResponse.Data; +} + +export namespace DocumentRetrieveResponse { + export interface Data { + /** + * Document ID + */ + id?: string; + + /** + * When the document generation was completed + */ + completedAt?: string; + + /** + * When the document was created + */ + createdAt?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * File size in bytes + */ + fileSize?: number; + + /** + * Number of pages in the PDF + */ + pageCount?: number; + + /** + * URL to download the PDF + */ + pdfUrl?: string; + + /** + * Current document status + */ + status?: 'generating' | 'completed' | 'failed'; + } +} + +export interface DocumentRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +Documents.Generate = Generate; +Documents.GenerateTemplate = GenerateTemplate; + +export declare namespace Documents { + export { + type DocumentRetrieveResponse as DocumentRetrieveResponse, + type DocumentRetrieveParams as DocumentRetrieveParams, + }; + + export { + Generate as Generate, + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateParams as GenerateCreateParams, + }; + + export { + GenerateTemplate as GenerateTemplate, + type GenerateTemplateCreateResponse as GenerateTemplateCreateResponse, + type GenerateTemplateCreateParams as GenerateTemplateCreateParams, + }; +} diff --git a/src/resources/documents/generate-template.ts b/src/resources/documents/generate-template.ts new file mode 100644 index 0000000..60c6b31 --- /dev/null +++ b/src/resources/documents/generate-template.ts @@ -0,0 +1,72 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class GenerateTemplate extends APIResource { + /** + * Generate PDF document from an existing template with merge tags. + */ + create( + params: GenerateTemplateCreateParams, + options?: RequestOptions, + ): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/documents/v1/generate/template', { query: { projectId }, body, ...options }); + } +} + +export interface GenerateTemplateCreateResponse { + data?: GenerateTemplateCreateResponse.Data; +} + +export namespace GenerateTemplateCreateResponse { + export interface Data { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; + } +} + +export interface GenerateTemplateCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: ID of the template to use for generation + */ + templateId: string; + + /** + * Body param: Optional filename for the generated PDF + */ + filename?: string; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace GenerateTemplate { + export { + type GenerateTemplateCreateResponse as GenerateTemplateCreateResponse, + type GenerateTemplateCreateParams as GenerateTemplateCreateParams, + }; +} diff --git a/src/resources/documents/generate.ts b/src/resources/documents/generate.ts new file mode 100644 index 0000000..2d02591 --- /dev/null +++ b/src/resources/documents/generate.ts @@ -0,0 +1,79 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Generate extends APIResource { + /** + * Generate PDF document from JSON design, HTML content, or URL. + */ + create(params: GenerateCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/documents/v1/generate', { query: { projectId }, body, ...options }); + } +} + +export interface GenerateCreateResponse { + data?: GenerateCreateResponse.Data; +} + +export namespace GenerateCreateResponse { + export interface Data { + /** + * Unique document identifier + */ + documentId?: string; + + /** + * Generated filename + */ + filename?: string; + + /** + * URL to download the generated PDF + */ + pdfUrl?: string; + + status?: 'generating' | 'completed' | 'failed'; + } +} + +export interface GenerateCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: Proprietary design format JSON + */ + design?: { [key: string]: unknown }; + + /** + * Body param: Optional filename for the generated PDF + */ + filename?: string; + + /** + * Body param: HTML content to convert to PDF + */ + html?: string; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Body param: URL to convert to PDF + */ + url?: string; +} + +export declare namespace Generate { + export { + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateParams as GenerateCreateParams, + }; +} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts new file mode 100644 index 0000000..9d23892 --- /dev/null +++ b/src/resources/documents/index.ts @@ -0,0 +1,9 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Documents, type DocumentRetrieveResponse, type DocumentRetrieveParams } from './documents'; +export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; +export { + GenerateTemplate, + type GenerateTemplateCreateResponse, + type GenerateTemplateCreateParams, +} from './generate-template'; diff --git a/src/resources/emails.ts b/src/resources/emails.ts index 5c3d4bf..bd0ec59 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -1,226 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Emails extends APIResource { - /** - * Retrieve details of a previously sent email. - */ - retrieve( - id: string, - query: EmailRetrieveParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, { query, ...options }); - } - - /** - * Convert design JSON to HTML with optional merge tags. - */ - renderCreate( - params: EmailRenderCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/render', { query: { projectId }, body, ...options }); - } - - /** - * Send email with design JSON or HTML content. - */ - sendCreate(params: EmailSendCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/send', { query: { projectId }, body, ...options }); - } - - /** - * Send email using an existing template with merge tags. - */ - sendTemplateTemplate( - params: EmailSendTemplateTemplateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/send/template', { query: { projectId }, body, ...options }); - } -} - -export interface EmailRetrieveResponse { - data?: EmailRetrieveResponse.Data; -} - -export namespace EmailRetrieveResponse { - export interface Data { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; - } -} - -export interface EmailRenderCreateResponse { - data?: EmailRenderCreateResponse.Data; -} - -export namespace EmailRenderCreateResponse { - export interface Data { - /** - * Rendered HTML content - */ - html?: string; - } -} - -export interface EmailSendCreateResponse { - data?: EmailSendCreateResponse.Data; -} - -export namespace EmailSendCreateResponse { - export interface Data { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; - } -} - -export interface EmailSendTemplateTemplateResponse { - data?: EmailSendTemplateTemplateResponse.Data; -} - -export namespace EmailSendTemplateTemplateResponse { - export interface Data { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; - } -} - -export interface EmailRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export interface EmailRenderCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export interface EmailSendCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Recipient email address - */ - to: string; - - /** - * Body param: Proprietary design format JSON - */ - design?: { [key: string]: unknown }; - - /** - * Body param: HTML content to send - */ - html?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: Email subject line - */ - subject?: string; -} - -export interface EmailSendTemplateTemplateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: ID of the template to use - */ - templateId: string; - - /** - * Body param: Recipient email address - */ - to: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -export declare namespace Emails { - export { - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRenderCreateResponse as EmailRenderCreateResponse, - type EmailSendCreateResponse as EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse as EmailSendTemplateTemplateResponse, - type EmailRetrieveParams as EmailRetrieveParams, - type EmailRenderCreateParams as EmailRenderCreateParams, - type EmailSendCreateParams as EmailSendCreateParams, - type EmailSendTemplateTemplateParams as EmailSendTemplateTemplateParams, - }; -} +export * from './emails/index'; diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts new file mode 100644 index 0000000..41459dc --- /dev/null +++ b/src/resources/emails/emails.ts @@ -0,0 +1,103 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as RenderAPI from './render'; +import { Render, RenderCreateParams, RenderCreateResponse } from './render'; +import * as SendAPI from './send'; +import { Send, SendCreateParams, SendCreateResponse } from './send'; +import * as SendTemplateAPI from './send-template'; +import { SendTemplate, SendTemplateCreateParams, SendTemplateCreateResponse } from './send-template'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Emails extends APIResource { + render: RenderAPI.Render = new RenderAPI.Render(this._client); + send: SendAPI.Send = new SendAPI.Send(this._client); + sendTemplate: SendTemplateAPI.SendTemplate = new SendTemplateAPI.SendTemplate(this._client); + + /** + * Retrieve details of a previously sent email. + */ + retrieve( + id: string, + query: EmailRetrieveParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/emails/v1/emails/${id}`, { query, ...options }); + } +} + +export interface EmailRetrieveResponse { + data?: EmailRetrieveResponse.Data; +} + +export namespace EmailRetrieveResponse { + export interface Data { + /** + * Email message ID + */ + id?: string; + + /** + * HTML content of the email (optional) + */ + html?: string; + + /** + * When the email was sent + */ + sentAt?: string; + + /** + * Current email status + */ + status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; + + /** + * Email subject line + */ + subject?: string; + + /** + * Recipient email address + */ + to?: string; + } +} + +export interface EmailRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +Emails.Render = Render; +Emails.Send = Send; +Emails.SendTemplate = SendTemplate; + +export declare namespace Emails { + export { + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailRetrieveParams as EmailRetrieveParams, + }; + + export { + Render as Render, + type RenderCreateResponse as RenderCreateResponse, + type RenderCreateParams as RenderCreateParams, + }; + + export { + Send as Send, + type SendCreateResponse as SendCreateResponse, + type SendCreateParams as SendCreateParams, + }; + + export { + SendTemplate as SendTemplate, + type SendTemplateCreateResponse as SendTemplateCreateResponse, + type SendTemplateCreateParams as SendTemplateCreateParams, + }; +} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts new file mode 100644 index 0000000..a047eda --- /dev/null +++ b/src/resources/emails/index.ts @@ -0,0 +1,10 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Emails, type EmailRetrieveResponse, type EmailRetrieveParams } from './emails'; +export { Render, type RenderCreateResponse, type RenderCreateParams } from './render'; +export { Send, type SendCreateResponse, type SendCreateParams } from './send'; +export { + SendTemplate, + type SendTemplateCreateResponse, + type SendTemplateCreateParams, +} from './send-template'; diff --git a/src/resources/emails/render.ts b/src/resources/emails/render.ts new file mode 100644 index 0000000..6dd2be1 --- /dev/null +++ b/src/resources/emails/render.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Render extends APIResource { + /** + * Convert design JSON to HTML with optional merge tags. + */ + create(params: RenderCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/emails/v1/render', { query: { projectId }, body, ...options }); + } +} + +export interface RenderCreateResponse { + data?: RenderCreateResponse.Data; +} + +export namespace RenderCreateResponse { + export interface Data { + /** + * Rendered HTML content + */ + html?: string; + } +} + +export interface RenderCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Render { + export { type RenderCreateResponse as RenderCreateResponse, type RenderCreateParams as RenderCreateParams }; +} diff --git a/src/resources/emails/send-template.ts b/src/resources/emails/send-template.ts new file mode 100644 index 0000000..2336dbe --- /dev/null +++ b/src/resources/emails/send-template.ts @@ -0,0 +1,64 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class SendTemplate extends APIResource { + /** + * Send email using an existing template with merge tags. + */ + create(params: SendTemplateCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/emails/v1/send/template', { query: { projectId }, body, ...options }); + } +} + +export interface SendTemplateCreateResponse { + data?: SendTemplateCreateResponse.Data; +} + +export namespace SendTemplateCreateResponse { + export interface Data { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; + } +} + +export interface SendTemplateCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: ID of the template to use + */ + templateId: string; + + /** + * Body param: Recipient email address + */ + to: string; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Body param: Email subject line (optional, uses template default if not provided) + */ + subject?: string; +} + +export declare namespace SendTemplate { + export { + type SendTemplateCreateResponse as SendTemplateCreateResponse, + type SendTemplateCreateParams as SendTemplateCreateParams, + }; +} diff --git a/src/resources/emails/send.ts b/src/resources/emails/send.ts new file mode 100644 index 0000000..d47ebd4 --- /dev/null +++ b/src/resources/emails/send.ts @@ -0,0 +1,66 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Send extends APIResource { + /** + * Send email with design JSON or HTML content. + */ + create(params: SendCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/emails/v1/send', { query: { projectId }, body, ...options }); + } +} + +export interface SendCreateResponse { + data?: SendCreateResponse.Data; +} + +export namespace SendCreateResponse { + export interface Data { + /** + * Unique message identifier + */ + messageId?: string; + + status?: 'sent' | 'queued' | 'failed'; + } +} + +export interface SendCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: Recipient email address + */ + to: string; + + /** + * Body param: Proprietary design format JSON + */ + design?: { [key: string]: unknown }; + + /** + * Body param: HTML content to send + */ + html?: string; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; + + /** + * Body param: Email subject line + */ + subject?: string; +} + +export declare namespace Send { + export { type SendCreateResponse as SendCreateResponse, type SendCreateParams as SendCreateParams }; +} diff --git a/src/resources/export.ts b/src/resources/export.ts index a32bee5..d368bec 100644 --- a/src/resources/export.ts +++ b/src/resources/export.ts @@ -1,116 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; - -export class Export extends APIResource { - /** - * Export design to HTML. - */ - htmlList(query: ExportHTMLListParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/html', { query, ...options }); - } - - /** - * Export design to image. - */ - imageList(query: ExportImageListParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/image', { query, ...options }); - } - - /** - * Export design to PDF. - */ - pdfList(query: ExportPdfListParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/pdf', { query, ...options }); - } - - /** - * Export design to ZIP archive. - */ - zipList(query: ExportZipListParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/zip', { query, ...options }); - } -} - -export interface ExportHTMLListResponse { - data?: ExportHTMLListResponse.Data; -} - -export namespace ExportHTMLListResponse { - export interface Data { - success?: boolean; - } -} - -export interface ExportImageListResponse { - data?: ExportImageListResponse.Data; -} - -export namespace ExportImageListResponse { - export interface Data { - success?: boolean; - } -} - -export interface ExportPdfListResponse { - data?: ExportPdfListResponse.Data; -} - -export namespace ExportPdfListResponse { - export interface Data { - success?: boolean; - } -} - -export interface ExportZipListResponse { - data?: ExportZipListResponse.Data; -} - -export namespace ExportZipListResponse { - export interface Data { - success?: boolean; - } -} - -export interface ExportHTMLListParams { - /** - * The project ID - */ - projectId: string; -} - -export interface ExportImageListParams { - /** - * The project ID - */ - projectId: string; -} - -export interface ExportPdfListParams { - /** - * The project ID - */ - projectId: string; -} - -export interface ExportZipListParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Export { - export { - type ExportHTMLListResponse as ExportHTMLListResponse, - type ExportImageListResponse as ExportImageListResponse, - type ExportPdfListResponse as ExportPdfListResponse, - type ExportZipListResponse as ExportZipListResponse, - type ExportHTMLListParams as ExportHTMLListParams, - type ExportImageListParams as ExportImageListParams, - type ExportPdfListParams as ExportPdfListParams, - type ExportZipListParams as ExportZipListParams, - }; -} +export * from './export/index'; diff --git a/src/resources/export/export.ts b/src/resources/export/export.ts new file mode 100644 index 0000000..c5c2a30 --- /dev/null +++ b/src/resources/export/export.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as HTMLAPI from './html'; +import { HTML, HTMLRetrieveParams, HTMLRetrieveResponse } from './html'; +import * as ImageAPI from './image'; +import { Image, ImageRetrieveParams, ImageRetrieveResponse } from './image'; +import * as PdfAPI from './pdf'; +import { Pdf, PdfRetrieveParams, PdfRetrieveResponse } from './pdf'; +import * as ZipAPI from './zip'; +import { Zip, ZipRetrieveParams, ZipRetrieveResponse } from './zip'; + +export class Export extends APIResource { + html: HTMLAPI.HTML = new HTMLAPI.HTML(this._client); + image: ImageAPI.Image = new ImageAPI.Image(this._client); + pdf: PdfAPI.Pdf = new PdfAPI.Pdf(this._client); + zip: ZipAPI.Zip = new ZipAPI.Zip(this._client); +} + +Export.HTML = HTML; +Export.Image = Image; +Export.Pdf = Pdf; +Export.Zip = Zip; + +export declare namespace Export { + export { + HTML as HTML, + type HTMLRetrieveResponse as HTMLRetrieveResponse, + type HTMLRetrieveParams as HTMLRetrieveParams, + }; + + export { + Image as Image, + type ImageRetrieveResponse as ImageRetrieveResponse, + type ImageRetrieveParams as ImageRetrieveParams, + }; + + export { + Pdf as Pdf, + type PdfRetrieveResponse as PdfRetrieveResponse, + type PdfRetrieveParams as PdfRetrieveParams, + }; + + export { + Zip as Zip, + type ZipRetrieveResponse as ZipRetrieveResponse, + type ZipRetrieveParams as ZipRetrieveParams, + }; +} diff --git a/src/resources/export/html.ts b/src/resources/export/html.ts new file mode 100644 index 0000000..68816b6 --- /dev/null +++ b/src/resources/export/html.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class HTML extends APIResource { + /** + * Export design to HTML. + */ + retrieve(query: HTMLRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/html', { query, ...options }); + } +} + +export interface HTMLRetrieveResponse { + data?: HTMLRetrieveResponse.Data; +} + +export namespace HTMLRetrieveResponse { + export interface Data { + success?: boolean; + } +} + +export interface HTMLRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace HTML { + export { type HTMLRetrieveResponse as HTMLRetrieveResponse, type HTMLRetrieveParams as HTMLRetrieveParams }; +} diff --git a/src/resources/export/image.ts b/src/resources/export/image.ts new file mode 100644 index 0000000..b9dba53 --- /dev/null +++ b/src/resources/export/image.ts @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Image extends APIResource { + /** + * Export design to image. + */ + retrieve(query: ImageRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/image', { query, ...options }); + } +} + +export interface ImageRetrieveResponse { + data?: ImageRetrieveResponse.Data; +} + +export namespace ImageRetrieveResponse { + export interface Data { + success?: boolean; + } +} + +export interface ImageRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Image { + export { + type ImageRetrieveResponse as ImageRetrieveResponse, + type ImageRetrieveParams as ImageRetrieveParams, + }; +} diff --git a/src/resources/export/index.ts b/src/resources/export/index.ts new file mode 100644 index 0000000..2b9b59d --- /dev/null +++ b/src/resources/export/index.ts @@ -0,0 +1,7 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Export } from './export'; +export { HTML, type HTMLRetrieveResponse, type HTMLRetrieveParams } from './html'; +export { Image, type ImageRetrieveResponse, type ImageRetrieveParams } from './image'; +export { Pdf, type PdfRetrieveResponse, type PdfRetrieveParams } from './pdf'; +export { Zip, type ZipRetrieveResponse, type ZipRetrieveParams } from './zip'; diff --git a/src/resources/export/pdf.ts b/src/resources/export/pdf.ts new file mode 100644 index 0000000..307f2db --- /dev/null +++ b/src/resources/export/pdf.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Pdf extends APIResource { + /** + * Export design to PDF. + */ + retrieve(query: PdfRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/pdf', { query, ...options }); + } +} + +export interface PdfRetrieveResponse { + data?: PdfRetrieveResponse.Data; +} + +export namespace PdfRetrieveResponse { + export interface Data { + success?: boolean; + } +} + +export interface PdfRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Pdf { + export { type PdfRetrieveResponse as PdfRetrieveResponse, type PdfRetrieveParams as PdfRetrieveParams }; +} diff --git a/src/resources/export/zip.ts b/src/resources/export/zip.ts new file mode 100644 index 0000000..3436f8c --- /dev/null +++ b/src/resources/export/zip.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Zip extends APIResource { + /** + * Export design to ZIP archive. + */ + retrieve(query: ZipRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/export/v3/zip', { query, ...options }); + } +} + +export interface ZipRetrieveResponse { + data?: ZipRetrieveResponse.Data; +} + +export namespace ZipRetrieveResponse { + export interface Data { + success?: boolean; + } +} + +export interface ZipRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Zip { + export { type ZipRetrieveResponse as ZipRetrieveResponse, type ZipRetrieveParams as ZipRetrieveParams }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index a26d88e..91eb561 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,56 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - Documents, - type DocumentDocumentsRetrieveResponse, - type DocumentGenerateCreateResponse, - type DocumentGenerateTemplateTemplateResponse, - type DocumentDocumentsRetrieveParams, - type DocumentGenerateCreateParams, - type DocumentGenerateTemplateTemplateParams, -} from './documents'; -export { - Emails, - type EmailRetrieveResponse, - type EmailRenderCreateResponse, - type EmailSendCreateResponse, - type EmailSendTemplateTemplateResponse, - type EmailRetrieveParams, - type EmailRenderCreateParams, - type EmailSendCreateParams, - type EmailSendTemplateTemplateParams, -} from './emails'; -export { - Export, - type ExportHTMLListResponse, - type ExportImageListResponse, - type ExportPdfListResponse, - type ExportZipListResponse, - type ExportHTMLListParams, - type ExportImageListParams, - type ExportPdfListParams, - type ExportZipListParams, -} from './export'; -export { Pages, type PageRenderCreateResponse, type PageRenderCreateParams } from './pages'; -export { - Project, - type ProjectCurrentListResponse, - type ProjectDomainsCreateResponse, - type ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse, - type ProjectWorkspacesListResponse, - type ProjectWorkspacesRetrieveResponse, - type ProjectCurrentListParams, - type ProjectDomainsCreateParams, - type ProjectDomainsListParams, - type ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams, - type ProjectTemplatesListParams, - type ProjectTemplatesUpdateParams, - type ProjectTemplatesListResponsesCursorPage, -} from './project'; +export { Convert } from './convert/convert'; +export { Documents, type DocumentRetrieveResponse, type DocumentRetrieveParams } from './documents/documents'; +export { Emails, type EmailRetrieveResponse, type EmailRetrieveParams } from './emails/emails'; +export { Export } from './export/export'; +export { Pages } from './pages/pages'; +export { Project } from './project/project'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts index 067aa07..c218cbe 100644 --- a/src/resources/pages.ts +++ b/src/resources/pages.ts @@ -1,55 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; - -export class Pages extends APIResource { - /** - * Convert page design JSON to HTML with optional merge tags. - */ - renderCreate( - params: PageRenderCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/pages/v1/render', { query: { projectId }, body, ...options }); - } -} - -export interface PageRenderCreateResponse { - data?: PageRenderCreateResponse.Data; -} - -export namespace PageRenderCreateResponse { - export interface Data { - /** - * Rendered HTML content - */ - html?: string; - } -} - -export interface PageRenderCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Pages { - export { - type PageRenderCreateResponse as PageRenderCreateResponse, - type PageRenderCreateParams as PageRenderCreateParams, - }; -} +export * from './pages/index'; diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts new file mode 100644 index 0000000..3398157 --- /dev/null +++ b/src/resources/pages/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Pages } from './pages'; +export { Render, type RenderCreateResponse, type RenderCreateParams } from './render'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts new file mode 100644 index 0000000..c28ceeb --- /dev/null +++ b/src/resources/pages/pages.ts @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as RenderAPI from './render'; +import { Render, RenderCreateParams, RenderCreateResponse } from './render'; + +export class Pages extends APIResource { + render: RenderAPI.Render = new RenderAPI.Render(this._client); +} + +Pages.Render = Render; + +export declare namespace Pages { + export { + Render as Render, + type RenderCreateResponse as RenderCreateResponse, + type RenderCreateParams as RenderCreateParams, + }; +} diff --git a/src/resources/pages/render.ts b/src/resources/pages/render.ts new file mode 100644 index 0000000..0b55f31 --- /dev/null +++ b/src/resources/pages/render.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Render extends APIResource { + /** + * Convert page design JSON to HTML with optional merge tags. + */ + create(params: RenderCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/pages/v1/render', { query: { projectId }, body, ...options }); + } +} + +export interface RenderCreateResponse { + data?: RenderCreateResponse.Data; +} + +export namespace RenderCreateResponse { + export interface Data { + /** + * Rendered HTML content + */ + html?: string; + } +} + +export interface RenderCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: Proprietary design format JSON + */ + design: { [key: string]: unknown }; + + /** + * Body param: Optional merge tags for personalization + */ + mergeTags?: { [key: string]: string }; +} + +export declare namespace Render { + export { type RenderCreateResponse as RenderCreateResponse, type RenderCreateParams as RenderCreateParams }; +} diff --git a/src/resources/project.ts b/src/resources/project.ts index 20fe5e6..60fc38d 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -1,471 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; -import { buildHeaders } from '../internal/headers'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -export class Project extends APIResource { - /** - * Get project details for the specified project. - */ - currentList( - query: ProjectCurrentListParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/project/v1/current', { query, ...options }); - } - - /** - * Add a new domain to the project. - */ - domainsCreate( - params: ProjectDomainsCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/project/v1/domains', { query: { projectId }, body, ...options }); - } - - /** - * Remove domain from project. - */ - domainsDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List all domains for the project. - */ - domainsList( - query: ProjectDomainsListParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/project/v1/domains', { query, ...options }); - } - - /** - * Get domain details by ID. - */ - domainsRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}`, options); - } - - /** - * Update domain settings. - */ - domainsUpdate( - id: string, - body: ProjectDomainsUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); - } - - /** - * Create a new project template. - */ - templatesCreate( - params: ProjectTemplatesCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/project/v1/templates', { query: { projectId }, body, ...options }); - } - - /** - * Delete project template. - */ - templatesDelete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * List project templates with cursor-based pagination. Returns templates in - * descending order by update time. - */ - templatesList( - query: ProjectTemplatesListParams, - options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/project/v1/templates', CursorPage, { - query, - ...options, - }); - } - - /** - * Get project template by ID. - */ - templatesRetrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}`, options); - } - - /** - * Update project template. - */ - templatesUpdate( - id: string, - body: ProjectTemplatesUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); - } - - /** - * Get all workspaces accessible by the current token. - */ - workspacesList(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/workspaces', options); - } - - /** - * Get a specific workspace by ID with its projects. - */ - workspacesRetrieve( - workspaceID: string, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/project/v1/workspaces/${workspaceID}`, options); - } -} - -export type ProjectTemplatesListResponsesCursorPage = CursorPage; - -export interface ProjectCurrentListResponse { - data?: ProjectCurrentListResponse.Data; -} - -export namespace ProjectCurrentListResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface ProjectDomainsCreateResponse { - data?: ProjectDomainsCreateResponse.Data; -} - -export namespace ProjectDomainsCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsListResponse { - data?: Array; -} - -export namespace ProjectDomainsListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface ProjectDomainsRetrieveResponse { - data?: ProjectDomainsRetrieveResponse.Data; -} - -export namespace ProjectDomainsRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectDomainsUpdateResponse { - data?: ProjectDomainsUpdateResponse.Data; -} - -export namespace ProjectDomainsUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface ProjectTemplatesCreateResponse { - data?: ProjectTemplatesCreateResponse.Data; -} - -export namespace ProjectTemplatesCreateResponse { - export interface Data { - /** - * Template ID - */ - id?: string; - - createdAt?: string; - - /** - * Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Template name - */ - name?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesListResponse { - /** - * Template ID - */ - id?: string; - - createdAt?: string; - - /** - * Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Template name - */ - name?: string; - - updatedAt?: string; -} - -export interface ProjectTemplatesRetrieveResponse { - data?: ProjectTemplatesRetrieveResponse.Data; -} - -export namespace ProjectTemplatesRetrieveResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectTemplatesUpdateResponse { - data?: ProjectTemplatesUpdateResponse.Data; -} - -export namespace ProjectTemplatesUpdateResponse { - export interface Data { - id?: string; - - body?: string; - - createdAt?: string; - - name?: string; - - subject?: string; - - updatedAt?: string; - } -} - -export interface ProjectWorkspacesListResponse { - data?: Array; -} - -export namespace ProjectWorkspacesListResponse { - export interface Data { - id?: number; - - name?: string; - } -} - -export interface ProjectWorkspacesRetrieveResponse { - data?: ProjectWorkspacesRetrieveResponse.Data; -} - -export namespace ProjectWorkspacesRetrieveResponse { - export interface Data { - id?: number; - - name?: string; - - projects?: Array; - } - - export namespace Data { - export interface Project { - id?: number; - - name?: string; - - status?: string; - } - } -} - -export interface ProjectCurrentListParams { - /** - * The project ID - */ - projectId: string; -} - -export interface ProjectDomainsCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Domain name to add - */ - domain: string; -} - -export interface ProjectDomainsListParams { - /** - * The project ID - */ - projectId: string; -} - -export interface ProjectDomainsUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export interface ProjectTemplatesCreateParams { - /** - * Query param: The project ID to create the template in - */ - projectId: string; - - /** - * Body param: Template name - */ - name: string; - - /** - * Body param: Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; -} - -export interface ProjectTemplatesListParams extends CursorPageParams { - /** - * The project ID to list templates for - */ - projectId: string; - - /** - * Filter by template type - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Filter by name (case-insensitive search) - */ - name?: string; -} - -export interface ProjectTemplatesUpdateParams { - /** - * Updated email body content - */ - body?: string; - - /** - * Updated template name - */ - name?: string; - - /** - * Updated email subject line - */ - subject?: string; -} - -export declare namespace Project { - export { - type ProjectCurrentListResponse as ProjectCurrentListResponse, - type ProjectDomainsCreateResponse as ProjectDomainsCreateResponse, - type ProjectDomainsListResponse as ProjectDomainsListResponse, - type ProjectDomainsRetrieveResponse as ProjectDomainsRetrieveResponse, - type ProjectDomainsUpdateResponse as ProjectDomainsUpdateResponse, - type ProjectTemplatesCreateResponse as ProjectTemplatesCreateResponse, - type ProjectTemplatesListResponse as ProjectTemplatesListResponse, - type ProjectTemplatesRetrieveResponse as ProjectTemplatesRetrieveResponse, - type ProjectTemplatesUpdateResponse as ProjectTemplatesUpdateResponse, - type ProjectWorkspacesListResponse as ProjectWorkspacesListResponse, - type ProjectWorkspacesRetrieveResponse as ProjectWorkspacesRetrieveResponse, - type ProjectTemplatesListResponsesCursorPage as ProjectTemplatesListResponsesCursorPage, - type ProjectCurrentListParams as ProjectCurrentListParams, - type ProjectDomainsCreateParams as ProjectDomainsCreateParams, - type ProjectDomainsListParams as ProjectDomainsListParams, - type ProjectDomainsUpdateParams as ProjectDomainsUpdateParams, - type ProjectTemplatesCreateParams as ProjectTemplatesCreateParams, - type ProjectTemplatesListParams as ProjectTemplatesListParams, - type ProjectTemplatesUpdateParams as ProjectTemplatesUpdateParams, - }; -} +export * from './project/index'; diff --git a/src/resources/project/current.ts b/src/resources/project/current.ts new file mode 100644 index 0000000..361bcb1 --- /dev/null +++ b/src/resources/project/current.ts @@ -0,0 +1,54 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Current extends APIResource { + /** + * Get project details for the specified project. + */ + retrieve(query: CurrentRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/current', { query, ...options }); + } +} + +export interface CurrentRetrieveResponse { + data?: CurrentRetrieveResponse.Data; +} + +export namespace CurrentRetrieveResponse { + export interface Data { + id?: number; + + createdAt?: string; + + name?: string; + + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface CurrentRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Current { + export { + type CurrentRetrieveResponse as CurrentRetrieveResponse, + type CurrentRetrieveParams as CurrentRetrieveParams, + }; +} diff --git a/src/resources/project/domains.ts b/src/resources/project/domains.ts new file mode 100644 index 0000000..cac4a6f --- /dev/null +++ b/src/resources/project/domains.ts @@ -0,0 +1,162 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Domains extends APIResource { + /** + * Add a new domain to the project. + */ + create(params: DomainCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/project/v1/domains', { query: { projectId }, body, ...options }); + } + + /** + * Get domain details by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/domains/${id}`, options); + } + + /** + * Update domain settings. + */ + update( + id: string, + body: DomainUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); + } + + /** + * List all domains for the project. + */ + list(query: DomainListParams, options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/domains', { query, ...options }); + } + + /** + * Remove domain from project. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/domains/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface DomainCreateResponse { + data?: DomainCreateResponse.Data; +} + +export namespace DomainCreateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainRetrieveResponse { + data?: DomainRetrieveResponse.Data; +} + +export namespace DomainRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainUpdateResponse { + data?: DomainUpdateResponse.Data; +} + +export namespace DomainUpdateResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: string; + + verified?: boolean; + } +} + +export interface DomainListResponse { + data?: Array; +} + +export namespace DomainListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + domain?: string; + + status?: 'active' | 'pending' | 'failed'; + + verified?: boolean; + } +} + +export interface DomainCreateParams { + /** + * Query param: The project ID + */ + projectId: string; + + /** + * Body param: Domain name to add + */ + domain: string; +} + +export interface DomainUpdateParams { + /** + * Updated domain name + */ + domain?: string; +} + +export interface DomainListParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Domains { + export { + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainUpdateResponse as DomainUpdateResponse, + type DomainListResponse as DomainListResponse, + type DomainCreateParams as DomainCreateParams, + type DomainUpdateParams as DomainUpdateParams, + type DomainListParams as DomainListParams, + }; +} diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts new file mode 100644 index 0000000..1733b9a --- /dev/null +++ b/src/resources/project/index.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Current, type CurrentRetrieveResponse, type CurrentRetrieveParams } from './current'; +export { + Domains, + type DomainCreateResponse, + type DomainRetrieveResponse, + type DomainUpdateResponse, + type DomainListResponse, + type DomainCreateParams, + type DomainUpdateParams, + type DomainListParams, +} from './domains'; +export { Project } from './project'; +export { + Templates, + type TemplateCreateResponse, + type TemplateRetrieveResponse, + type TemplateUpdateResponse, + type TemplateListResponse, + type TemplateCreateParams, + type TemplateUpdateParams, + type TemplateListParams, +} from './templates'; +export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts new file mode 100644 index 0000000..1dbe3da --- /dev/null +++ b/src/resources/project/project.ts @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as CurrentAPI from './current'; +import { Current, CurrentRetrieveParams, CurrentRetrieveResponse } from './current'; +import * as DomainsAPI from './domains'; +import { + DomainCreateParams, + DomainCreateResponse, + DomainListParams, + DomainListResponse, + DomainRetrieveResponse, + DomainUpdateParams, + DomainUpdateResponse, + Domains, +} from './domains'; +import * as TemplatesAPI from './templates'; +import { + TemplateCreateParams, + TemplateCreateResponse, + TemplateListParams, + TemplateListResponse, + TemplateRetrieveResponse, + TemplateUpdateParams, + TemplateUpdateResponse, + Templates, +} from './templates'; +import * as WorkspacesAPI from './workspaces'; +import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './workspaces'; + +export class Project extends APIResource { + current: CurrentAPI.Current = new CurrentAPI.Current(this._client); + domains: DomainsAPI.Domains = new DomainsAPI.Domains(this._client); + templates: TemplatesAPI.Templates = new TemplatesAPI.Templates(this._client); + workspaces: WorkspacesAPI.Workspaces = new WorkspacesAPI.Workspaces(this._client); +} + +Project.Current = Current; +Project.Domains = Domains; +Project.Templates = Templates; +Project.Workspaces = Workspaces; + +export declare namespace Project { + export { + Current as Current, + type CurrentRetrieveResponse as CurrentRetrieveResponse, + type CurrentRetrieveParams as CurrentRetrieveParams, + }; + + export { + Domains as Domains, + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainUpdateResponse as DomainUpdateResponse, + type DomainListResponse as DomainListResponse, + type DomainCreateParams as DomainCreateParams, + type DomainUpdateParams as DomainUpdateParams, + type DomainListParams as DomainListParams, + }; + + export { + Templates as Templates, + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateUpdateResponse as TemplateUpdateResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateCreateParams as TemplateCreateParams, + type TemplateUpdateParams as TemplateUpdateParams, + type TemplateListParams as TemplateListParams, + }; + + export { + Workspaces as Workspaces, + type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, + type WorkspaceListResponse as WorkspaceListResponse, + }; +} diff --git a/src/resources/project/templates.ts b/src/resources/project/templates.ts new file mode 100644 index 0000000..6faa6ee --- /dev/null +++ b/src/resources/project/templates.ts @@ -0,0 +1,230 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Templates extends APIResource { + /** + * Create a new project template. + */ + create(params: TemplateCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/project/v1/templates', { query: { projectId }, body, ...options }); + } + + /** + * Get project template by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/templates/${id}`, options); + } + + /** + * Update project template. + */ + update( + id: string, + body: TemplateUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + } + + /** + * List project templates with cursor-based pagination. Returns templates in + * descending order by update time. + */ + list(query: TemplateListParams, options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/templates', { query, ...options }); + } + + /** + * Delete project template. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/project/v1/templates/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface TemplateCreateResponse { + data?: TemplateCreateResponse.Data; +} + +export namespace TemplateCreateResponse { + export interface Data { + /** + * Template ID + */ + id?: string; + + createdAt?: string; + + /** + * Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; + + /** + * Template name + */ + name?: string; + + updatedAt?: string; + } +} + +export interface TemplateRetrieveResponse { + data?: TemplateRetrieveResponse.Data; +} + +export namespace TemplateRetrieveResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateUpdateResponse { + data?: TemplateUpdateResponse.Data; +} + +export namespace TemplateUpdateResponse { + export interface Data { + id?: string; + + body?: string; + + createdAt?: string; + + name?: string; + + subject?: string; + + updatedAt?: string; + } +} + +export interface TemplateListResponse { + data: Array; + + /** + * Whether there are more results after this page + */ + has_more: boolean; + + /** + * Cursor for the next page. Null if no more results. + */ + next_cursor?: string | null; +} + +export namespace TemplateListResponse { + export interface Data { + /** + * Template ID + */ + id?: string; + + createdAt?: string; + + /** + * Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; + + /** + * Template name + */ + name?: string; + + updatedAt?: string; + } +} + +export interface TemplateCreateParams { + /** + * Query param: The project ID to create the template in + */ + projectId: string; + + /** + * Body param: Template name + */ + name: string; + + /** + * Body param: Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; +} + +export interface TemplateUpdateParams { + /** + * Updated email body content + */ + body?: string; + + /** + * Updated template name + */ + name?: string; + + /** + * Updated email subject line + */ + subject?: string; +} + +export interface TemplateListParams { + /** + * The project ID to list templates for + */ + projectId: string; + + /** + * Pagination cursor from previous response + */ + cursor?: string; + + /** + * Filter by template type + */ + displayMode?: 'email' | 'web' | 'document'; + + /** + * Number of templates to return (1-100) + */ + limit?: number; + + /** + * Filter by name (case-insensitive search) + */ + name?: string; +} + +export declare namespace Templates { + export { + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateUpdateResponse as TemplateUpdateResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateCreateParams as TemplateCreateParams, + type TemplateUpdateParams as TemplateUpdateParams, + type TemplateListParams as TemplateListParams, + }; +} diff --git a/src/resources/project/workspaces.ts b/src/resources/project/workspaces.ts new file mode 100644 index 0000000..083fd3b --- /dev/null +++ b/src/resources/project/workspaces.ts @@ -0,0 +1,65 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Workspaces extends APIResource { + /** + * Get a specific workspace by ID with its projects. + */ + retrieve(workspaceID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/project/v1/workspaces/${workspaceID}`, options); + } + + /** + * Get all workspaces accessible by the current token. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/project/v1/workspaces', options); + } +} + +export interface WorkspaceRetrieveResponse { + data?: WorkspaceRetrieveResponse.Data; +} + +export namespace WorkspaceRetrieveResponse { + export interface Data { + id?: number; + + name?: string; + + projects?: Array; + } + + export namespace Data { + export interface Project { + id?: number; + + name?: string; + + status?: string; + } + } +} + +export interface WorkspaceListResponse { + data?: Array; +} + +export namespace WorkspaceListResponse { + export interface Data { + id?: number; + + name?: string; + } +} + +export declare namespace Workspaces { + export { + type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, + type WorkspaceListResponse as WorkspaceListResponse, + }; +} diff --git a/tests/api-resources/convert/full-to-simple.test.ts b/tests/api-resources/convert/full-to-simple.test.ts new file mode 100644 index 0000000..4f006a5 --- /dev/null +++ b/tests/api-resources/convert/full-to-simple.test.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource fullToSimple', () => { + test('create: only required params', async () => { + const responsePromise = client.convert.fullToSimple.create({ design: { body: {} } }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.convert.fullToSimple.create({ + design: { + body: {}, + counters: {}, + schemaVersion: 0, + }, + displayMode: 'email', + includeDefaultValues: true, + }); + }); +}); diff --git a/tests/api-resources/convert/simple-to-full.test.ts b/tests/api-resources/convert/simple-to-full.test.ts new file mode 100644 index 0000000..a78f6de --- /dev/null +++ b/tests/api-resources/convert/simple-to-full.test.ts @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource simpleToFull', () => { + test('create: only required params', async () => { + const responsePromise = client.convert.simpleToFull.create({ design: { body: {} } }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.convert.simpleToFull.create({ + design: { + body: {}, + _conversion: { data: 'data', version: 0 }, + counters: {}, + schemaVersion: 0, + }, + displayMode: 'email', + includeDefaultValues: true, + }); + }); +}); diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts deleted file mode 100644 index 4453628..0000000 --- a/tests/api-resources/documents.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource documents', () => { - test('documentsRetrieve: only required params', async () => { - const responsePromise = client.documents.documentsRetrieve('id', { projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('documentsRetrieve: required and optional params', async () => { - const response = await client.documents.documentsRetrieve('id', { projectId: 'projectId' }); - }); - - test('generateCreate: only required params', async () => { - const responsePromise = client.documents.generateCreate({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('generateCreate: required and optional params', async () => { - const response = await client.documents.generateCreate({ - projectId: 'projectId', - design: { foo: 'bar' }, - filename: 'filename', - html: 'html', - mergeTags: { foo: 'string' }, - url: 'https://example.com', - }); - }); - - test('generateTemplateTemplate: only required params', async () => { - const responsePromise = client.documents.generateTemplateTemplate({ - projectId: 'projectId', - templateId: 'templateId', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('generateTemplateTemplate: required and optional params', async () => { - const response = await client.documents.generateTemplateTemplate({ - projectId: 'projectId', - templateId: 'templateId', - filename: 'filename', - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/documents/documents.test.ts b/tests/api-resources/documents/documents.test.ts new file mode 100644 index 0000000..41f3924 --- /dev/null +++ b/tests/api-resources/documents/documents.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource documents', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.documents.retrieve('id', { projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.documents.retrieve('id', { projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/documents/generate-template.test.ts b/tests/api-resources/documents/generate-template.test.ts new file mode 100644 index 0000000..2fd929f --- /dev/null +++ b/tests/api-resources/documents/generate-template.test.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource generateTemplate', () => { + test('create: only required params', async () => { + const responsePromise = client.documents.generateTemplate.create({ + projectId: 'projectId', + templateId: 'templateId', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.documents.generateTemplate.create({ + projectId: 'projectId', + templateId: 'templateId', + filename: 'filename', + mergeTags: { foo: 'string' }, + }); + }); +}); diff --git a/tests/api-resources/documents/generate.test.ts b/tests/api-resources/documents/generate.test.ts new file mode 100644 index 0000000..6db57d6 --- /dev/null +++ b/tests/api-resources/documents/generate.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource generate', () => { + test('create: only required params', async () => { + const responsePromise = client.documents.generate.create({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.documents.generate.create({ + projectId: 'projectId', + design: { foo: 'bar' }, + filename: 'filename', + html: 'html', + mergeTags: { foo: 'string' }, + url: 'https://example.com', + }); + }); +}); diff --git a/tests/api-resources/emails/emails.test.ts b/tests/api-resources/emails/emails.test.ts new file mode 100644 index 0000000..c3e8e96 --- /dev/null +++ b/tests/api-resources/emails/emails.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource emails', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.emails.retrieve('id', { projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.emails.retrieve('id', { projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/pages.test.ts b/tests/api-resources/emails/render.test.ts similarity index 75% rename from tests/api-resources/pages.test.ts rename to tests/api-resources/emails/render.test.ts index b343b11..7dcbd01 100644 --- a/tests/api-resources/pages.test.ts +++ b/tests/api-resources/emails/render.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource pages', () => { - test('renderCreate: only required params', async () => { - const responsePromise = client.pages.renderCreate({ +describe('resource render', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.render.create({ projectId: 'projectId', design: { foo: 'bar' }, }); @@ -22,8 +22,8 @@ describe('resource pages', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('renderCreate: required and optional params', async () => { - const response = await client.pages.renderCreate({ + test('create: required and optional params', async () => { + const response = await client.emails.render.create({ projectId: 'projectId', design: { foo: 'bar' }, mergeTags: { foo: 'string' }, diff --git a/tests/api-resources/emails/send-template.test.ts b/tests/api-resources/emails/send-template.test.ts new file mode 100644 index 0000000..98e3b2b --- /dev/null +++ b/tests/api-resources/emails/send-template.test.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource sendTemplate', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.sendTemplate.create({ + projectId: 'projectId', + templateId: 'templateId', + to: 'dev@stainless.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.sendTemplate.create({ + projectId: 'projectId', + templateId: 'templateId', + to: 'dev@stainless.com', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); +}); diff --git a/tests/api-resources/emails/send.test.ts b/tests/api-resources/emails/send.test.ts new file mode 100644 index 0000000..39492f0 --- /dev/null +++ b/tests/api-resources/emails/send.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource send', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.send.create({ projectId: 'projectId', to: 'dev@stainless.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.send.create({ + projectId: 'projectId', + to: 'dev@stainless.com', + design: { foo: 'bar' }, + html: 'html', + mergeTags: { foo: 'string' }, + subject: 'subject', + }); + }); +}); diff --git a/tests/api-resources/export/html.test.ts b/tests/api-resources/export/html.test.ts new file mode 100644 index 0000000..9f59af0 --- /dev/null +++ b/tests/api-resources/export/html.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource html', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.export.html.retrieve({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.export.html.retrieve({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/export/image.test.ts b/tests/api-resources/export/image.test.ts new file mode 100644 index 0000000..598d5cb --- /dev/null +++ b/tests/api-resources/export/image.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource image', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.export.image.retrieve({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.export.image.retrieve({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/export/pdf.test.ts b/tests/api-resources/export/pdf.test.ts new file mode 100644 index 0000000..8bd3fc0 --- /dev/null +++ b/tests/api-resources/export/pdf.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource pdf', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.export.pdf.retrieve({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.export.pdf.retrieve({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/export/zip.test.ts b/tests/api-resources/export/zip.test.ts new file mode 100644 index 0000000..63a356c --- /dev/null +++ b/tests/api-resources/export/zip.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource zip', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.export.zip.retrieve({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.export.zip.retrieve({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/pages/render.test.ts b/tests/api-resources/pages/render.test.ts new file mode 100644 index 0000000..0e8cc65 --- /dev/null +++ b/tests/api-resources/pages/render.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource render', () => { + test('create: only required params', async () => { + const responsePromise = client.pages.render.create({ + projectId: 'projectId', + design: { foo: 'bar' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.pages.render.create({ + projectId: 'projectId', + design: { foo: 'bar' }, + mergeTags: { foo: 'string' }, + }); + }); +}); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts deleted file mode 100644 index 62f3eca..0000000 --- a/tests/api-resources/project.test.ts +++ /dev/null @@ -1,205 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource project', () => { - test('currentList: only required params', async () => { - const responsePromise = client.project.currentList({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('currentList: required and optional params', async () => { - const response = await client.project.currentList({ projectId: 'projectId' }); - }); - - test('domainsCreate: only required params', async () => { - const responsePromise = client.project.domainsCreate({ projectId: 'projectId', domain: 'domain' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsCreate: required and optional params', async () => { - const response = await client.project.domainsCreate({ projectId: 'projectId', domain: 'domain' }); - }); - - test('domainsDelete', async () => { - const responsePromise = client.project.domainsDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsList: only required params', async () => { - const responsePromise = client.project.domainsList({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsList: required and optional params', async () => { - const response = await client.project.domainsList({ projectId: 'projectId' }); - }); - - test('domainsRetrieve', async () => { - const responsePromise = client.project.domainsRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsUpdate', async () => { - const responsePromise = client.project.domainsUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('domainsUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.domainsUpdate('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - test('templatesCreate: only required params', async () => { - const responsePromise = client.project.templatesCreate({ projectId: 'projectId', name: 'name' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesCreate: required and optional params', async () => { - const response = await client.project.templatesCreate({ - projectId: 'projectId', - name: 'name', - displayMode: 'email', - }); - }); - - test('templatesDelete', async () => { - const responsePromise = client.project.templatesDelete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesList: only required params', async () => { - const responsePromise = client.project.templatesList({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesList: required and optional params', async () => { - const response = await client.project.templatesList({ - projectId: 'projectId', - cursor: 'cursor', - displayMode: 'email', - limit: 1, - name: 'name', - }); - }); - - test('templatesRetrieve', async () => { - const responsePromise = client.project.templatesRetrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesUpdate', async () => { - const responsePromise = client.project.templatesUpdate('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('templatesUpdate: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.templatesUpdate( - 'id', - { - body: 'body', - name: 'name', - subject: 'subject', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - test('workspacesList', async () => { - const responsePromise = client.project.workspacesList(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('workspacesRetrieve', async () => { - const responsePromise = client.project.workspacesRetrieve('workspaceId'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/project/current.test.ts b/tests/api-resources/project/current.test.ts new file mode 100644 index 0000000..8e2851d --- /dev/null +++ b/tests/api-resources/project/current.test.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource current', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.project.current.retrieve({ projectId: 'projectId' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.project.current.retrieve({ projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/export.test.ts b/tests/api-resources/project/domains.test.ts similarity index 52% rename from tests/api-resources/export.test.ts rename to tests/api-resources/project/domains.test.ts index 30efddd..57a618a 100644 --- a/tests/api-resources/export.test.ts +++ b/tests/api-resources/project/domains.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource export', () => { - test('htmlList: only required params', async () => { - const responsePromise = client.export.htmlList({ projectId: 'projectId' }); +describe('resource domains', () => { + test('create: only required params', async () => { + const responsePromise = client.project.domains.create({ projectId: 'projectId', domain: 'domain' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,12 +19,12 @@ describe('resource export', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('htmlList: required and optional params', async () => { - const response = await client.export.htmlList({ projectId: 'projectId' }); + test('create: required and optional params', async () => { + const response = await client.project.domains.create({ projectId: 'projectId', domain: 'domain' }); }); - test('imageList: only required params', async () => { - const responsePromise = client.export.imageList({ projectId: 'projectId' }); + test('retrieve', async () => { + const responsePromise = client.project.domains.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -34,12 +34,8 @@ describe('resource export', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('imageList: required and optional params', async () => { - const response = await client.export.imageList({ projectId: 'projectId' }); - }); - - test('pdfList: only required params', async () => { - const responsePromise = client.export.pdfList({ projectId: 'projectId' }); + test('update', async () => { + const responsePromise = client.project.domains.update('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -49,12 +45,15 @@ describe('resource export', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('pdfList: required and optional params', async () => { - const response = await client.export.pdfList({ projectId: 'projectId' }); + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.domains.update('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); }); - test('zipList: only required params', async () => { - const responsePromise = client.export.zipList({ projectId: 'projectId' }); + test('list: only required params', async () => { + const responsePromise = client.project.domains.list({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -64,7 +63,18 @@ describe('resource export', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('zipList: required and optional params', async () => { - const response = await client.export.zipList({ projectId: 'projectId' }); + test('list: required and optional params', async () => { + const response = await client.project.domains.list({ projectId: 'projectId' }); + }); + + test('delete', async () => { + const responsePromise = client.project.domains.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); }); }); diff --git a/tests/api-resources/emails.test.ts b/tests/api-resources/project/templates.test.ts similarity index 50% rename from tests/api-resources/emails.test.ts rename to tests/api-resources/project/templates.test.ts index 210fea6..4a487a8 100644 --- a/tests/api-resources/emails.test.ts +++ b/tests/api-resources/project/templates.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource emails', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.emails.retrieve('id', { projectId: 'projectId' }); +describe('resource templates', () => { + test('create: only required params', async () => { + const responsePromise = client.project.templates.create({ projectId: 'projectId', name: 'name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,15 +19,16 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('retrieve: required and optional params', async () => { - const response = await client.emails.retrieve('id', { projectId: 'projectId' }); - }); - - test('renderCreate: only required params', async () => { - const responsePromise = client.emails.renderCreate({ + test('create: required and optional params', async () => { + const response = await client.project.templates.create({ projectId: 'projectId', - design: { foo: 'bar' }, + name: 'name', + displayMode: 'email', }); + }); + + test('retrieve', async () => { + const responsePromise = client.project.templates.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -37,16 +38,8 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('renderCreate: required and optional params', async () => { - const response = await client.emails.renderCreate({ - projectId: 'projectId', - design: { foo: 'bar' }, - mergeTags: { foo: 'string' }, - }); - }); - - test('sendCreate: only required params', async () => { - const responsePromise = client.emails.sendCreate({ projectId: 'projectId', to: 'dev@stainless.com' }); + test('update', async () => { + const responsePromise = client.project.templates.update('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -56,23 +49,23 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('sendCreate: required and optional params', async () => { - const response = await client.emails.sendCreate({ - projectId: 'projectId', - to: 'dev@stainless.com', - design: { foo: 'bar' }, - html: 'html', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.templates.update( + 'id', + { + body: 'body', + name: 'name', + subject: 'subject', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); }); - test('sendTemplateTemplate: only required params', async () => { - const responsePromise = client.emails.sendTemplateTemplate({ - projectId: 'projectId', - templateId: 'templateId', - to: 'dev@stainless.com', - }); + test('list: only required params', async () => { + const responsePromise = client.project.templates.list({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -82,13 +75,24 @@ describe('resource emails', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('sendTemplateTemplate: required and optional params', async () => { - const response = await client.emails.sendTemplateTemplate({ + test('list: required and optional params', async () => { + const response = await client.project.templates.list({ projectId: 'projectId', - templateId: 'templateId', - to: 'dev@stainless.com', - mergeTags: { foo: 'string' }, - subject: 'subject', + cursor: 'cursor', + displayMode: 'email', + limit: 1, + name: 'name', }); }); + + test('delete', async () => { + const responsePromise = client.project.templates.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); }); diff --git a/tests/api-resources/project/workspaces.test.ts b/tests/api-resources/project/workspaces.test.ts new file mode 100644 index 0000000..fb9c997 --- /dev/null +++ b/tests/api-resources/project/workspaces.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource workspaces', () => { + test('retrieve', async () => { + const responsePromise = client.project.workspaces.retrieve('workspaceId'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list', async () => { + const responsePromise = client.project.workspaces.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); From d14a08fa65fb183e66bd1dae723b8ae9d694b946 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:30:05 +0000 Subject: [PATCH 050/118] feat(api): api update --- .stats.yml | 8 +- README.md | 61 ++++-- api.md | 170 ++--------------- src/client.ts | 35 +--- src/resources/convert/full-to-simple.ts | 12 +- src/resources/convert/simple-to-full.ts | 6 +- src/resources/documents.ts | 3 - src/resources/documents/documents.ts | 109 ----------- src/resources/documents/generate-template.ts | 72 ------- src/resources/documents/generate.ts | 79 -------- src/resources/documents/index.ts | 9 - src/resources/emails.ts | 3 - src/resources/emails/emails.ts | 103 ----------- src/resources/emails/index.ts | 10 - src/resources/emails/render.ts | 49 ----- src/resources/emails/send-template.ts | 64 ------- src/resources/emails/send.ts | 66 ------- src/resources/export.ts | 3 - src/resources/export/export.ts | 49 ----- src/resources/export/html.ts | 35 ---- src/resources/export/image.ts | 38 ---- src/resources/export/index.ts | 7 - src/resources/export/pdf.ts | 35 ---- src/resources/export/zip.ts | 35 ---- src/resources/index.ts | 7 +- src/resources/pages.ts | 3 - src/resources/pages/index.ts | 4 - src/resources/pages/pages.ts | 19 -- src/resources/pages/render.ts | 49 ----- src/resources/project/current.ts | 54 ------ src/resources/project/domains.ts | 162 ---------------- src/resources/project/index.ts | 20 +- src/resources/project/project.ts | 109 ++++++----- src/resources/project/templates.ts | 175 +++--------------- src/resources/{project => }/workspaces.ts | 12 +- .../convert/full-to-simple.test.ts | 7 +- .../convert/simple-to-full.test.ts | 6 +- .../api-resources/documents/documents.test.ts | 25 --- .../documents/generate-template.test.ts | 33 ---- .../api-resources/documents/generate.test.ts | 32 ---- tests/api-resources/emails/emails.test.ts | 25 --- tests/api-resources/emails/render.test.ts | 32 ---- .../emails/send-template.test.ts | 35 ---- tests/api-resources/emails/send.test.ts | 32 ---- tests/api-resources/export/html.test.ts | 25 --- tests/api-resources/export/image.test.ts | 25 --- tests/api-resources/export/zip.test.ts | 25 --- tests/api-resources/pages/render.test.ts | 32 ---- tests/api-resources/project/current.test.ts | 25 --- tests/api-resources/project/domains.test.ts | 80 -------- .../pdf.test.ts => project/project.test.ts} | 6 +- tests/api-resources/project/templates.test.ts | 60 +----- .../{project => }/workspaces.test.ts | 4 +- 53 files changed, 200 insertions(+), 1984 deletions(-) delete mode 100644 src/resources/documents.ts delete mode 100644 src/resources/documents/documents.ts delete mode 100644 src/resources/documents/generate-template.ts delete mode 100644 src/resources/documents/generate.ts delete mode 100644 src/resources/documents/index.ts delete mode 100644 src/resources/emails.ts delete mode 100644 src/resources/emails/emails.ts delete mode 100644 src/resources/emails/index.ts delete mode 100644 src/resources/emails/render.ts delete mode 100644 src/resources/emails/send-template.ts delete mode 100644 src/resources/emails/send.ts delete mode 100644 src/resources/export.ts delete mode 100644 src/resources/export/export.ts delete mode 100644 src/resources/export/html.ts delete mode 100644 src/resources/export/image.ts delete mode 100644 src/resources/export/index.ts delete mode 100644 src/resources/export/pdf.ts delete mode 100644 src/resources/export/zip.ts delete mode 100644 src/resources/pages.ts delete mode 100644 src/resources/pages/index.ts delete mode 100644 src/resources/pages/pages.ts delete mode 100644 src/resources/pages/render.ts delete mode 100644 src/resources/project/current.ts delete mode 100644 src/resources/project/domains.ts rename src/resources/{project => }/workspaces.ts (76%) delete mode 100644 tests/api-resources/documents/documents.test.ts delete mode 100644 tests/api-resources/documents/generate-template.test.ts delete mode 100644 tests/api-resources/documents/generate.test.ts delete mode 100644 tests/api-resources/emails/emails.test.ts delete mode 100644 tests/api-resources/emails/render.test.ts delete mode 100644 tests/api-resources/emails/send-template.test.ts delete mode 100644 tests/api-resources/emails/send.test.ts delete mode 100644 tests/api-resources/export/html.test.ts delete mode 100644 tests/api-resources/export/image.test.ts delete mode 100644 tests/api-resources/export/zip.test.ts delete mode 100644 tests/api-resources/pages/render.test.ts delete mode 100644 tests/api-resources/project/current.test.ts delete mode 100644 tests/api-resources/project/domains.test.ts rename tests/api-resources/{export/pdf.test.ts => project/project.test.ts} (79%) rename tests/api-resources/{project => }/workspaces.test.ts (88%) diff --git a/.stats.yml b/.stats.yml index c33024a..43eb3f0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 27 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-077d753eb6d4f805b2f84bf887289213f91c1da5f5a3a4e1e36e1da3689efb46.yml -openapi_spec_hash: b210022cf72d9a38fe1baee599054518 -config_hash: 15a2f2b4c1b498b9b314d587d6a331d0 +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-579dff50df9d2d3be275dc58817917d2efec68100883d139ae7d62908a24e5d6.yml +openapi_spec_hash: 8583074e5ea7cc31410a42c2c4550d7c +config_hash: 3c023f8805c0765c987ddcee566aabef diff --git a/README.md b/README.md index 9739903..6696fa1 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ const client = new Unlayer({ environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const fullToSimple = await client.convert.fullToSimple.create({ design: { body: {} } }); +const project = await client.project.retrieve({ projectId: 'your-project-id' }); -console.log(fullToSimple.data); +console.log(project.data); ``` ### Request & Response types @@ -48,9 +48,8 @@ const client = new Unlayer({ environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' }); -const params: Unlayer.Convert.FullToSimpleCreateParams = { design: { body: {} } }; -const fullToSimple: Unlayer.Convert.FullToSimpleCreateResponse = - await client.convert.fullToSimple.create(params); +const params: Unlayer.ProjectRetrieveParams = { projectId: 'your-project-id' }; +const project: Unlayer.ProjectRetrieveResponse = await client.project.retrieve(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -63,8 +62,8 @@ a subclass of `APIError` will be thrown: ```ts -const fullToSimple = await client.convert.fullToSimple - .create({ design: { body: {} } }) +const project = await client.project + .retrieve({ projectId: 'your-project-id' }) .catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 @@ -105,7 +104,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.convert.fullToSimple.create({ design: { body: {} } }, { +await client.project.retrieve({ projectId: 'your-project-id' }, { maxRetries: 5, }); ``` @@ -122,7 +121,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.convert.fullToSimple.create({ design: { body: {} } }, { +await client.project.retrieve({ projectId: 'your-project-id' }, { timeout: 5 * 1000, }); ``` @@ -131,6 +130,40 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). +## Auto-pagination + +List methods in the Unlayer API are paginated. +You can use the `for await … of` syntax to iterate through items across all pages: + +```ts +async function fetchAllTemplateListResponses(params) { + const allTemplateListResponses = []; + // Automatically fetches more pages as needed. + for await (const templateListResponse of client.project.templates.list({ + projectId: 'your-project-id', + limit: 10, + })) { + allTemplateListResponses.push(templateListResponse); + } + return allTemplateListResponses; +} +``` + +Alternatively, you can request a single page at a time: + +```ts +let page = await client.project.templates.list({ projectId: 'your-project-id', limit: 10 }); +for (const templateListResponse of page.data) { + console.log(templateListResponse); +} + +// Convenience methods are provided for manually paginating: +while (page.hasNextPage()) { + page = await page.getNextPage(); + // ... +} +``` + ## Advanced Usage ### Accessing raw Response data (e.g., headers) @@ -145,15 +178,15 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.convert.fullToSimple.create({ design: { body: {} } }).asResponse(); +const response = await client.project.retrieve({ projectId: 'your-project-id' }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: fullToSimple, response: raw } = await client.convert.fullToSimple - .create({ design: { body: {} } }) +const { data: project, response: raw } = await client.project + .retrieve({ projectId: 'your-project-id' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(fullToSimple.data); +console.log(project.data); ``` ### Logging @@ -233,7 +266,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.convert.fullToSimple.create({ +client.project.retrieve({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index eaccee5..102ed43 100644 --- a/api.md +++ b/api.md @@ -8,7 +8,7 @@ Types: Methods: -- client.convert.fullToSimple.create({ ...params }) -> FullToSimpleCreateResponse +- client.convert.fullToSimple.create({ ...params }) -> FullToSimpleCreateResponse ## SimpleToFull @@ -18,186 +18,38 @@ Types: Methods: -- client.convert.simpleToFull.create({ ...params }) -> SimpleToFullCreateResponse - -# Documents - -Types: - -- DocumentRetrieveResponse - -Methods: - -- client.documents.retrieve(id, { ...params }) -> DocumentRetrieveResponse - -## Generate - -Types: - -- GenerateCreateResponse - -Methods: - -- client.documents.generate.create({ ...params }) -> GenerateCreateResponse - -## GenerateTemplate - -Types: - -- GenerateTemplateCreateResponse - -Methods: - -- client.documents.generateTemplate.create({ ...params }) -> GenerateTemplateCreateResponse - -# Emails - -Types: - -- EmailRetrieveResponse - -Methods: - -- client.emails.retrieve(id, { ...params }) -> EmailRetrieveResponse - -## Render - -Types: - -- RenderCreateResponse - -Methods: - -- client.emails.render.create({ ...params }) -> RenderCreateResponse - -## Send - -Types: - -- SendCreateResponse - -Methods: - -- client.emails.send.create({ ...params }) -> SendCreateResponse - -## SendTemplate - -Types: - -- SendTemplateCreateResponse - -Methods: - -- client.emails.sendTemplate.create({ ...params }) -> SendTemplateCreateResponse - -# Export - -## HTML - -Types: - -- HTMLRetrieveResponse - -Methods: - -- client.export.html.retrieve({ ...params }) -> HTMLRetrieveResponse - -## Image - -Types: - -- ImageRetrieveResponse - -Methods: - -- client.export.image.retrieve({ ...params }) -> ImageRetrieveResponse - -## Pdf - -Types: - -- PdfRetrieveResponse - -Methods: - -- client.export.pdf.retrieve({ ...params }) -> PdfRetrieveResponse - -## Zip - -Types: - -- ZipRetrieveResponse - -Methods: - -- client.export.zip.retrieve({ ...params }) -> ZipRetrieveResponse - -# Pages - -## Render - -Types: - -- RenderCreateResponse - -Methods: - -- client.pages.render.create({ ...params }) -> RenderCreateResponse +- client.convert.simpleToFull.create({ ...params }) -> SimpleToFullCreateResponse # Project -## Current - -Types: - -- CurrentRetrieveResponse - -Methods: - -- client.project.current.retrieve({ ...params }) -> CurrentRetrieveResponse - -## Domains - Types: -- DomainCreateResponse -- DomainRetrieveResponse -- DomainUpdateResponse -- DomainListResponse +- ProjectRetrieveResponse Methods: -- client.project.domains.create({ ...params }) -> DomainCreateResponse -- client.project.domains.retrieve(id) -> DomainRetrieveResponse -- client.project.domains.update(id, { ...params }) -> DomainUpdateResponse -- client.project.domains.list({ ...params }) -> DomainListResponse -- client.project.domains.delete(id) -> void +- client.project.retrieve({ ...params }) -> ProjectRetrieveResponse ## Templates Types: -- TemplateCreateResponse - TemplateRetrieveResponse -- TemplateUpdateResponse - TemplateListResponse Methods: -- client.project.templates.create({ ...params }) -> TemplateCreateResponse -- client.project.templates.retrieve(id) -> TemplateRetrieveResponse -- client.project.templates.update(id, { ...params }) -> TemplateUpdateResponse -- client.project.templates.list({ ...params }) -> TemplateListResponse -- client.project.templates.delete(id) -> void +- client.project.templates.retrieve(id, { ...params }) -> TemplateRetrieveResponse +- client.project.templates.list({ ...params }) -> TemplateListResponsesCursorPage -## Workspaces +# Workspaces Types: -- WorkspaceRetrieveResponse -- WorkspaceListResponse +- WorkspaceRetrieveResponse +- WorkspaceListResponse Methods: -- client.project.workspaces.retrieve(workspaceID) -> WorkspaceRetrieveResponse -- client.project.workspaces.list() -> WorkspaceListResponse +- client.workspaces.retrieve(workspaceID) -> WorkspaceRetrieveResponse +- client.workspaces.list() -> WorkspaceListResponse diff --git a/src/client.ts b/src/client.ts index ce8e792..052468f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,12 +18,9 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; import { Convert } from './resources/convert/convert'; -import { DocumentRetrieveParams, DocumentRetrieveResponse, Documents } from './resources/documents/documents'; -import { EmailRetrieveParams, EmailRetrieveResponse, Emails } from './resources/emails/emails'; -import { Export } from './resources/export/export'; -import { Pages } from './resources/pages/pages'; -import { Project } from './resources/project/project'; +import { Project, ProjectRetrieveParams, ProjectRetrieveResponse } from './resources/project/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -781,19 +778,13 @@ export class Unlayer { static toFile = Uploads.toFile; convert: API.Convert = new API.Convert(this); - documents: API.Documents = new API.Documents(this); - emails: API.Emails = new API.Emails(this); - export: API.Export = new API.Export(this); - pages: API.Pages = new API.Pages(this); project: API.Project = new API.Project(this); + workspaces: API.Workspaces = new API.Workspaces(this); } Unlayer.Convert = Convert; -Unlayer.Documents = Documents; -Unlayer.Emails = Emails; -Unlayer.Export = Export; -Unlayer.Pages = Pages; Unlayer.Project = Project; +Unlayer.Workspaces = Workspaces; export declare namespace Unlayer { export type RequestOptions = Opts.RequestOptions; @@ -804,20 +795,14 @@ export declare namespace Unlayer { export { Convert as Convert }; export { - Documents as Documents, - type DocumentRetrieveResponse as DocumentRetrieveResponse, - type DocumentRetrieveParams as DocumentRetrieveParams, + Project as Project, + type ProjectRetrieveResponse as ProjectRetrieveResponse, + type ProjectRetrieveParams as ProjectRetrieveParams, }; export { - Emails as Emails, - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRetrieveParams as EmailRetrieveParams, + Workspaces as Workspaces, + type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, + type WorkspaceListResponse as WorkspaceListResponse, }; - - export { Export as Export }; - - export { Pages as Pages }; - - export { Project as Project }; } diff --git a/src/resources/convert/full-to-simple.ts b/src/resources/convert/full-to-simple.ts index da8cf22..44e02b9 100644 --- a/src/resources/convert/full-to-simple.ts +++ b/src/resources/convert/full-to-simple.ts @@ -9,7 +9,7 @@ export class FullToSimple extends APIResource { * Convert design json from Full to Simple schema. */ create(body: FullToSimpleCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/convert/full-to-simple', { body, ...options }); + return this._client.post('/v3/convert/full-to-simple', { body, ...options }); } } @@ -30,14 +30,20 @@ export interface FullToSimpleCreateParams { displayMode?: 'email' | 'web' | 'popup' | 'document'; + /** + * When true, includes \_conversion metadata in the response. This metadata can be + * passed to simple-to-full to restore original values without data loss. + */ + includeConversion?: boolean; + includeDefaultValues?: boolean; } export namespace FullToSimpleCreateParams { export interface Design { - body: unknown; + body: { [key: string]: unknown }; - counters?: unknown; + counters?: { [key: string]: unknown }; schemaVersion?: number; diff --git a/src/resources/convert/simple-to-full.ts b/src/resources/convert/simple-to-full.ts index 24d1681..c1051de 100644 --- a/src/resources/convert/simple-to-full.ts +++ b/src/resources/convert/simple-to-full.ts @@ -9,7 +9,7 @@ export class SimpleToFull extends APIResource { * Convert design json from Simple to Full schema. */ create(body: SimpleToFullCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/convert/simple-to-full', { body, ...options }); + return this._client.post('/v3/convert/simple-to-full', { body, ...options }); } } @@ -35,11 +35,11 @@ export interface SimpleToFullCreateParams { export namespace SimpleToFullCreateParams { export interface Design { - body: unknown; + body: { [key: string]: unknown }; _conversion?: Design._Conversion; - counters?: unknown; + counters?: { [key: string]: unknown }; schemaVersion?: number; diff --git a/src/resources/documents.ts b/src/resources/documents.ts deleted file mode 100644 index 6dcfade..0000000 --- a/src/resources/documents.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './documents/index'; diff --git a/src/resources/documents/documents.ts b/src/resources/documents/documents.ts deleted file mode 100644 index 515b005..0000000 --- a/src/resources/documents/documents.ts +++ /dev/null @@ -1,109 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as GenerateAPI from './generate'; -import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; -import * as GenerateTemplateAPI from './generate-template'; -import { - GenerateTemplate, - GenerateTemplateCreateParams, - GenerateTemplateCreateResponse, -} from './generate-template'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Documents extends APIResource { - generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); - generateTemplate: GenerateTemplateAPI.GenerateTemplate = new GenerateTemplateAPI.GenerateTemplate( - this._client, - ); - - /** - * Retrieve details of a previously generated document. - */ - retrieve( - id: string, - query: DocumentRetrieveParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/documents/v1/documents/${id}`, { query, ...options }); - } -} - -export interface DocumentRetrieveResponse { - data?: DocumentRetrieveResponse.Data; -} - -export namespace DocumentRetrieveResponse { - export interface Data { - /** - * Document ID - */ - id?: string; - - /** - * When the document generation was completed - */ - completedAt?: string; - - /** - * When the document was created - */ - createdAt?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * File size in bytes - */ - fileSize?: number; - - /** - * Number of pages in the PDF - */ - pageCount?: number; - - /** - * URL to download the PDF - */ - pdfUrl?: string; - - /** - * Current document status - */ - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface DocumentRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -Documents.Generate = Generate; -Documents.GenerateTemplate = GenerateTemplate; - -export declare namespace Documents { - export { - type DocumentRetrieveResponse as DocumentRetrieveResponse, - type DocumentRetrieveParams as DocumentRetrieveParams, - }; - - export { - Generate as Generate, - type GenerateCreateResponse as GenerateCreateResponse, - type GenerateCreateParams as GenerateCreateParams, - }; - - export { - GenerateTemplate as GenerateTemplate, - type GenerateTemplateCreateResponse as GenerateTemplateCreateResponse, - type GenerateTemplateCreateParams as GenerateTemplateCreateParams, - }; -} diff --git a/src/resources/documents/generate-template.ts b/src/resources/documents/generate-template.ts deleted file mode 100644 index 60c6b31..0000000 --- a/src/resources/documents/generate-template.ts +++ /dev/null @@ -1,72 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class GenerateTemplate extends APIResource { - /** - * Generate PDF document from an existing template with merge tags. - */ - create( - params: GenerateTemplateCreateParams, - options?: RequestOptions, - ): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/documents/v1/generate/template', { query: { projectId }, body, ...options }); - } -} - -export interface GenerateTemplateCreateResponse { - data?: GenerateTemplateCreateResponse.Data; -} - -export namespace GenerateTemplateCreateResponse { - export interface Data { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface GenerateTemplateCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: ID of the template to use for generation - */ - templateId: string; - - /** - * Body param: Optional filename for the generated PDF - */ - filename?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace GenerateTemplate { - export { - type GenerateTemplateCreateResponse as GenerateTemplateCreateResponse, - type GenerateTemplateCreateParams as GenerateTemplateCreateParams, - }; -} diff --git a/src/resources/documents/generate.ts b/src/resources/documents/generate.ts deleted file mode 100644 index 2d02591..0000000 --- a/src/resources/documents/generate.ts +++ /dev/null @@ -1,79 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Generate extends APIResource { - /** - * Generate PDF document from JSON design, HTML content, or URL. - */ - create(params: GenerateCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/documents/v1/generate', { query: { projectId }, body, ...options }); - } -} - -export interface GenerateCreateResponse { - data?: GenerateCreateResponse.Data; -} - -export namespace GenerateCreateResponse { - export interface Data { - /** - * Unique document identifier - */ - documentId?: string; - - /** - * Generated filename - */ - filename?: string; - - /** - * URL to download the generated PDF - */ - pdfUrl?: string; - - status?: 'generating' | 'completed' | 'failed'; - } -} - -export interface GenerateCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design?: { [key: string]: unknown }; - - /** - * Body param: Optional filename for the generated PDF - */ - filename?: string; - - /** - * Body param: HTML content to convert to PDF - */ - html?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: URL to convert to PDF - */ - url?: string; -} - -export declare namespace Generate { - export { - type GenerateCreateResponse as GenerateCreateResponse, - type GenerateCreateParams as GenerateCreateParams, - }; -} diff --git a/src/resources/documents/index.ts b/src/resources/documents/index.ts deleted file mode 100644 index 9d23892..0000000 --- a/src/resources/documents/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Documents, type DocumentRetrieveResponse, type DocumentRetrieveParams } from './documents'; -export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; -export { - GenerateTemplate, - type GenerateTemplateCreateResponse, - type GenerateTemplateCreateParams, -} from './generate-template'; diff --git a/src/resources/emails.ts b/src/resources/emails.ts deleted file mode 100644 index bd0ec59..0000000 --- a/src/resources/emails.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './emails/index'; diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts deleted file mode 100644 index 41459dc..0000000 --- a/src/resources/emails/emails.ts +++ /dev/null @@ -1,103 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as RenderAPI from './render'; -import { Render, RenderCreateParams, RenderCreateResponse } from './render'; -import * as SendAPI from './send'; -import { Send, SendCreateParams, SendCreateResponse } from './send'; -import * as SendTemplateAPI from './send-template'; -import { SendTemplate, SendTemplateCreateParams, SendTemplateCreateResponse } from './send-template'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Emails extends APIResource { - render: RenderAPI.Render = new RenderAPI.Render(this._client); - send: SendAPI.Send = new SendAPI.Send(this._client); - sendTemplate: SendTemplateAPI.SendTemplate = new SendTemplateAPI.SendTemplate(this._client); - - /** - * Retrieve details of a previously sent email. - */ - retrieve( - id: string, - query: EmailRetrieveParams, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/emails/v1/emails/${id}`, { query, ...options }); - } -} - -export interface EmailRetrieveResponse { - data?: EmailRetrieveResponse.Data; -} - -export namespace EmailRetrieveResponse { - export interface Data { - /** - * Email message ID - */ - id?: string; - - /** - * HTML content of the email (optional) - */ - html?: string; - - /** - * When the email was sent - */ - sentAt?: string; - - /** - * Current email status - */ - status?: 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'failed'; - - /** - * Email subject line - */ - subject?: string; - - /** - * Recipient email address - */ - to?: string; - } -} - -export interface EmailRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -Emails.Render = Render; -Emails.Send = Send; -Emails.SendTemplate = SendTemplate; - -export declare namespace Emails { - export { - type EmailRetrieveResponse as EmailRetrieveResponse, - type EmailRetrieveParams as EmailRetrieveParams, - }; - - export { - Render as Render, - type RenderCreateResponse as RenderCreateResponse, - type RenderCreateParams as RenderCreateParams, - }; - - export { - Send as Send, - type SendCreateResponse as SendCreateResponse, - type SendCreateParams as SendCreateParams, - }; - - export { - SendTemplate as SendTemplate, - type SendTemplateCreateResponse as SendTemplateCreateResponse, - type SendTemplateCreateParams as SendTemplateCreateParams, - }; -} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts deleted file mode 100644 index a047eda..0000000 --- a/src/resources/emails/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Emails, type EmailRetrieveResponse, type EmailRetrieveParams } from './emails'; -export { Render, type RenderCreateResponse, type RenderCreateParams } from './render'; -export { Send, type SendCreateResponse, type SendCreateParams } from './send'; -export { - SendTemplate, - type SendTemplateCreateResponse, - type SendTemplateCreateParams, -} from './send-template'; diff --git a/src/resources/emails/render.ts b/src/resources/emails/render.ts deleted file mode 100644 index 6dd2be1..0000000 --- a/src/resources/emails/render.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Render extends APIResource { - /** - * Convert design JSON to HTML with optional merge tags. - */ - create(params: RenderCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/render', { query: { projectId }, body, ...options }); - } -} - -export interface RenderCreateResponse { - data?: RenderCreateResponse.Data; -} - -export namespace RenderCreateResponse { - export interface Data { - /** - * Rendered HTML content - */ - html?: string; - } -} - -export interface RenderCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Render { - export { type RenderCreateResponse as RenderCreateResponse, type RenderCreateParams as RenderCreateParams }; -} diff --git a/src/resources/emails/send-template.ts b/src/resources/emails/send-template.ts deleted file mode 100644 index 2336dbe..0000000 --- a/src/resources/emails/send-template.ts +++ /dev/null @@ -1,64 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class SendTemplate extends APIResource { - /** - * Send email using an existing template with merge tags. - */ - create(params: SendTemplateCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/send/template', { query: { projectId }, body, ...options }); - } -} - -export interface SendTemplateCreateResponse { - data?: SendTemplateCreateResponse.Data; -} - -export namespace SendTemplateCreateResponse { - export interface Data { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; - } -} - -export interface SendTemplateCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: ID of the template to use - */ - templateId: string; - - /** - * Body param: Recipient email address - */ - to: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: Email subject line (optional, uses template default if not provided) - */ - subject?: string; -} - -export declare namespace SendTemplate { - export { - type SendTemplateCreateResponse as SendTemplateCreateResponse, - type SendTemplateCreateParams as SendTemplateCreateParams, - }; -} diff --git a/src/resources/emails/send.ts b/src/resources/emails/send.ts deleted file mode 100644 index d47ebd4..0000000 --- a/src/resources/emails/send.ts +++ /dev/null @@ -1,66 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Send extends APIResource { - /** - * Send email with design JSON or HTML content. - */ - create(params: SendCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/emails/v1/send', { query: { projectId }, body, ...options }); - } -} - -export interface SendCreateResponse { - data?: SendCreateResponse.Data; -} - -export namespace SendCreateResponse { - export interface Data { - /** - * Unique message identifier - */ - messageId?: string; - - status?: 'sent' | 'queued' | 'failed'; - } -} - -export interface SendCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Recipient email address - */ - to: string; - - /** - * Body param: Proprietary design format JSON - */ - design?: { [key: string]: unknown }; - - /** - * Body param: HTML content to send - */ - html?: string; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; - - /** - * Body param: Email subject line - */ - subject?: string; -} - -export declare namespace Send { - export { type SendCreateResponse as SendCreateResponse, type SendCreateParams as SendCreateParams }; -} diff --git a/src/resources/export.ts b/src/resources/export.ts deleted file mode 100644 index d368bec..0000000 --- a/src/resources/export.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './export/index'; diff --git a/src/resources/export/export.ts b/src/resources/export/export.ts deleted file mode 100644 index c5c2a30..0000000 --- a/src/resources/export/export.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as HTMLAPI from './html'; -import { HTML, HTMLRetrieveParams, HTMLRetrieveResponse } from './html'; -import * as ImageAPI from './image'; -import { Image, ImageRetrieveParams, ImageRetrieveResponse } from './image'; -import * as PdfAPI from './pdf'; -import { Pdf, PdfRetrieveParams, PdfRetrieveResponse } from './pdf'; -import * as ZipAPI from './zip'; -import { Zip, ZipRetrieveParams, ZipRetrieveResponse } from './zip'; - -export class Export extends APIResource { - html: HTMLAPI.HTML = new HTMLAPI.HTML(this._client); - image: ImageAPI.Image = new ImageAPI.Image(this._client); - pdf: PdfAPI.Pdf = new PdfAPI.Pdf(this._client); - zip: ZipAPI.Zip = new ZipAPI.Zip(this._client); -} - -Export.HTML = HTML; -Export.Image = Image; -Export.Pdf = Pdf; -Export.Zip = Zip; - -export declare namespace Export { - export { - HTML as HTML, - type HTMLRetrieveResponse as HTMLRetrieveResponse, - type HTMLRetrieveParams as HTMLRetrieveParams, - }; - - export { - Image as Image, - type ImageRetrieveResponse as ImageRetrieveResponse, - type ImageRetrieveParams as ImageRetrieveParams, - }; - - export { - Pdf as Pdf, - type PdfRetrieveResponse as PdfRetrieveResponse, - type PdfRetrieveParams as PdfRetrieveParams, - }; - - export { - Zip as Zip, - type ZipRetrieveResponse as ZipRetrieveResponse, - type ZipRetrieveParams as ZipRetrieveParams, - }; -} diff --git a/src/resources/export/html.ts b/src/resources/export/html.ts deleted file mode 100644 index 68816b6..0000000 --- a/src/resources/export/html.ts +++ /dev/null @@ -1,35 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class HTML extends APIResource { - /** - * Export design to HTML. - */ - retrieve(query: HTMLRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/html', { query, ...options }); - } -} - -export interface HTMLRetrieveResponse { - data?: HTMLRetrieveResponse.Data; -} - -export namespace HTMLRetrieveResponse { - export interface Data { - success?: boolean; - } -} - -export interface HTMLRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace HTML { - export { type HTMLRetrieveResponse as HTMLRetrieveResponse, type HTMLRetrieveParams as HTMLRetrieveParams }; -} diff --git a/src/resources/export/image.ts b/src/resources/export/image.ts deleted file mode 100644 index b9dba53..0000000 --- a/src/resources/export/image.ts +++ /dev/null @@ -1,38 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Image extends APIResource { - /** - * Export design to image. - */ - retrieve(query: ImageRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/image', { query, ...options }); - } -} - -export interface ImageRetrieveResponse { - data?: ImageRetrieveResponse.Data; -} - -export namespace ImageRetrieveResponse { - export interface Data { - success?: boolean; - } -} - -export interface ImageRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Image { - export { - type ImageRetrieveResponse as ImageRetrieveResponse, - type ImageRetrieveParams as ImageRetrieveParams, - }; -} diff --git a/src/resources/export/index.ts b/src/resources/export/index.ts deleted file mode 100644 index 2b9b59d..0000000 --- a/src/resources/export/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Export } from './export'; -export { HTML, type HTMLRetrieveResponse, type HTMLRetrieveParams } from './html'; -export { Image, type ImageRetrieveResponse, type ImageRetrieveParams } from './image'; -export { Pdf, type PdfRetrieveResponse, type PdfRetrieveParams } from './pdf'; -export { Zip, type ZipRetrieveResponse, type ZipRetrieveParams } from './zip'; diff --git a/src/resources/export/pdf.ts b/src/resources/export/pdf.ts deleted file mode 100644 index 307f2db..0000000 --- a/src/resources/export/pdf.ts +++ /dev/null @@ -1,35 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Pdf extends APIResource { - /** - * Export design to PDF. - */ - retrieve(query: PdfRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/pdf', { query, ...options }); - } -} - -export interface PdfRetrieveResponse { - data?: PdfRetrieveResponse.Data; -} - -export namespace PdfRetrieveResponse { - export interface Data { - success?: boolean; - } -} - -export interface PdfRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Pdf { - export { type PdfRetrieveResponse as PdfRetrieveResponse, type PdfRetrieveParams as PdfRetrieveParams }; -} diff --git a/src/resources/export/zip.ts b/src/resources/export/zip.ts deleted file mode 100644 index 3436f8c..0000000 --- a/src/resources/export/zip.ts +++ /dev/null @@ -1,35 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Zip extends APIResource { - /** - * Export design to ZIP archive. - */ - retrieve(query: ZipRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/export/v3/zip', { query, ...options }); - } -} - -export interface ZipRetrieveResponse { - data?: ZipRetrieveResponse.Data; -} - -export namespace ZipRetrieveResponse { - export interface Data { - success?: boolean; - } -} - -export interface ZipRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Zip { - export { type ZipRetrieveResponse as ZipRetrieveResponse, type ZipRetrieveParams as ZipRetrieveParams }; -} diff --git a/src/resources/index.ts b/src/resources/index.ts index 91eb561..c51af00 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,8 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Convert } from './convert/convert'; -export { Documents, type DocumentRetrieveResponse, type DocumentRetrieveParams } from './documents/documents'; -export { Emails, type EmailRetrieveResponse, type EmailRetrieveParams } from './emails/emails'; -export { Export } from './export/export'; -export { Pages } from './pages/pages'; -export { Project } from './project/project'; +export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project/project'; +export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/pages.ts b/src/resources/pages.ts deleted file mode 100644 index c218cbe..0000000 --- a/src/resources/pages.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './pages/index'; diff --git a/src/resources/pages/index.ts b/src/resources/pages/index.ts deleted file mode 100644 index 3398157..0000000 --- a/src/resources/pages/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Pages } from './pages'; -export { Render, type RenderCreateResponse, type RenderCreateParams } from './render'; diff --git a/src/resources/pages/pages.ts b/src/resources/pages/pages.ts deleted file mode 100644 index c28ceeb..0000000 --- a/src/resources/pages/pages.ts +++ /dev/null @@ -1,19 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as RenderAPI from './render'; -import { Render, RenderCreateParams, RenderCreateResponse } from './render'; - -export class Pages extends APIResource { - render: RenderAPI.Render = new RenderAPI.Render(this._client); -} - -Pages.Render = Render; - -export declare namespace Pages { - export { - Render as Render, - type RenderCreateResponse as RenderCreateResponse, - type RenderCreateParams as RenderCreateParams, - }; -} diff --git a/src/resources/pages/render.ts b/src/resources/pages/render.ts deleted file mode 100644 index 0b55f31..0000000 --- a/src/resources/pages/render.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Render extends APIResource { - /** - * Convert page design JSON to HTML with optional merge tags. - */ - create(params: RenderCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/pages/v1/render', { query: { projectId }, body, ...options }); - } -} - -export interface RenderCreateResponse { - data?: RenderCreateResponse.Data; -} - -export namespace RenderCreateResponse { - export interface Data { - /** - * Rendered HTML content - */ - html?: string; - } -} - -export interface RenderCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Proprietary design format JSON - */ - design: { [key: string]: unknown }; - - /** - * Body param: Optional merge tags for personalization - */ - mergeTags?: { [key: string]: string }; -} - -export declare namespace Render { - export { type RenderCreateResponse as RenderCreateResponse, type RenderCreateParams as RenderCreateParams }; -} diff --git a/src/resources/project/current.ts b/src/resources/project/current.ts deleted file mode 100644 index 361bcb1..0000000 --- a/src/resources/project/current.ts +++ /dev/null @@ -1,54 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Current extends APIResource { - /** - * Get project details for the specified project. - */ - retrieve(query: CurrentRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/current', { query, ...options }); - } -} - -export interface CurrentRetrieveResponse { - data?: CurrentRetrieveResponse.Data; -} - -export namespace CurrentRetrieveResponse { - export interface Data { - id?: number; - - createdAt?: string; - - name?: string; - - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface CurrentRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Current { - export { - type CurrentRetrieveResponse as CurrentRetrieveResponse, - type CurrentRetrieveParams as CurrentRetrieveParams, - }; -} diff --git a/src/resources/project/domains.ts b/src/resources/project/domains.ts deleted file mode 100644 index cac4a6f..0000000 --- a/src/resources/project/domains.ts +++ /dev/null @@ -1,162 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { buildHeaders } from '../../internal/headers'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; - -export class Domains extends APIResource { - /** - * Add a new domain to the project. - */ - create(params: DomainCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/project/v1/domains', { query: { projectId }, body, ...options }); - } - - /** - * Get domain details by ID. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/domains/${id}`, options); - } - - /** - * Update domain settings. - */ - update( - id: string, - body: DomainUpdateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/domains/${id}`, { body, ...options }); - } - - /** - * List all domains for the project. - */ - list(query: DomainListParams, options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/domains', { query, ...options }); - } - - /** - * Remove domain from project. - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/domains/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export interface DomainCreateResponse { - data?: DomainCreateResponse.Data; -} - -export namespace DomainCreateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainRetrieveResponse { - data?: DomainRetrieveResponse.Data; -} - -export namespace DomainRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainUpdateResponse { - data?: DomainUpdateResponse.Data; -} - -export namespace DomainUpdateResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: string; - - verified?: boolean; - } -} - -export interface DomainListResponse { - data?: Array; -} - -export namespace DomainListResponse { - export interface Data { - id?: string; - - createdAt?: string; - - domain?: string; - - status?: 'active' | 'pending' | 'failed'; - - verified?: boolean; - } -} - -export interface DomainCreateParams { - /** - * Query param: The project ID - */ - projectId: string; - - /** - * Body param: Domain name to add - */ - domain: string; -} - -export interface DomainUpdateParams { - /** - * Updated domain name - */ - domain?: string; -} - -export interface DomainListParams { - /** - * The project ID - */ - projectId: string; -} - -export declare namespace Domains { - export { - type DomainCreateResponse as DomainCreateResponse, - type DomainRetrieveResponse as DomainRetrieveResponse, - type DomainUpdateResponse as DomainUpdateResponse, - type DomainListResponse as DomainListResponse, - type DomainCreateParams as DomainCreateParams, - type DomainUpdateParams as DomainUpdateParams, - type DomainListParams as DomainListParams, - }; -} diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts index 1733b9a..0cb65dc 100644 --- a/src/resources/project/index.ts +++ b/src/resources/project/index.ts @@ -1,25 +1,11 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Current, type CurrentRetrieveResponse, type CurrentRetrieveParams } from './current'; -export { - Domains, - type DomainCreateResponse, - type DomainRetrieveResponse, - type DomainUpdateResponse, - type DomainListResponse, - type DomainCreateParams, - type DomainUpdateParams, - type DomainListParams, -} from './domains'; -export { Project } from './project'; +export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project'; export { Templates, - type TemplateCreateResponse, type TemplateRetrieveResponse, - type TemplateUpdateResponse, type TemplateListResponse, - type TemplateCreateParams, - type TemplateUpdateParams, + type TemplateRetrieveParams, type TemplateListParams, + type TemplateListResponsesCursorPage, } from './templates'; -export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts index 1dbe3da..5ceae62 100644 --- a/src/resources/project/project.ts +++ b/src/resources/project/project.ts @@ -1,77 +1,88 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import * as CurrentAPI from './current'; -import { Current, CurrentRetrieveParams, CurrentRetrieveResponse } from './current'; -import * as DomainsAPI from './domains'; -import { - DomainCreateParams, - DomainCreateResponse, - DomainListParams, - DomainListResponse, - DomainRetrieveResponse, - DomainUpdateParams, - DomainUpdateResponse, - Domains, -} from './domains'; import * as TemplatesAPI from './templates'; import { - TemplateCreateParams, - TemplateCreateResponse, TemplateListParams, TemplateListResponse, + TemplateListResponsesCursorPage, + TemplateRetrieveParams, TemplateRetrieveResponse, - TemplateUpdateParams, - TemplateUpdateResponse, Templates, } from './templates'; -import * as WorkspacesAPI from './workspaces'; -import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './workspaces'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; export class Project extends APIResource { - current: CurrentAPI.Current = new CurrentAPI.Current(this._client); - domains: DomainsAPI.Domains = new DomainsAPI.Domains(this._client); templates: TemplatesAPI.Templates = new TemplatesAPI.Templates(this._client); - workspaces: WorkspacesAPI.Workspaces = new WorkspacesAPI.Workspaces(this._client); + + /** + * Get project details for the specified project. + */ + retrieve(query: ProjectRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/v3/project', { query, ...options }); + } +} + +export interface ProjectRetrieveResponse { + data?: ProjectRetrieveResponse.Data; +} + +export namespace ProjectRetrieveResponse { + export interface Data { + /** + * The project ID. + */ + id?: number; + + /** + * When the project was created. + */ + createdAt?: string; + + /** + * The project name. + */ + name?: string; + + /** + * The project status. + */ + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectRetrieveParams { + /** + * The project ID + */ + projectId: string; } -Project.Current = Current; -Project.Domains = Domains; Project.Templates = Templates; -Project.Workspaces = Workspaces; export declare namespace Project { export { - Current as Current, - type CurrentRetrieveResponse as CurrentRetrieveResponse, - type CurrentRetrieveParams as CurrentRetrieveParams, - }; - - export { - Domains as Domains, - type DomainCreateResponse as DomainCreateResponse, - type DomainRetrieveResponse as DomainRetrieveResponse, - type DomainUpdateResponse as DomainUpdateResponse, - type DomainListResponse as DomainListResponse, - type DomainCreateParams as DomainCreateParams, - type DomainUpdateParams as DomainUpdateParams, - type DomainListParams as DomainListParams, + type ProjectRetrieveResponse as ProjectRetrieveResponse, + type ProjectRetrieveParams as ProjectRetrieveParams, }; export { Templates as Templates, - type TemplateCreateResponse as TemplateCreateResponse, type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateUpdateResponse as TemplateUpdateResponse, type TemplateListResponse as TemplateListResponse, - type TemplateCreateParams as TemplateCreateParams, - type TemplateUpdateParams as TemplateUpdateParams, + type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, + type TemplateRetrieveParams as TemplateRetrieveParams, type TemplateListParams as TemplateListParams, }; - - export { - Workspaces as Workspaces, - type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, - type WorkspaceListResponse as WorkspaceListResponse, - }; } diff --git a/src/resources/project/templates.ts b/src/resources/project/templates.ts index 6faa6ee..3438f71 100644 --- a/src/resources/project/templates.ts +++ b/src/resources/project/templates.ts @@ -2,82 +2,38 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; -import { buildHeaders } from '../../internal/headers'; +import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; export class Templates extends APIResource { - /** - * Create a new project template. - */ - create(params: TemplateCreateParams, options?: RequestOptions): APIPromise { - const { projectId, ...body } = params; - return this._client.post('/project/v1/templates', { query: { projectId }, body, ...options }); - } - /** * Get project template by ID. */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/templates/${id}`, options); - } - - /** - * Update project template. - */ - update( + retrieve( id: string, - body: TemplateUpdateParams | null | undefined = {}, + query: TemplateRetrieveParams, options?: RequestOptions, - ): APIPromise { - return this._client.put(path`/project/v1/templates/${id}`, { body, ...options }); + ): APIPromise { + return this._client.get(path`/v3/project/templates/${id}`, { query, ...options }); } /** * List project templates with cursor-based pagination. Returns templates in * descending order by update time. */ - list(query: TemplateListParams, options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/templates', { query, ...options }); - } - - /** - * Delete project template. - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/project/v1/templates/${id}`, { + list( + query: TemplateListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/v3/project/templates', CursorPage, { + query, ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } } -export interface TemplateCreateResponse { - data?: TemplateCreateResponse.Data; -} - -export namespace TemplateCreateResponse { - export interface Data { - /** - * Template ID - */ - id?: string; - - createdAt?: string; - - /** - * Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Template name - */ - name?: string; - - updatedAt?: string; - } -} +export type TemplateListResponsesCursorPage = CursorPage; export interface TemplateRetrieveResponse { data?: TemplateRetrieveResponse.Data; @@ -87,130 +43,59 @@ export namespace TemplateRetrieveResponse { export interface Data { id?: string; - body?: string; - createdAt?: string; - name?: string; - - subject?: string; + design?: { [key: string]: unknown }; - updatedAt?: string; - } -} - -export interface TemplateUpdateResponse { - data?: TemplateUpdateResponse.Data; -} - -export namespace TemplateUpdateResponse { - export interface Data { - id?: string; + displayMode?: 'email' | 'web' | 'document'; - body?: string; - - createdAt?: string; + html?: string | null; name?: string; - subject?: string; - updatedAt?: string; } } export interface TemplateListResponse { - data: Array; - - /** - * Whether there are more results after this page - */ - has_more: boolean; - /** - * Cursor for the next page. Null if no more results. + * Template ID */ - next_cursor?: string | null; -} - -export namespace TemplateListResponse { - export interface Data { - /** - * Template ID - */ - id?: string; + id?: string; - createdAt?: string; - - /** - * Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Template name - */ - name?: string; + createdAt?: string; - updatedAt?: string; - } -} - -export interface TemplateCreateParams { /** - * Query param: The project ID to create the template in - */ - projectId: string; - - /** - * Body param: Template name - */ - name: string; - - /** - * Body param: Template type/display mode + * Template type/display mode */ displayMode?: 'email' | 'web' | 'document'; -} - -export interface TemplateUpdateParams { - /** - * Updated email body content - */ - body?: string; /** - * Updated template name + * Template name */ name?: string; - /** - * Updated email subject line - */ - subject?: string; + updatedAt?: string; } -export interface TemplateListParams { +export interface TemplateRetrieveParams { /** - * The project ID to list templates for + * The project ID */ projectId: string; +} +export interface TemplateListParams extends CursorPageParams { /** - * Pagination cursor from previous response + * The project ID to list templates for */ - cursor?: string; + projectId: string; /** * Filter by template type */ displayMode?: 'email' | 'web' | 'document'; - /** - * Number of templates to return (1-100) - */ - limit?: number; - /** * Filter by name (case-insensitive search) */ @@ -219,12 +104,10 @@ export interface TemplateListParams { export declare namespace Templates { export { - type TemplateCreateResponse as TemplateCreateResponse, type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateUpdateResponse as TemplateUpdateResponse, type TemplateListResponse as TemplateListResponse, - type TemplateCreateParams as TemplateCreateParams, - type TemplateUpdateParams as TemplateUpdateParams, + type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, + type TemplateRetrieveParams as TemplateRetrieveParams, type TemplateListParams as TemplateListParams, }; } diff --git a/src/resources/project/workspaces.ts b/src/resources/workspaces.ts similarity index 76% rename from src/resources/project/workspaces.ts rename to src/resources/workspaces.ts index 083fd3b..a81dc2f 100644 --- a/src/resources/project/workspaces.ts +++ b/src/resources/workspaces.ts @@ -1,23 +1,23 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; export class Workspaces extends APIResource { /** * Get a specific workspace by ID with its projects. */ retrieve(workspaceID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/project/v1/workspaces/${workspaceID}`, options); + return this._client.get(path`/v3/workspaces/${workspaceID}`, options); } /** * Get all workspaces accessible by the current token. */ list(options?: RequestOptions): APIPromise { - return this._client.get('/project/v1/workspaces', options); + return this._client.get('/v3/workspaces', options); } } diff --git a/tests/api-resources/convert/full-to-simple.test.ts b/tests/api-resources/convert/full-to-simple.test.ts index 4f006a5..f33082d 100644 --- a/tests/api-resources/convert/full-to-simple.test.ts +++ b/tests/api-resources/convert/full-to-simple.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource fullToSimple', () => { test('create: only required params', async () => { - const responsePromise = client.convert.fullToSimple.create({ design: { body: {} } }); + const responsePromise = client.convert.fullToSimple.create({ design: { body: { foo: 'bar' } } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -22,11 +22,12 @@ describe('resource fullToSimple', () => { test('create: required and optional params', async () => { const response = await client.convert.fullToSimple.create({ design: { - body: {}, - counters: {}, + body: { foo: 'bar' }, + counters: { foo: 'bar' }, schemaVersion: 0, }, displayMode: 'email', + includeConversion: true, includeDefaultValues: true, }); }); diff --git a/tests/api-resources/convert/simple-to-full.test.ts b/tests/api-resources/convert/simple-to-full.test.ts index a78f6de..cef0634 100644 --- a/tests/api-resources/convert/simple-to-full.test.ts +++ b/tests/api-resources/convert/simple-to-full.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource simpleToFull', () => { test('create: only required params', async () => { - const responsePromise = client.convert.simpleToFull.create({ design: { body: {} } }); + const responsePromise = client.convert.simpleToFull.create({ design: { body: { foo: 'bar' } } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -22,9 +22,9 @@ describe('resource simpleToFull', () => { test('create: required and optional params', async () => { const response = await client.convert.simpleToFull.create({ design: { - body: {}, + body: { foo: 'bar' }, _conversion: { data: 'data', version: 0 }, - counters: {}, + counters: { foo: 'bar' }, schemaVersion: 0, }, displayMode: 'email', diff --git a/tests/api-resources/documents/documents.test.ts b/tests/api-resources/documents/documents.test.ts deleted file mode 100644 index 41f3924..0000000 --- a/tests/api-resources/documents/documents.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource documents', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.documents.retrieve('id', { projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.documents.retrieve('id', { projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/documents/generate-template.test.ts b/tests/api-resources/documents/generate-template.test.ts deleted file mode 100644 index 2fd929f..0000000 --- a/tests/api-resources/documents/generate-template.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource generateTemplate', () => { - test('create: only required params', async () => { - const responsePromise = client.documents.generateTemplate.create({ - projectId: 'projectId', - templateId: 'templateId', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.documents.generateTemplate.create({ - projectId: 'projectId', - templateId: 'templateId', - filename: 'filename', - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/documents/generate.test.ts b/tests/api-resources/documents/generate.test.ts deleted file mode 100644 index 6db57d6..0000000 --- a/tests/api-resources/documents/generate.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource generate', () => { - test('create: only required params', async () => { - const responsePromise = client.documents.generate.create({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.documents.generate.create({ - projectId: 'projectId', - design: { foo: 'bar' }, - filename: 'filename', - html: 'html', - mergeTags: { foo: 'string' }, - url: 'https://example.com', - }); - }); -}); diff --git a/tests/api-resources/emails/emails.test.ts b/tests/api-resources/emails/emails.test.ts deleted file mode 100644 index c3e8e96..0000000 --- a/tests/api-resources/emails/emails.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource emails', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.emails.retrieve('id', { projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.emails.retrieve('id', { projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/emails/render.test.ts b/tests/api-resources/emails/render.test.ts deleted file mode 100644 index 7dcbd01..0000000 --- a/tests/api-resources/emails/render.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource render', () => { - test('create: only required params', async () => { - const responsePromise = client.emails.render.create({ - projectId: 'projectId', - design: { foo: 'bar' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.emails.render.create({ - projectId: 'projectId', - design: { foo: 'bar' }, - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/emails/send-template.test.ts b/tests/api-resources/emails/send-template.test.ts deleted file mode 100644 index 98e3b2b..0000000 --- a/tests/api-resources/emails/send-template.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource sendTemplate', () => { - test('create: only required params', async () => { - const responsePromise = client.emails.sendTemplate.create({ - projectId: 'projectId', - templateId: 'templateId', - to: 'dev@stainless.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.emails.sendTemplate.create({ - projectId: 'projectId', - templateId: 'templateId', - to: 'dev@stainless.com', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); - }); -}); diff --git a/tests/api-resources/emails/send.test.ts b/tests/api-resources/emails/send.test.ts deleted file mode 100644 index 39492f0..0000000 --- a/tests/api-resources/emails/send.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource send', () => { - test('create: only required params', async () => { - const responsePromise = client.emails.send.create({ projectId: 'projectId', to: 'dev@stainless.com' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.emails.send.create({ - projectId: 'projectId', - to: 'dev@stainless.com', - design: { foo: 'bar' }, - html: 'html', - mergeTags: { foo: 'string' }, - subject: 'subject', - }); - }); -}); diff --git a/tests/api-resources/export/html.test.ts b/tests/api-resources/export/html.test.ts deleted file mode 100644 index 9f59af0..0000000 --- a/tests/api-resources/export/html.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource html', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.export.html.retrieve({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.export.html.retrieve({ projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/export/image.test.ts b/tests/api-resources/export/image.test.ts deleted file mode 100644 index 598d5cb..0000000 --- a/tests/api-resources/export/image.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource image', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.export.image.retrieve({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.export.image.retrieve({ projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/export/zip.test.ts b/tests/api-resources/export/zip.test.ts deleted file mode 100644 index 63a356c..0000000 --- a/tests/api-resources/export/zip.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource zip', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.export.zip.retrieve({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.export.zip.retrieve({ projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/pages/render.test.ts b/tests/api-resources/pages/render.test.ts deleted file mode 100644 index 0e8cc65..0000000 --- a/tests/api-resources/pages/render.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource render', () => { - test('create: only required params', async () => { - const responsePromise = client.pages.render.create({ - projectId: 'projectId', - design: { foo: 'bar' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.pages.render.create({ - projectId: 'projectId', - design: { foo: 'bar' }, - mergeTags: { foo: 'string' }, - }); - }); -}); diff --git a/tests/api-resources/project/current.test.ts b/tests/api-resources/project/current.test.ts deleted file mode 100644 index 8e2851d..0000000 --- a/tests/api-resources/project/current.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource current', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.project.current.retrieve({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.project.current.retrieve({ projectId: 'projectId' }); - }); -}); diff --git a/tests/api-resources/project/domains.test.ts b/tests/api-resources/project/domains.test.ts deleted file mode 100644 index 57a618a..0000000 --- a/tests/api-resources/project/domains.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Unlayer from '@unlayer/sdk'; - -const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource domains', () => { - test('create: only required params', async () => { - const responsePromise = client.project.domains.create({ projectId: 'projectId', domain: 'domain' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: required and optional params', async () => { - const response = await client.project.domains.create({ projectId: 'projectId', domain: 'domain' }); - }); - - test('retrieve', async () => { - const responsePromise = client.project.domains.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update', async () => { - const responsePromise = client.project.domains.update('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.domains.update('id', { domain: 'domain' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); - }); - - test('list: only required params', async () => { - const responsePromise = client.project.domains.list({ projectId: 'projectId' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('list: required and optional params', async () => { - const response = await client.project.domains.list({ projectId: 'projectId' }); - }); - - test('delete', async () => { - const responsePromise = client.project.domains.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/export/pdf.test.ts b/tests/api-resources/project/project.test.ts similarity index 79% rename from tests/api-resources/export/pdf.test.ts rename to tests/api-resources/project/project.test.ts index 8bd3fc0..5d4c33c 100644 --- a/tests/api-resources/export/pdf.test.ts +++ b/tests/api-resources/project/project.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource pdf', () => { +describe('resource project', () => { test('retrieve: only required params', async () => { - const responsePromise = client.export.pdf.retrieve({ projectId: 'projectId' }); + const responsePromise = client.project.retrieve({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,6 +20,6 @@ describe('resource pdf', () => { }); test('retrieve: required and optional params', async () => { - const response = await client.export.pdf.retrieve({ projectId: 'projectId' }); + const response = await client.project.retrieve({ projectId: 'projectId' }); }); }); diff --git a/tests/api-resources/project/templates.test.ts b/tests/api-resources/project/templates.test.ts index 4a487a8..7ce1b35 100644 --- a/tests/api-resources/project/templates.test.ts +++ b/tests/api-resources/project/templates.test.ts @@ -8,8 +8,8 @@ const client = new Unlayer({ }); describe('resource templates', () => { - test('create: only required params', async () => { - const responsePromise = client.project.templates.create({ projectId: 'projectId', name: 'name' }); + test('retrieve: only required params', async () => { + const responsePromise = client.project.templates.retrieve('id', { projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,49 +19,8 @@ describe('resource templates', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('create: required and optional params', async () => { - const response = await client.project.templates.create({ - projectId: 'projectId', - name: 'name', - displayMode: 'email', - }); - }); - - test('retrieve', async () => { - const responsePromise = client.project.templates.retrieve('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update', async () => { - const responsePromise = client.project.templates.update('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.templates.update( - 'id', - { - body: 'body', - name: 'name', - subject: 'subject', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Unlayer.NotFoundError); + test('retrieve: required and optional params', async () => { + const response = await client.project.templates.retrieve('id', { projectId: 'projectId' }); }); test('list: only required params', async () => { @@ -84,15 +43,4 @@ describe('resource templates', () => { name: 'name', }); }); - - test('delete', async () => { - const responsePromise = client.project.templates.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); }); diff --git a/tests/api-resources/project/workspaces.test.ts b/tests/api-resources/workspaces.test.ts similarity index 88% rename from tests/api-resources/project/workspaces.test.ts rename to tests/api-resources/workspaces.test.ts index fb9c997..bce3b99 100644 --- a/tests/api-resources/project/workspaces.test.ts +++ b/tests/api-resources/workspaces.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource workspaces', () => { test('retrieve', async () => { - const responsePromise = client.project.workspaces.retrieve('workspaceId'); + const responsePromise = client.workspaces.retrieve('workspaceId'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource workspaces', () => { }); test('list', async () => { - const responsePromise = client.project.workspaces.list(); + const responsePromise = client.workspaces.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; From 492134c3296faaa53a82d2c57b600cdc743ea5a2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:40:14 +0000 Subject: [PATCH 051/118] feat(api): api update --- .stats.yml | 6 +- README.md | 4 +- api.md | 14 +-- src/client.ts | 21 ++++- src/resources/index.ts | 10 ++- src/resources/project.ts | 65 +++++++++++++- src/resources/project/index.ts | 11 --- src/resources/project/project.ts | 88 ------------------- src/resources/{project => }/templates.ts | 23 +++-- .../{project => }/project.test.ts | 0 .../{project => }/templates.test.ts | 8 +- 11 files changed, 119 insertions(+), 131 deletions(-) delete mode 100644 src/resources/project/index.ts delete mode 100644 src/resources/project/project.ts rename src/resources/{project => }/templates.ts (76%) rename tests/api-resources/{project => }/project.test.ts (100%) rename tests/api-resources/{project => }/templates.test.ts (80%) diff --git a/.stats.yml b/.stats.yml index 43eb3f0..c827f62 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-579dff50df9d2d3be275dc58817917d2efec68100883d139ae7d62908a24e5d6.yml -openapi_spec_hash: 8583074e5ea7cc31410a42c2c4550d7c -config_hash: 3c023f8805c0765c987ddcee566aabef +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml +openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed +config_hash: ea554d62bfbb5e8ea43ebf0a274dec31 diff --git a/README.md b/README.md index 6696fa1..7a0a244 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ You can use the `for await … of` syntax to iterate through items across all pa async function fetchAllTemplateListResponses(params) { const allTemplateListResponses = []; // Automatically fetches more pages as needed. - for await (const templateListResponse of client.project.templates.list({ + for await (const templateListResponse of client.templates.list({ projectId: 'your-project-id', limit: 10, })) { @@ -152,7 +152,7 @@ async function fetchAllTemplateListResponses(params) { Alternatively, you can request a single page at a time: ```ts -let page = await client.project.templates.list({ projectId: 'your-project-id', limit: 10 }); +let page = await client.templates.list({ projectId: 'your-project-id', limit: 10 }); for (const templateListResponse of page.data) { console.log(templateListResponse); } diff --git a/api.md b/api.md index 102ed43..4399859 100644 --- a/api.md +++ b/api.md @@ -24,23 +24,23 @@ Methods: Types: -- ProjectRetrieveResponse +- ProjectRetrieveResponse Methods: -- client.project.retrieve({ ...params }) -> ProjectRetrieveResponse +- client.project.retrieve({ ...params }) -> ProjectRetrieveResponse -## Templates +# Templates Types: -- TemplateRetrieveResponse -- TemplateListResponse +- TemplateRetrieveResponse +- TemplateListResponse Methods: -- client.project.templates.retrieve(id, { ...params }) -> TemplateRetrieveResponse -- client.project.templates.list({ ...params }) -> TemplateListResponsesCursorPage +- client.templates.retrieve(id, { ...params }) -> TemplateRetrieveResponse +- client.templates.list({ ...params }) -> TemplateListResponsesCursorPage # Workspaces diff --git a/src/client.ts b/src/client.ts index 052468f..01d3d7b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,9 +18,17 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { Project, ProjectRetrieveParams, ProjectRetrieveResponse } from './resources/project'; +import { + TemplateListParams, + TemplateListResponse, + TemplateListResponsesCursorPage, + TemplateRetrieveParams, + TemplateRetrieveResponse, + Templates, +} from './resources/templates'; import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; import { Convert } from './resources/convert/convert'; -import { Project, ProjectRetrieveParams, ProjectRetrieveResponse } from './resources/project/project'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -779,11 +787,13 @@ export class Unlayer { convert: API.Convert = new API.Convert(this); project: API.Project = new API.Project(this); + templates: API.Templates = new API.Templates(this); workspaces: API.Workspaces = new API.Workspaces(this); } Unlayer.Convert = Convert; Unlayer.Project = Project; +Unlayer.Templates = Templates; Unlayer.Workspaces = Workspaces; export declare namespace Unlayer { @@ -800,6 +810,15 @@ export declare namespace Unlayer { type ProjectRetrieveParams as ProjectRetrieveParams, }; + export { + Templates as Templates, + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, + type TemplateRetrieveParams as TemplateRetrieveParams, + type TemplateListParams as TemplateListParams, + }; + export { Workspaces as Workspaces, type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index c51af00..bc83167 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,5 +1,13 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Convert } from './convert/convert'; -export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project/project'; +export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project'; +export { + Templates, + type TemplateRetrieveResponse, + type TemplateListResponse, + type TemplateRetrieveParams, + type TemplateListParams, + type TemplateListResponsesCursorPage, +} from './templates'; export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/project.ts b/src/resources/project.ts index 60fc38d..a067792 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -1,3 +1,66 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './project/index'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class Project extends APIResource { + /** + * Get project details for the specified project. + */ + retrieve(query: ProjectRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.get('/v3/project', { query, ...options }); + } +} + +export interface ProjectRetrieveResponse { + data?: ProjectRetrieveResponse.Data; +} + +export namespace ProjectRetrieveResponse { + export interface Data { + /** + * The project ID. + */ + id?: number; + + /** + * When the project was created. + */ + createdAt?: string; + + /** + * The project name. + */ + name?: string; + + /** + * The project status. + */ + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +export interface ProjectRetrieveParams { + /** + * The project ID + */ + projectId: string; +} + +export declare namespace Project { + export { + type ProjectRetrieveResponse as ProjectRetrieveResponse, + type ProjectRetrieveParams as ProjectRetrieveParams, + }; +} diff --git a/src/resources/project/index.ts b/src/resources/project/index.ts deleted file mode 100644 index 0cb65dc..0000000 --- a/src/resources/project/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project'; -export { - Templates, - type TemplateRetrieveResponse, - type TemplateListResponse, - type TemplateRetrieveParams, - type TemplateListParams, - type TemplateListResponsesCursorPage, -} from './templates'; diff --git a/src/resources/project/project.ts b/src/resources/project/project.ts deleted file mode 100644 index 5ceae62..0000000 --- a/src/resources/project/project.ts +++ /dev/null @@ -1,88 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as TemplatesAPI from './templates'; -import { - TemplateListParams, - TemplateListResponse, - TemplateListResponsesCursorPage, - TemplateRetrieveParams, - TemplateRetrieveResponse, - Templates, -} from './templates'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Project extends APIResource { - templates: TemplatesAPI.Templates = new TemplatesAPI.Templates(this._client); - - /** - * Get project details for the specified project. - */ - retrieve(query: ProjectRetrieveParams, options?: RequestOptions): APIPromise { - return this._client.get('/v3/project', { query, ...options }); - } -} - -export interface ProjectRetrieveResponse { - data?: ProjectRetrieveResponse.Data; -} - -export namespace ProjectRetrieveResponse { - export interface Data { - /** - * The project ID. - */ - id?: number; - - /** - * When the project was created. - */ - createdAt?: string; - - /** - * The project name. - */ - name?: string; - - /** - * The project status. - */ - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export interface ProjectRetrieveParams { - /** - * The project ID - */ - projectId: string; -} - -Project.Templates = Templates; - -export declare namespace Project { - export { - type ProjectRetrieveResponse as ProjectRetrieveResponse, - type ProjectRetrieveParams as ProjectRetrieveParams, - }; - - export { - Templates as Templates, - type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateListResponse as TemplateListResponse, - type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, - type TemplateRetrieveParams as TemplateRetrieveParams, - type TemplateListParams as TemplateListParams, - }; -} diff --git a/src/resources/project/templates.ts b/src/resources/templates.ts similarity index 76% rename from src/resources/project/templates.ts rename to src/resources/templates.ts index 3438f71..7f99640 100644 --- a/src/resources/project/templates.ts +++ b/src/resources/templates.ts @@ -1,35 +1,32 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; export class Templates extends APIResource { /** - * Get project template by ID. + * Get template by ID. */ retrieve( id: string, query: TemplateRetrieveParams, options?: RequestOptions, ): APIPromise { - return this._client.get(path`/v3/project/templates/${id}`, { query, ...options }); + return this._client.get(path`/v3/templates/${id}`, { query, ...options }); } /** - * List project templates with cursor-based pagination. Returns templates in - * descending order by update time. + * List templates with cursor-based pagination. Returns templates in descending + * order by update time. */ list( query: TemplateListParams, options?: RequestOptions, ): PagePromise { - return this._client.getAPIList('/v3/project/templates', CursorPage, { - query, - ...options, - }); + return this._client.getAPIList('/v3/templates', CursorPage, { query, ...options }); } } diff --git a/tests/api-resources/project/project.test.ts b/tests/api-resources/project.test.ts similarity index 100% rename from tests/api-resources/project/project.test.ts rename to tests/api-resources/project.test.ts diff --git a/tests/api-resources/project/templates.test.ts b/tests/api-resources/templates.test.ts similarity index 80% rename from tests/api-resources/project/templates.test.ts rename to tests/api-resources/templates.test.ts index 7ce1b35..e67da40 100644 --- a/tests/api-resources/project/templates.test.ts +++ b/tests/api-resources/templates.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource templates', () => { test('retrieve: only required params', async () => { - const responsePromise = client.project.templates.retrieve('id', { projectId: 'projectId' }); + const responsePromise = client.templates.retrieve('id', { projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,11 +20,11 @@ describe('resource templates', () => { }); test('retrieve: required and optional params', async () => { - const response = await client.project.templates.retrieve('id', { projectId: 'projectId' }); + const response = await client.templates.retrieve('id', { projectId: 'projectId' }); }); test('list: only required params', async () => { - const responsePromise = client.project.templates.list({ projectId: 'projectId' }); + const responsePromise = client.templates.list({ projectId: 'projectId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -35,7 +35,7 @@ describe('resource templates', () => { }); test('list: required and optional params', async () => { - const response = await client.project.templates.list({ + const response = await client.templates.list({ projectId: 'projectId', cursor: 'cursor', displayMode: 'email', From 11c8cbf86a4c870040e044d1b75f182872cbc123 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:56:57 +0000 Subject: [PATCH 052/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index c827f62..b0c7f3b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed -config_hash: ea554d62bfbb5e8ea43ebf0a274dec31 +config_hash: 00a7b0dff20113623ba749fe28286413 From 5dc77cb085fa15701b54c9ee7f35a75468390125 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:57:21 +0000 Subject: [PATCH 053/118] chore: update SDK settings --- .github/workflows/release-doctor.yml | 20 +++++++++ .release-please-manifest.json | 3 ++ .stats.yml | 2 +- CONTRIBUTING.md | 4 +- README.md | 4 +- bin/check-release-environment | 18 ++++++++ package.json | 2 +- release-please-config.json | 64 ++++++++++++++++++++++++++++ src/version.ts | 2 +- 9 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..93671f0 --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,20 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'unlayer/unlayer-typescript' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v6 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..b985ff6 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} diff --git a/.stats.yml b/.stats.yml index b0c7f3b..3a44165 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed -config_hash: 00a7b0dff20113623ba749fe28286413 +config_hash: 344aa63165862b95d788ad377dd902e3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d4637a..2fc3541 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,14 +42,14 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ npm install git+ssh://git@github.com:stainless-sdks/unlayer-typescript.git +$ npm install git+ssh://git@github.com:unlayer/unlayer-typescript.git ``` Alternatively, to link a local copy of the repo: ```sh # Clone -$ git clone https://www.github.com/stainless-sdks/unlayer-typescript +$ git clone https://www.github.com/unlayer/unlayer-typescript $ cd unlayer-typescript # With yarn diff --git a/README.md b/README.md index 7a0a244..300950f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:stainless-sdks/unlayer-typescript.git +npm install git+ssh://git@github.com:unlayer/unlayer-typescript.git ``` > [!NOTE] @@ -376,7 +376,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/unlayer-typescript/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/unlayer/unlayer-typescript/issues) with questions, bugs, or suggestions. ## Requirements diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..6b43775 --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +errors=() + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" + diff --git a/package.json b/package.json index cea38cc..693d311 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", - "repository": "github:stainless-sdks/unlayer-typescript", + "repository": "github:unlayer/unlayer-typescript", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "files": [ diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..1ebd0bd --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,64 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "node", + "extra-files": ["src/version.ts", "README.md"] +} diff --git a/src/version.ts b/src/version.ts index ecebcdd..d74dce8 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1'; +export const VERSION = '0.0.1'; // x-release-please-version From c1b5fd25fd939ac9a96952015521b52fbc5dce9f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:57:47 +0000 Subject: [PATCH 054/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 3a44165..c325690 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed -config_hash: 344aa63165862b95d788ad377dd902e3 +config_hash: 68f088239d13d9983e4913c6b8396c0d From 27920796a081027b164725c410922950710abec1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:58:08 +0000 Subject: [PATCH 055/118] chore: update SDK settings --- .github/workflows/publish-npm.yml | 32 ++++++++++++++++++++++++++++ .github/workflows/release-doctor.yml | 2 ++ .stats.yml | 2 +- CONTRIBUTING.md | 14 ++++++++++++ README.md | 5 +---- bin/check-release-environment | 4 ++++ 6 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/publish-npm.yml diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 0000000..8d3b32c --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,32 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to NPM in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/unlayer/unlayer-typescript/actions/workflows/publish-npm.yml +name: Publish NPM +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + run: | + yarn install + + - name: Publish to NPM + run: | + bash ./bin/publish-npm + env: + NPM_TOKEN: ${{ secrets.UNLAYER_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 93671f0..71339c4 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,4 +17,6 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment + env: + NPM_TOKEN: ${{ secrets.UNLAYER_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.stats.yml b/.stats.yml index c325690..5702403 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed -config_hash: 68f088239d13d9983e4913c6b8396c0d +config_hash: 87d560e6d481bc04dc9310719a5eb946 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2fc3541..6a088a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -91,3 +91,17 @@ To format and fix all lint issues automatically: ```sh $ yarn fix ``` + +## Publishing and releases + +Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If +the changes aren't made through the automated pipeline, you may want to make releases manually. + +### Publish with a GitHub workflow + +You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/unlayer/unlayer-typescript/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. + +### Publish manually + +If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on +the environment. diff --git a/README.md b/README.md index 300950f..f5d1b35 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,9 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:unlayer/unlayer-typescript.git +npm install @unlayer/sdk ``` -> [!NOTE] -> Once this package is [published to npm](https://www.stainless.com/docs/guides/publish), this will become: `npm install @unlayer/sdk` - ## Usage The full API of this library can be found in [api.md](api.md). diff --git a/bin/check-release-environment b/bin/check-release-environment index 6b43775..e4b6d58 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ errors=() +if [ -z "${NPM_TOKEN}" ]; then + errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then From b0236dc6ee0d30543d436ec936ec7902c961b20a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 18:57:34 +0000 Subject: [PATCH 056/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5702403..5a7e305 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-e77bc881d5cb6c68be6f3d3861ed021b99f6cde45ee28d3511abe284d888262e.yml -openapi_spec_hash: 7e7fae1b919c5d337e8b22be2a24d3ed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-05f06124acf955282470ca7d863e8d10c5dd36cbde746d154482e9972277cd03.yml +openapi_spec_hash: 21532f2d9416a6e55bf9107df0948cd8 config_hash: 87d560e6d481bc04dc9310719a5eb946 From 2477850f49db421f983e1346182be8c398591619 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 03:45:49 +0000 Subject: [PATCH 057/118] chore(internal/client): fix form-urlencoded requests --- src/client.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/client.ts b/src/client.ts index 01d3d7b..b721084 100644 --- a/src/client.ts +++ b/src/client.ts @@ -761,6 +761,14 @@ export class Unlayer { (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')) ) { return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable) }; + } else if ( + typeof body === 'object' && + headers.values.get('content-type') === 'application/x-www-form-urlencoded' + ) { + return { + bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, + body: this.stringifyQuery(body as Record), + }; } else { return this.#encoder({ body, headers }); } From 0c8b14cd70cb5c175e6afa858225b50a069f0723 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 04:06:17 +0000 Subject: [PATCH 058/118] chore: update mock server docs --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a088a4..dad7a7c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ $ pnpm link -—global @unlayer/sdk Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```sh -$ npx prism mock path/to/your/openapi.yml +$ ./scripts/mock ``` ```sh From 59d365ed299aade026bcf90ae61ca80bea87a1d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 13:56:48 +0000 Subject: [PATCH 059/118] feat(api): api update --- .stats.yml | 6 +- README.md | 10 +- src/client.ts | 109 ++++++++++-------- src/resources/project.ts | 9 +- src/resources/templates.ts | 18 +-- src/resources/workspaces.ts | 6 +- .../convert/full-to-simple.test.ts | 2 +- .../convert/simple-to-full.test.ts | 2 +- tests/api-resources/project.test.ts | 13 ++- tests/api-resources/templates.test.ts | 39 ++++--- tests/api-resources/workspaces.test.ts | 2 +- tests/index.test.ts | 109 +++++++----------- 12 files changed, 168 insertions(+), 157 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5a7e305..2fb1d6b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-05f06124acf955282470ca7d863e8d10c5dd36cbde746d154482e9972277cd03.yml -openapi_spec_hash: 21532f2d9416a6e55bf9107df0948cd8 -config_hash: 87d560e6d481bc04dc9310719a5eb946 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-14707e371ca64ee082f425e10f8bd4b7d9e2eeb28d6e69daad66902abb1b8b6b.yml +openapi_spec_hash: 8198d0442f4736109bf6c49a5a8697ab +config_hash: 144077318a24cfbe9ce6da795a628a80 diff --git a/README.md b/README.md index f5d1b35..b00af96 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,7 @@ The full API of this library can be found in [api.md](api.md). import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: process.env['UNLAYER_ACCESS_TOKEN'], // This is the default and can be omitted - environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); const project = await client.project.retrieve({ projectId: 'your-project-id' }); @@ -41,8 +40,7 @@ This library includes TypeScript definitions for all request params and response import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: process.env['UNLAYER_ACCESS_TOKEN'], // This is the default and can be omitted - environment: 'stage', // or 'production' | 'qa' | 'dev'; defaults to 'production' + apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); const params: Unlayer.ProjectRetrieveParams = { projectId: 'your-project-id' }; @@ -137,8 +135,8 @@ async function fetchAllTemplateListResponses(params) { const allTemplateListResponses = []; // Automatically fetches more pages as needed. for await (const templateListResponse of client.templates.list({ - projectId: 'your-project-id', limit: 10, + projectId: 'your-project-id', })) { allTemplateListResponses.push(templateListResponse); } @@ -149,7 +147,7 @@ async function fetchAllTemplateListResponses(params) { Alternatively, you can request a single page at a time: ```ts -let page = await client.templates.list({ projectId: 'your-project-id', limit: 10 }); +let page = await client.templates.list({ limit: 10, projectId: 'your-project-id' }); for (const templateListResponse of page.data) { console.log(templateListResponse); } diff --git a/src/client.ts b/src/client.ts index b721084..ed5b220 100644 --- a/src/client.ts +++ b/src/client.ts @@ -42,30 +42,21 @@ import { } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; -const environments = { - production: 'https://api.unlayer.com', - stage: 'https://api.stage.unlayer.com', - qa: 'https://api.qa.unlayer.com', - dev: 'https://api.dev.unlayer.com', -}; -type Environment = keyof typeof environments; - export interface ClientOptions { /** - * Defaults to process.env['UNLAYER_ACCESS_TOKEN']. + * Defaults to process.env['UNLAYER_API_KEY']. */ - accessToken?: string | undefined; + apiKey?: string | null | undefined; /** - * Specifies the environment to use for the API. - * - * Each environment maps to a different base URL: - * - `production` corresponds to `https://api.unlayer.com` - * - `stage` corresponds to `https://api.stage.unlayer.com` - * - `qa` corresponds to `https://api.qa.unlayer.com` - * - `dev` corresponds to `https://api.dev.unlayer.com` + * Defaults to process.env['UNLAYER_PERSONAL_ACCESS_TOKEN']. + */ + personalAccessToken?: string | null | undefined; + + /** + * Defaults to process.env['UNLAYER_PROJECT_ID']. */ - environment?: Environment | undefined; + projectID?: string | null | undefined; /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" @@ -140,7 +131,9 @@ export interface ClientOptions { * API Client for interfacing with the Unlayer API. */ export class Unlayer { - accessToken: string; + apiKey: string | null; + personalAccessToken: string | null; + projectID: string | null; baseURL: string; maxRetries: number; @@ -157,8 +150,9 @@ export class Unlayer { /** * API Client for interfacing with the Unlayer API. * - * @param {string | undefined} [opts.accessToken=process.env['UNLAYER_ACCESS_TOKEN'] ?? undefined] - * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. + * @param {string | null | undefined} [opts.apiKey=process.env['UNLAYER_API_KEY'] ?? null] + * @param {string | null | undefined} [opts.personalAccessToken=process.env['UNLAYER_PERSONAL_ACCESS_TOKEN'] ?? null] + * @param {string | null | undefined} [opts.projectID=process.env['UNLAYER_PROJECT_ID'] ?? null] * @param {string} [opts.baseURL=process.env['UNLAYER_BASE_URL'] ?? https://api.unlayer.com] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -169,29 +163,20 @@ export class Unlayer { */ constructor({ baseURL = readEnv('UNLAYER_BASE_URL'), - accessToken = readEnv('UNLAYER_ACCESS_TOKEN'), + apiKey = readEnv('UNLAYER_API_KEY') ?? null, + personalAccessToken = readEnv('UNLAYER_PERSONAL_ACCESS_TOKEN') ?? null, + projectID = readEnv('UNLAYER_PROJECT_ID') ?? null, ...opts }: ClientOptions = {}) { - if (accessToken === undefined) { - throw new Errors.UnlayerError( - "The UNLAYER_ACCESS_TOKEN environment variable is missing or empty; either provide it, or instantiate the Unlayer client with an accessToken option, like new Unlayer({ accessToken: 'My Access Token' }).", - ); - } - const options: ClientOptions = { - accessToken, + apiKey, + personalAccessToken, + projectID, ...opts, - baseURL, - environment: opts.environment ?? 'production', + baseURL: baseURL || `https://api.unlayer.com`, }; - if (baseURL && opts.environment) { - throw new Errors.UnlayerError( - 'Ambiguous URL; The `baseURL` option (or UNLAYER_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null', - ); - } - - this.baseURL = options.baseURL || environments[options.environment || 'production']; + this.baseURL = options.baseURL!; this.timeout = options.timeout ?? Unlayer.DEFAULT_TIMEOUT /* 1 minute */; this.logger = options.logger ?? console; const defaultLogLevel = 'warn'; @@ -208,7 +193,9 @@ export class Unlayer { this._options = options; - this.accessToken = accessToken; + this.apiKey = apiKey; + this.personalAccessToken = personalAccessToken; + this.projectID = projectID; } /** @@ -217,15 +204,16 @@ export class Unlayer { withOptions(options: Partial): this { const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({ ...this._options, - environment: options.environment ? options.environment : undefined, - baseURL: options.environment ? undefined : this.baseURL, + baseURL: this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, fetch: this.fetch, fetchOptions: this.fetchOptions, - accessToken: this.accessToken, + apiKey: this.apiKey, + personalAccessToken: this.personalAccessToken, + projectID: this.projectID, ...options, }); return client; @@ -235,7 +223,7 @@ export class Unlayer { * Check whether the base URL is set to its default. */ #baseURLOverridden(): boolean { - return this.baseURL !== environments[this._options.environment || 'production']; + return this.baseURL !== 'https://api.unlayer.com'; } protected defaultQuery(): Record | undefined { @@ -243,11 +231,41 @@ export class Unlayer { } protected validateHeaders({ values, nulls }: NullableHeaders) { - return; + if (this.apiKey && values.get('authorization')) { + return; + } + if (nulls.has('authorization')) { + return; + } + + if (this.personalAccessToken && values.get('authorization')) { + return; + } + if (nulls.has('authorization')) { + return; + } + + throw new Error( + 'Could not resolve authentication method. Expected either apiKey or personalAccessToken to be set. Or for one of the "Authorization" or "Authorization" headers to be explicitly omitted', + ); } protected async authHeaders(opts: FinalRequestOptions): Promise { - return buildHeaders([{ Authorization: `Bearer ${this.accessToken}` }]); + return buildHeaders([await this.apiKeyAuth(opts), await this.personalAccessTokenAuth(opts)]); + } + + protected async apiKeyAuth(opts: FinalRequestOptions): Promise { + if (this.apiKey == null) { + return undefined; + } + return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); + } + + protected async personalAccessTokenAuth(opts: FinalRequestOptions): Promise { + if (this.personalAccessToken == null) { + return undefined; + } + return buildHeaders([{ Authorization: `Bearer ${this.personalAccessToken}` }]); } /** @@ -711,6 +729,7 @@ export class Unlayer { 'X-Stainless-Retry-Count': String(retryCount), ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), ...getPlatformHeaders(), + 'X-Project-ID': this.projectID, }, await this.authHeaders(options), this._options.defaultHeaders, diff --git a/src/resources/project.ts b/src/resources/project.ts index a067792..1ee648e 100644 --- a/src/resources/project.ts +++ b/src/resources/project.ts @@ -8,7 +8,10 @@ export class Project extends APIResource { /** * Get project details for the specified project. */ - retrieve(query: ProjectRetrieveParams, options?: RequestOptions): APIPromise { + retrieve( + query: ProjectRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { return this._client.get('/v3/project', { query, ...options }); } } @@ -53,9 +56,9 @@ export namespace ProjectRetrieveResponse { export interface ProjectRetrieveParams { /** - * The project ID + * The project ID (required for PAT auth, auto-resolved for API key auth) */ - projectId: string; + projectId?: string; } export declare namespace Project { diff --git a/src/resources/templates.ts b/src/resources/templates.ts index 7f99640..38eef4b 100644 --- a/src/resources/templates.ts +++ b/src/resources/templates.ts @@ -12,7 +12,7 @@ export class Templates extends APIResource { */ retrieve( id: string, - query: TemplateRetrieveParams, + query: TemplateRetrieveParams | null | undefined = {}, options?: RequestOptions, ): APIPromise { return this._client.get(path`/v3/templates/${id}`, { query, ...options }); @@ -23,7 +23,7 @@ export class Templates extends APIResource { * order by update time. */ list( - query: TemplateListParams, + query: TemplateListParams | null | undefined = {}, options?: RequestOptions, ): PagePromise { return this._client.getAPIList('/v3/templates', CursorPage, { query, ...options }); @@ -77,17 +77,12 @@ export interface TemplateListResponse { export interface TemplateRetrieveParams { /** - * The project ID + * The project ID (required for PAT auth, auto-resolved for API key auth) */ - projectId: string; + projectId?: string; } export interface TemplateListParams extends CursorPageParams { - /** - * The project ID to list templates for - */ - projectId: string; - /** * Filter by template type */ @@ -97,6 +92,11 @@ export interface TemplateListParams extends CursorPageParams { * Filter by name (case-insensitive search) */ name?: string; + + /** + * The project ID to list templates for + */ + projectId?: string; } export declare namespace Templates { diff --git a/src/resources/workspaces.ts b/src/resources/workspaces.ts index a81dc2f..e51624e 100644 --- a/src/resources/workspaces.ts +++ b/src/resources/workspaces.ts @@ -7,14 +7,16 @@ import { path } from '../internal/utils/path'; export class Workspaces extends APIResource { /** - * Get a specific workspace by ID with its projects. + * Get a specific workspace by ID with its projects. Requires a Personal Access + * Token (PAT). */ retrieve(workspaceID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v3/workspaces/${workspaceID}`, options); } /** - * Get all workspaces accessible by the current token. + * Get all workspaces accessible by the current token. Requires a Personal Access + * Token (PAT). */ list(options?: RequestOptions): APIPromise { return this._client.get('/v3/workspaces', options); diff --git a/tests/api-resources/convert/full-to-simple.test.ts b/tests/api-resources/convert/full-to-simple.test.ts index f33082d..831b256 100644 --- a/tests/api-resources/convert/full-to-simple.test.ts +++ b/tests/api-resources/convert/full-to-simple.test.ts @@ -3,7 +3,7 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); diff --git a/tests/api-resources/convert/simple-to-full.test.ts b/tests/api-resources/convert/simple-to-full.test.ts index cef0634..a5f33bd 100644 --- a/tests/api-resources/convert/simple-to-full.test.ts +++ b/tests/api-resources/convert/simple-to-full.test.ts @@ -3,7 +3,7 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/project.test.ts index 5d4c33c..6365f13 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/project.test.ts @@ -3,13 +3,13 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource project', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.project.retrieve({ projectId: 'projectId' }); + test('retrieve', async () => { + const responsePromise = client.project.retrieve(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,7 +19,10 @@ describe('resource project', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('retrieve: required and optional params', async () => { - const response = await client.project.retrieve({ projectId: 'projectId' }); + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.project.retrieve({ projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); }); }); diff --git a/tests/api-resources/templates.test.ts b/tests/api-resources/templates.test.ts index e67da40..d40fd99 100644 --- a/tests/api-resources/templates.test.ts +++ b/tests/api-resources/templates.test.ts @@ -3,13 +3,13 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); describe('resource templates', () => { - test('retrieve: only required params', async () => { - const responsePromise = client.templates.retrieve('id', { projectId: 'projectId' }); + test('retrieve', async () => { + const responsePromise = client.templates.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,12 +19,15 @@ describe('resource templates', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('retrieve: required and optional params', async () => { - const response = await client.templates.retrieve('id', { projectId: 'projectId' }); + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.templates.retrieve('id', { projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); }); - test('list: only required params', async () => { - const responsePromise = client.templates.list({ projectId: 'projectId' }); + test('list', async () => { + const responsePromise = client.templates.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -34,13 +37,19 @@ describe('resource templates', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('list: required and optional params', async () => { - const response = await client.templates.list({ - projectId: 'projectId', - cursor: 'cursor', - displayMode: 'email', - limit: 1, - name: 'name', - }); + test('list: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.templates.list( + { + cursor: 'cursor', + displayMode: 'email', + limit: 1, + name: 'name', + projectId: 'projectId', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); }); }); diff --git a/tests/api-resources/workspaces.test.ts b/tests/api-resources/workspaces.test.ts index bce3b99..ad10668 100644 --- a/tests/api-resources/workspaces.test.ts +++ b/tests/api-resources/workspaces.test.ts @@ -3,7 +3,7 @@ import Unlayer from '@unlayer/sdk'; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); diff --git a/tests/index.test.ts b/tests/index.test.ts index 553cc61..da4aec7 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -23,7 +23,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-My-Default-Header': '2' }, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); test('they are used in the request', async () => { @@ -90,7 +90,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'debug', - accessToken: 'My Access Token', + apiKey: 'My API Key', }); await forceAPIResponseForClient(client); @@ -98,7 +98,7 @@ describe('instantiate client', () => { }); test('default logLevel is warn', async () => { - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.logLevel).toBe('warn'); }); @@ -114,7 +114,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'info', - accessToken: 'My Access Token', + apiKey: 'My API Key', }); await forceAPIResponseForClient(client); @@ -131,7 +131,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'debug'; - const client = new Unlayer({ logger: logger, accessToken: 'My Access Token' }); + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); expect(client.logLevel).toBe('debug'); await forceAPIResponseForClient(client); @@ -148,7 +148,7 @@ describe('instantiate client', () => { }; process.env['UNLAYER_LOG'] = 'not a log level'; - const client = new Unlayer({ logger: logger, accessToken: 'My Access Token' }); + const client = new Unlayer({ logger: logger, apiKey: 'My API Key' }); expect(client.logLevel).toBe('warn'); expect(warnMock).toHaveBeenCalledWith( 'process.env[\'UNLAYER_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', @@ -168,7 +168,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'off', - accessToken: 'My Access Token', + apiKey: 'My API Key', }); await forceAPIResponseForClient(client); @@ -188,7 +188,7 @@ describe('instantiate client', () => { const client = new Unlayer({ logger: logger, logLevel: 'debug', - accessToken: 'My Access Token', + apiKey: 'My API Key', }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); @@ -200,7 +200,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' }, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); @@ -209,7 +209,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo', hello: 'world' }, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); @@ -218,7 +218,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' }, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); @@ -227,7 +227,7 @@ describe('instantiate client', () => { test('custom fetch', async () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: (url) => { return Promise.resolve( new Response(JSON.stringify({ url, custom: true }), { @@ -245,7 +245,7 @@ describe('instantiate client', () => { // make sure the global fetch type is assignable to our Fetch type const client = new Unlayer({ baseURL: 'http://localhost:5000/', - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: defaultFetch, }); }); @@ -253,7 +253,7 @@ describe('instantiate client', () => { test('custom signal', async () => { const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: (...args) => { return new Promise((resolve, reject) => setTimeout( @@ -285,7 +285,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: testFetch, }); @@ -295,18 +295,12 @@ describe('instantiate client', () => { describe('baseUrl', () => { test('trailing slash', () => { - const client = new Unlayer({ - baseURL: 'http://localhost:5000/custom/path/', - accessToken: 'My Access Token', - }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); test('no trailing slash', () => { - const client = new Unlayer({ - baseURL: 'http://localhost:5000/custom/path', - accessToken: 'My Access Token', - }); + const client = new Unlayer({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); @@ -315,54 +309,37 @@ describe('instantiate client', () => { }); test('explicit option', () => { - const client = new Unlayer({ baseURL: 'https://example.com', accessToken: 'My Access Token' }); + const client = new Unlayer({ baseURL: 'https://example.com', apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://example.com'); }); test('env variable', () => { process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://example.com/from_env'); }); test('empty env variable', () => { process.env['UNLAYER_BASE_URL'] = ''; // empty - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('blank env variable', () => { process.env['UNLAYER_BASE_URL'] = ' '; // blank - const client = new Unlayer({ accessToken: 'My Access Token' }); - expect(client.baseURL).toEqual('https://api.unlayer.com'); - }); - - test('env variable with environment', () => { - process.env['UNLAYER_BASE_URL'] = 'https://example.com/from_env'; - - expect( - () => new Unlayer({ accessToken: 'My Access Token', environment: 'production' }), - ).toThrowErrorMatchingInlineSnapshot( - `"Ambiguous URL; The \`baseURL\` option (or UNLAYER_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, - ); - - const client = new Unlayer({ - accessToken: 'My Access Token', - baseURL: null, - environment: 'production', - }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.unlayer.com'); }); test('in request options', () => { - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/option/foo', ); }); test('in request options overridden by client options', () => { - const client = new Unlayer({ accessToken: 'My Access Token', baseURL: 'http://localhost:5000/client' }); + const client = new Unlayer({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/client/foo', ); @@ -370,7 +347,7 @@ describe('instantiate client', () => { test('in request options overridden by env variable', () => { process.env['UNLAYER_BASE_URL'] = 'http://localhost:5000/env'; - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( 'http://localhost:5000/env/foo', ); @@ -378,11 +355,11 @@ describe('instantiate client', () => { }); test('maxRetries option is correctly set', () => { - const client = new Unlayer({ maxRetries: 4, accessToken: 'My Access Token' }); + const client = new Unlayer({ maxRetries: 4, apiKey: 'My API Key' }); expect(client.maxRetries).toEqual(4); // default - const client2 = new Unlayer({ accessToken: 'My Access Token' }); + const client2 = new Unlayer({ apiKey: 'My API Key' }); expect(client2.maxRetries).toEqual(2); }); @@ -391,7 +368,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', maxRetries: 3, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); const newClient = client.withOptions({ @@ -417,7 +394,7 @@ describe('instantiate client', () => { baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-Test-Header': 'test-value' }, defaultQuery: { 'test-param': 'test-value' }, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); const newClient = client.withOptions({ @@ -435,7 +412,7 @@ describe('instantiate client', () => { const client = new Unlayer({ baseURL: 'http://localhost:5000/', timeout: 1000, - accessToken: 'My Access Token', + apiKey: 'My API Key', }); // Modify the client properties directly after creation @@ -464,21 +441,21 @@ describe('instantiate client', () => { test('with environment variable arguments', () => { // set options via env var - process.env['UNLAYER_ACCESS_TOKEN'] = 'My Access Token'; + process.env['UNLAYER_API_KEY'] = 'My API Key'; const client = new Unlayer(); - expect(client.accessToken).toBe('My Access Token'); + expect(client.apiKey).toBe('My API Key'); }); test('with overridden environment variable arguments', () => { // set options via env var - process.env['UNLAYER_ACCESS_TOKEN'] = 'another My Access Token'; - const client = new Unlayer({ accessToken: 'My Access Token' }); - expect(client.accessToken).toBe('My Access Token'); + process.env['UNLAYER_API_KEY'] = 'another My API Key'; + const client = new Unlayer({ apiKey: 'My API Key' }); + expect(client.apiKey).toBe('My API Key'); }); }); describe('request building', () => { - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); describe('custom headers', () => { test('handles undefined', async () => { @@ -497,7 +474,7 @@ describe('request building', () => { }); describe('default encoder', () => { - const client = new Unlayer({ accessToken: 'My Access Token' }); + const client = new Unlayer({ apiKey: 'My API Key' }); class Serializable { toJSON() { @@ -583,7 +560,7 @@ describe('retries', () => { }; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', timeout: 10, fetch: testFetch, }); @@ -617,7 +594,7 @@ describe('retries', () => { }; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, }); @@ -645,7 +622,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, }); @@ -678,7 +655,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, defaultHeaders: { 'X-Stainless-Retry-Count': null }, @@ -711,7 +688,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Unlayer({ - accessToken: 'My Access Token', + apiKey: 'My API Key', fetch: testFetch, maxRetries: 4, }); @@ -744,7 +721,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ accessToken: 'My Access Token', fetch: testFetch }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -774,7 +751,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Unlayer({ accessToken: 'My Access Token', fetch: testFetch }); + const client = new Unlayer({ apiKey: 'My API Key', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); From 228c4d4e8075e181e5aa11107b9e288dea3c0abf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:01:48 +0000 Subject: [PATCH 060/118] feat(api): api update --- .stats.yml | 6 ++-- README.md | 31 +++++++++++-------- api.md | 6 ++-- src/client.ts | 12 +++---- src/resources/index.ts | 2 +- src/resources/{project.ts => projects.ts} | 26 +++++----------- .../{project.test.ts => projects.test.ts} | 11 ++----- 7 files changed, 38 insertions(+), 56 deletions(-) rename src/resources/{project.ts => projects.ts} (57%) rename tests/api-resources/{project.test.ts => projects.test.ts} (59%) diff --git a/.stats.yml b/.stats.yml index 2fb1d6b..3004020 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-14707e371ca64ee082f425e10f8bd4b7d9e2eeb28d6e69daad66902abb1b8b6b.yml -openapi_spec_hash: 8198d0442f4736109bf6c49a5a8697ab -config_hash: 144077318a24cfbe9ce6da795a628a80 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-48f00d1c04c23fb4d1cb7cf4af4f56b0c920d758c1f06e06e5373e5b15e9c27d.yml +openapi_spec_hash: 6ee2a94bb9840aceb4a6161c724ce46c +config_hash: c8d97d58d67dad9eeb65eb58fc781724 diff --git a/README.md b/README.md index b00af96..4d6a2dd 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,10 @@ const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); -const project = await client.project.retrieve({ projectId: 'your-project-id' }); +const page = await client.templates.list({ limit: 10, projectId: 'your-project-id' }); +const templateListResponse = page.data[0]; -console.log(project.data); +console.log(templateListResponse.id); ``` ### Request & Response types @@ -43,8 +44,8 @@ const client = new Unlayer({ apiKey: process.env['UNLAYER_API_KEY'], // This is the default and can be omitted }); -const params: Unlayer.ProjectRetrieveParams = { projectId: 'your-project-id' }; -const project: Unlayer.ProjectRetrieveResponse = await client.project.retrieve(params); +const params: Unlayer.TemplateListParams = { limit: 10, projectId: 'your-project-id' }; +const [templateListResponse]: [Unlayer.TemplateListResponse] = await client.templates.list(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -57,8 +58,8 @@ a subclass of `APIError` will be thrown: ```ts -const project = await client.project - .retrieve({ projectId: 'your-project-id' }) +const page = await client.templates + .list({ limit: 10, projectId: 'your-project-id' }) .catch(async (err) => { if (err instanceof Unlayer.APIError) { console.log(err.status); // 400 @@ -99,7 +100,7 @@ const client = new Unlayer({ }); // Or, configure per-request: -await client.project.retrieve({ projectId: 'your-project-id' }, { +await client.templates.list({ limit: 10, projectId: 'your-project-id' }, { maxRetries: 5, }); ``` @@ -116,7 +117,7 @@ const client = new Unlayer({ }); // Override per-request: -await client.project.retrieve({ projectId: 'your-project-id' }, { +await client.templates.list({ limit: 10, projectId: 'your-project-id' }, { timeout: 5 * 1000, }); ``` @@ -173,15 +174,19 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Unlayer(); -const response = await client.project.retrieve({ projectId: 'your-project-id' }).asResponse(); +const response = await client.templates + .list({ limit: 10, projectId: 'your-project-id' }) + .asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: project, response: raw } = await client.project - .retrieve({ projectId: 'your-project-id' }) +const { data: page, response: raw } = await client.templates + .list({ limit: 10, projectId: 'your-project-id' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(project.data); +for await (const templateListResponse of page) { + console.log(templateListResponse.id); +} ``` ### Logging @@ -261,7 +266,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.project.retrieve({ +client.templates.list({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index 4399859..6cee992 100644 --- a/api.md +++ b/api.md @@ -20,15 +20,15 @@ Methods: - client.convert.simpleToFull.create({ ...params }) -> SimpleToFullCreateResponse -# Project +# Projects Types: -- ProjectRetrieveResponse +- ProjectRetrieveResponse Methods: -- client.project.retrieve({ ...params }) -> ProjectRetrieveResponse +- client.projects.retrieve(id) -> ProjectRetrieveResponse # Templates diff --git a/src/client.ts b/src/client.ts index ed5b220..889cbc0 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,7 +18,7 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { Project, ProjectRetrieveParams, ProjectRetrieveResponse } from './resources/project'; +import { ProjectRetrieveResponse, Projects } from './resources/projects'; import { TemplateListParams, TemplateListResponse, @@ -813,13 +813,13 @@ export class Unlayer { static toFile = Uploads.toFile; convert: API.Convert = new API.Convert(this); - project: API.Project = new API.Project(this); + projects: API.Projects = new API.Projects(this); templates: API.Templates = new API.Templates(this); workspaces: API.Workspaces = new API.Workspaces(this); } Unlayer.Convert = Convert; -Unlayer.Project = Project; +Unlayer.Projects = Projects; Unlayer.Templates = Templates; Unlayer.Workspaces = Workspaces; @@ -831,11 +831,7 @@ export declare namespace Unlayer { export { Convert as Convert }; - export { - Project as Project, - type ProjectRetrieveResponse as ProjectRetrieveResponse, - type ProjectRetrieveParams as ProjectRetrieveParams, - }; + export { Projects as Projects, type ProjectRetrieveResponse as ProjectRetrieveResponse }; export { Templates as Templates, diff --git a/src/resources/index.ts b/src/resources/index.ts index bc83167..303eae0 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Convert } from './convert/convert'; -export { Project, type ProjectRetrieveResponse, type ProjectRetrieveParams } from './project'; +export { Projects, type ProjectRetrieveResponse } from './projects'; export { Templates, type TemplateRetrieveResponse, diff --git a/src/resources/project.ts b/src/resources/projects.ts similarity index 57% rename from src/resources/project.ts rename to src/resources/projects.ts index 1ee648e..6b97668 100644 --- a/src/resources/project.ts +++ b/src/resources/projects.ts @@ -3,16 +3,14 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; -export class Project extends APIResource { +export class Projects extends APIResource { /** - * Get project details for the specified project. + * Get project details by ID. */ - retrieve( - query: ProjectRetrieveParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/v3/project', { query, ...options }); + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/projects/${id}`, options); } } @@ -54,16 +52,6 @@ export namespace ProjectRetrieveResponse { } } -export interface ProjectRetrieveParams { - /** - * The project ID (required for PAT auth, auto-resolved for API key auth) - */ - projectId?: string; -} - -export declare namespace Project { - export { - type ProjectRetrieveResponse as ProjectRetrieveResponse, - type ProjectRetrieveParams as ProjectRetrieveParams, - }; +export declare namespace Projects { + export { type ProjectRetrieveResponse as ProjectRetrieveResponse }; } diff --git a/tests/api-resources/project.test.ts b/tests/api-resources/projects.test.ts similarity index 59% rename from tests/api-resources/project.test.ts rename to tests/api-resources/projects.test.ts index 6365f13..856e49a 100644 --- a/tests/api-resources/project.test.ts +++ b/tests/api-resources/projects.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource project', () => { +describe('resource projects', () => { test('retrieve', async () => { - const responsePromise = client.project.retrieve(); + const responsePromise = client.projects.retrieve('id'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -18,11 +18,4 @@ describe('resource project', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); - - test('retrieve: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.project.retrieve({ projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Unlayer.NotFoundError); - }); }); From c2d4322801d6f20bdda02d53e3cacd57abeaa025 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 04:20:49 +0000 Subject: [PATCH 061/118] fix(docs/contributing): correct pnpm link command --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dad7a7c..051f357 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ $ yarn link @unlayer/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @unlayer/sdk +$ pnpm link --global @unlayer/sdk ``` ## Running tests From 67e57f89cf5b46a97415da30edde0bb9b4ffaa90 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 08:55:55 +0000 Subject: [PATCH 062/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 3004020..3b0ed67 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-48f00d1c04c23fb4d1cb7cf4af4f56b0c920d758c1f06e06e5373e5b15e9c27d.yml openapi_spec_hash: 6ee2a94bb9840aceb4a6161c724ce46c -config_hash: c8d97d58d67dad9eeb65eb58fc781724 +config_hash: e1b17e2707760d0c014601073f354d8b From a17ad3200edb0bf43530181a25825c7872dad3f4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 08:56:38 +0000 Subject: [PATCH 063/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 3b0ed67..2702d73 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-48f00d1c04c23fb4d1cb7cf4af4f56b0c920d758c1f06e06e5373e5b15e9c27d.yml openapi_spec_hash: 6ee2a94bb9840aceb4a6161c724ce46c -config_hash: e1b17e2707760d0c014601073f354d8b +config_hash: 249869757b6eb98ae3d58f2a47ce21e2 From 89107916a1d6e9dcd4f71ba58fd66256c436fc73 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 08:59:50 +0000 Subject: [PATCH 064/118] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b985ff6..466df71 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.1.0" } diff --git a/package.json b/package.json index 693d311..af883de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@unlayer/sdk", - "version": "0.0.1", + "version": "0.1.0", "description": "The official TypeScript library for the Unlayer API", "author": "Unlayer ", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d74dce8..1baa228 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1'; // x-release-please-version +export const VERSION = '0.1.0'; // x-release-please-version From 5babe0d5b971b5ace1ea5e70918521f1860696b0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 21:27:13 +0000 Subject: [PATCH 065/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2702d73..3004020 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-48f00d1c04c23fb4d1cb7cf4af4f56b0c920d758c1f06e06e5373e5b15e9c27d.yml openapi_spec_hash: 6ee2a94bb9840aceb4a6161c724ce46c -config_hash: 249869757b6eb98ae3d58f2a47ce21e2 +config_hash: c8d97d58d67dad9eeb65eb58fc781724 From 2af1120f52bfe82cec03dee1ab258e94663e7a70 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 05:12:35 +0000 Subject: [PATCH 066/118] chore(internal): move stringifyQuery implementation to internal function --- src/client.ts | 22 +++++----------------- src/internal/utils.ts | 1 + src/internal/utils/query.ts | 23 +++++++++++++++++++++++ tests/stringifyQuery.test.ts | 6 ++---- 4 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 src/internal/utils/query.ts diff --git a/src/client.ts b/src/client.ts index 889cbc0..0b9842c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -11,6 +11,7 @@ import type { APIResponseProps } from './internal/parse'; import { getPlatformHeaders } from './internal/detect-platform'; import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; +import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as Pagination from './core/pagination'; @@ -271,21 +272,8 @@ export class Unlayer { /** * Basic re-implementation of `qs.stringify` for primitive types. */ - protected stringifyQuery(query: Record): string { - return Object.entries(query) - .filter(([_, value]) => typeof value !== 'undefined') - .map(([key, value]) => { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } - if (value === null) { - return `${encodeURIComponent(key)}=`; - } - throw new Errors.UnlayerError( - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, - ); - }) - .join('&'); + protected stringifyQuery(query: object | Record): string { + return stringifyQuery(query); } private getUserAgent(): string { @@ -322,7 +310,7 @@ export class Unlayer { } if (typeof query === 'object' && query && !Array.isArray(query)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); @@ -786,7 +774,7 @@ export class Unlayer { ) { return { bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, - body: this.stringifyQuery(body as Record), + body: this.stringifyQuery(body), }; } else { return this.#encoder({ body, headers }); diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 3cbfacc..c591353 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -6,3 +6,4 @@ export * from './utils/env'; export * from './utils/log'; export * from './utils/uuid'; export * from './utils/sleep'; +export * from './utils/query'; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 0000000..bd0eb5e --- /dev/null +++ b/src/internal/utils/query.ts @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { UnlayerError } from '../../core/error'; + +/** + * Basic re-implementation of `qs.stringify` for primitive types. + */ +export function stringifyQuery(query: object | Record) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new UnlayerError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); +} diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 4f47883..37eca7e 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,8 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Unlayer } from '@unlayer/sdk'; - -const { stringifyQuery } = Unlayer.prototype as any; +import { stringifyQuery } from '@unlayer/sdk/internal/utils/query'; describe(stringifyQuery, () => { for (const [input, expected] of [ @@ -15,7 +13,7 @@ describe(stringifyQuery, () => { 'e=f', )}=${encodeURIComponent('g&h')}`, ], - ]) { + ] as const) { it(`${JSON.stringify(input)} -> ${expected}`, () => { expect(stringifyQuery(input)).toEqual(expected); }); From 1f74ad627bb05c31e39beef8e7932bcc3103ba7a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:10:29 +0000 Subject: [PATCH 067/118] chore(internal): codegen related update --- src/client.ts | 9 +++++++++ src/resources/convert/full-to-simple.ts | 3 +++ src/resources/convert/simple-to-full.ts | 3 +++ src/resources/projects.ts | 3 +++ src/resources/templates.ts | 3 +++ src/resources/workspaces.ts | 3 +++ 6 files changed, 24 insertions(+) diff --git a/src/client.ts b/src/client.ts index 0b9842c..c6731e9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -801,8 +801,17 @@ export class Unlayer { static toFile = Uploads.toFile; convert: API.Convert = new API.Convert(this); + /** + * Project details and configuration. + */ projects: API.Projects = new API.Projects(this); + /** + * Template management and retrieval. + */ templates: API.Templates = new API.Templates(this); + /** + * Workspace access and management. + */ workspaces: API.Workspaces = new API.Workspaces(this); } diff --git a/src/resources/convert/full-to-simple.ts b/src/resources/convert/full-to-simple.ts index 44e02b9..ceb1e69 100644 --- a/src/resources/convert/full-to-simple.ts +++ b/src/resources/convert/full-to-simple.ts @@ -4,6 +4,9 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; +/** + * Design schema conversion between Full and Simple formats. + */ export class FullToSimple extends APIResource { /** * Convert design json from Full to Simple schema. diff --git a/src/resources/convert/simple-to-full.ts b/src/resources/convert/simple-to-full.ts index c1051de..2790174 100644 --- a/src/resources/convert/simple-to-full.ts +++ b/src/resources/convert/simple-to-full.ts @@ -4,6 +4,9 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; +/** + * Design schema conversion between Full and Simple formats. + */ export class SimpleToFull extends APIResource { /** * Convert design json from Simple to Full schema. diff --git a/src/resources/projects.ts b/src/resources/projects.ts index 6b97668..0d15122 100644 --- a/src/resources/projects.ts +++ b/src/resources/projects.ts @@ -5,6 +5,9 @@ import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Project details and configuration. + */ export class Projects extends APIResource { /** * Get project details by ID. diff --git a/src/resources/templates.ts b/src/resources/templates.ts index 38eef4b..8d1cbb8 100644 --- a/src/resources/templates.ts +++ b/src/resources/templates.ts @@ -6,6 +6,9 @@ import { CursorPage, type CursorPageParams, PagePromise } from '../core/paginati import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Template management and retrieval. + */ export class Templates extends APIResource { /** * Get template by ID. diff --git a/src/resources/workspaces.ts b/src/resources/workspaces.ts index e51624e..4b338e1 100644 --- a/src/resources/workspaces.ts +++ b/src/resources/workspaces.ts @@ -5,6 +5,9 @@ import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Workspace access and management. + */ export class Workspaces extends APIResource { /** * Get a specific workspace by ID with its projects. Requires a Personal Access From b2052f2f7e3b4f87d8694f7b844046d2a9327aee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:07:33 +0000 Subject: [PATCH 068/118] chore(internal): codegen related update --- src/client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index c6731e9..88a8145 100644 --- a/src/client.ts +++ b/src/client.ts @@ -639,9 +639,9 @@ export class Unlayer { } } - // If the API asks us to wait a certain amount of time (and it's a reasonable amount), - // just do what it says, but otherwise calculate a default - if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + // If the API asks us to wait a certain amount of time, just do what it + // says, but otherwise calculate a default + if (timeoutMillis === undefined) { const maxRetries = options.maxRetries ?? this.maxRetries; timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); } From 5a730c7630e239c0878b4e860ea6c2733cad4207 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:30:01 +0000 Subject: [PATCH 069/118] chore(test): do not count install time for mock server timeout --- scripts/mock | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/mock b/scripts/mock index 0b28f6e..bcf3b39 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,11 +21,22 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then + # Pre-install the package so the download doesn't eat into the startup timeout + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - # Wait for server to come online + # Wait for server to come online (max 30s) echo -n "Waiting for server" + attempts=0 while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + attempts=$((attempts + 1)) + if [ "$attempts" -ge 300 ]; then + echo + echo "Timed out waiting for Prism server to start" + cat .prism.log + exit 1 + fi echo -n "." sleep 0.1 done From 6822a04669432920834fbf4694a937d5e96ec317 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:13:43 +0000 Subject: [PATCH 070/118] chore(ci): skip uploading artifacts on stainless-internal branches --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 746dabb..585f542 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,14 +55,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/unlayer-typescript' + if: |- + github.repository == 'stainless-sdks/unlayer-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/unlayer-typescript' + if: |- + github.repository == 'stainless-sdks/unlayer-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} From d0200700fb90c199eb26dac0c9ce2c6ac28678ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:20:53 +0000 Subject: [PATCH 071/118] fix(client): preserve URL params already embedded in path --- src/client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 88a8145..8044a89 100644 --- a/src/client.ts +++ b/src/client.ts @@ -305,8 +305,9 @@ export class Unlayer { : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); - if (!isEmptyObj(defaultQuery)) { - query = { ...defaultQuery, ...query }; + const pathQuery = Object.fromEntries(url.searchParams); + if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) { + query = { ...pathQuery, ...defaultQuery, ...query }; } if (typeof query === 'object' && query && !Array.isArray(query)) { From e260cc281ee054f6301978f852df4d48b2bee1ab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 02:54:14 +0000 Subject: [PATCH 072/118] chore(internal): update dependencies to address dependabot vulnerabilities --- package.json | 11 +++++++++++ yarn.lock | 39 ++++++--------------------------------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index af883de..ef78334 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,17 @@ "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, + "overrides": { + "minimatch": "^9.0.5" + }, + "pnpm": { + "overrides": { + "minimatch": "^9.0.5" + } + }, + "resolutions": { + "minimatch": "^9.0.5" + }, "exports": { ".": { "import": "./dist/index.mjs", diff --git a/yarn.lock b/yarn.lock index fc9f262..078f09a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1219,15 +1219,7 @@ baseline-browser-mapping@^2.9.0: resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== -brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: +brace-expansion@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== @@ -1395,11 +1387,6 @@ commander@^10.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -2600,26 +2587,12 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2, minimatch@^5.0.1, minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^2.0.2" minimist@^1.2.6: version "1.2.6" From a761bdfa79bd26e68dd5b7fb936c51d320163308 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:20:31 +0000 Subject: [PATCH 073/118] chore(internal): tweak CI branches --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 585f542..51c9c41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' From 59a9e316220f95886f6105316f24411fdd51910d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 03:24:05 +0000 Subject: [PATCH 074/118] refactor(tests): switch from prism to steady --- CONTRIBUTING.md | 2 +- scripts/mock | 26 +++++++++++++------------- scripts/test | 16 ++++++++-------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 051f357..6069b57 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,7 @@ $ pnpm link --global @unlayer/sdk ## Running tests -Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. +Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests. ```sh $ ./scripts/mock diff --git a/scripts/mock b/scripts/mock index bcf3b39..38201de 100755 --- a/scripts/mock +++ b/scripts/mock @@ -19,34 +19,34 @@ fi echo "==> Starting mock server with URL ${URL}" -# Run prism mock on the given spec +# Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stdy/cli@0.19.3 -- steady --version - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" &> .stdy.log & - # Wait for server to come online (max 30s) + # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" attempts=0 - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do + if ! kill -0 $! 2>/dev/null; then + echo + cat .stdy.log + exit 1 + fi attempts=$((attempts + 1)) if [ "$attempts" -ge 300 ]; then echo - echo "Timed out waiting for Prism server to start" - cat .prism.log + echo "Timed out waiting for Steady server to start" + cat .stdy.log exit 1 fi echo -n "." sleep 0.1 done - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - echo else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" + npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 7bce051..af1c7a5 100755 --- a/scripts/test +++ b/scripts/test @@ -9,8 +9,8 @@ GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 +function steady_is_running() { + curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1 } kill_server_on_port() { @@ -25,7 +25,7 @@ function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } -if ! is_overriding_api_base_url && ! prism_is_running ; then +if ! is_overriding_api_base_url && ! steady_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT @@ -36,19 +36,19 @@ fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" +elif ! steady_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" + echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.3 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets${NC}" echo exit 1 else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" echo fi From 393d5d6eea336cf3032211a7b6c73faff693dacd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Mar 2026 04:17:16 +0000 Subject: [PATCH 075/118] chore(tests): bump steady to v0.19.4 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index 38201de..e1c19e8 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.19.3 -- steady --version + npm exec --package=@stdy/cli@0.19.4 -- steady --version - npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index af1c7a5..8cf5220 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.3 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.4 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" echo exit 1 From 515ccaa6dab24049e75c25e1071f0c8852e9a28d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Mar 2026 04:21:48 +0000 Subject: [PATCH 076/118] chore(tests): bump steady to v0.19.5 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index e1c19e8..ab814d3 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.19.4 -- steady --version + npm exec --package=@stdy/cli@0.19.5 -- steady --version - npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 8cf5220..907f7be 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.4 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.5 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" echo exit 1 From eb4b9d5378617dabea4b2264559d3d98d4701da9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 04:19:53 +0000 Subject: [PATCH 077/118] chore(internal): update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2412bb7..c85fe68 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log node_modules yarn-error.log codegen.log From 01a9d9d22f88ece50b213d8f4ffd30770e677da8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 04:25:12 +0000 Subject: [PATCH 078/118] chore(tests): bump steady to v0.19.6 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index ab814d3..b319bdf 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.19.5 -- steady --version + npm exec --package=@stdy/cli@0.19.6 -- steady --version - npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 907f7be..8061e04 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.5 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.6 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" echo exit 1 From 700909379fb900795dedb8271046e32ecfed1935 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 03:05:16 +0000 Subject: [PATCH 079/118] chore(ci): skip lint on metadata-only changes Note that we still want to run tests, as these depend on the metadata. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51c9c41..b770d07 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -38,7 +38,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') permissions: contents: read id-token: write From 79d6476d393b61ef6d32db915fc6937c1883a8d3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 03:05:49 +0000 Subject: [PATCH 080/118] chore(tests): bump steady to v0.19.7 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index b319bdf..09eb49f 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.19.6 -- steady --version + npm exec --package=@stdy/cli@0.19.7 -- steady --version - npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 8061e04..a7cf561 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.6 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" echo exit 1 From 28cb1f8c444c6b01f51e73e4c1a70f18afed1a7d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 05:32:30 +0000 Subject: [PATCH 081/118] chore(internal): update multipart form array serialization --- scripts/mock | 4 ++-- scripts/test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mock b/scripts/mock index 09eb49f..290e21b 100755 --- a/scripts/mock +++ b/scripts/mock @@ -24,7 +24,7 @@ if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout npm exec --package=@stdy/cli@0.19.7 -- steady --version - npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index a7cf561..a1ebb5e 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 From 1eb07403a22608da916af33c2114763555106c17 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 06:11:54 +0000 Subject: [PATCH 082/118] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 078f09a..e5e2a93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0" From f4395cf54627d01a570bcb134ce6d1718a4bb0fa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:20:07 +0000 Subject: [PATCH 083/118] chore(tests): bump steady to v0.20.1 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index 290e21b..15c2994 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.19.7 -- steady --version + npm exec --package=@stdy/cli@0.20.1 -- steady --version - npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.20.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.20.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index a1ebb5e..7431f9f 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.20.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 From b663561add273f4bdcd406038081c58349d6b97a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:23:48 +0000 Subject: [PATCH 084/118] chore(tests): bump steady to v0.20.2 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index 15c2994..5cd7c15 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.20.1 -- steady --version + npm exec --package=@stdy/cli@0.20.2 -- steady --version - npm exec --package=@stdy/cli@0.20.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.20.2 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.20.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.20.2 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 7431f9f..a9d718c 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.20.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.20.2 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 From e88c836f64e30af70846f15e2b6f3687f1f1f07c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 08:52:34 +0000 Subject: [PATCH 085/118] chore(internal): codegen related update --- src/internal/utils/env.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/utils/env.ts b/src/internal/utils/env.ts index 2d84800..cc5fa0f 100644 --- a/src/internal/utils/env.ts +++ b/src/internal/utils/env.ts @@ -9,10 +9,10 @@ */ export const readEnv = (env: string): string | undefined => { if (typeof (globalThis as any).process !== 'undefined') { - return (globalThis as any).process.env?.[env]?.trim() ?? undefined; + return (globalThis as any).process.env?.[env]?.trim() || undefined; } if (typeof (globalThis as any).Deno !== 'undefined') { - return (globalThis as any).Deno.env?.get?.(env)?.trim(); + return (globalThis as any).Deno.env?.get?.(env)?.trim() || undefined; } return undefined; }; From 75c295dc7fe1d159c4f8f0979f25d9cf993f9e97 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 02:19:34 +0000 Subject: [PATCH 086/118] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5e2a93..f6eae3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" - integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" + integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== dependencies: balanced-match "^1.0.0" From 985a34f2c71494acdf5e56152fbabf34390ede83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 07:03:09 +0000 Subject: [PATCH 087/118] chore(tests): bump steady to v0.22.1 --- scripts/mock | 6 +++--- scripts/test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mock b/scripts/mock index 5cd7c15..feebe5e 100755 --- a/scripts/mock +++ b/scripts/mock @@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}" # Run steady mock on the given spec if [ "$1" == "--daemon" ]; then # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.20.2 -- steady --version + npm exec --package=@stdy/cli@0.22.1 -- steady --version - npm exec --package=@stdy/cli@0.20.2 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" @@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stdy/cli@0.20.2 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index a9d718c..19b8d0c 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! steady_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.20.2 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 From 3689e5e257526eb8bd675eab37cf0f07153c4e7f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 13:28:09 +0000 Subject: [PATCH 088/118] feat(api): api update --- .stats.yml | 8 +- api.md | 12 ++ src/client.ts | 5 + src/resources/ai.ts | 3 + src/resources/ai/ai.ts | 19 +++ src/resources/ai/generate.ts | 188 ++++++++++++++++++++++++ src/resources/ai/index.ts | 4 + src/resources/index.ts | 1 + tests/api-resources/ai/generate.test.ts | 55 +++++++ 9 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 src/resources/ai.ts create mode 100644 src/resources/ai/ai.ts create mode 100644 src/resources/ai/generate.ts create mode 100644 src/resources/ai/index.ts create mode 100644 tests/api-resources/ai/generate.test.ts diff --git a/.stats.yml b/.stats.yml index 3004020..2750c56 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-48f00d1c04c23fb4d1cb7cf4af4f56b0c920d758c1f06e06e5373e5b15e9c27d.yml -openapi_spec_hash: 6ee2a94bb9840aceb4a6161c724ce46c -config_hash: c8d97d58d67dad9eeb65eb58fc781724 +configured_endpoints: 8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-a1351fe18005248184e11e2c1d6e4a8df7ecfd0092f9fcfeabaa025a2c5b4986.yml +openapi_spec_hash: 3633a7fdec0e4c3d72dcbadeebaea907 +config_hash: 6f1858ca62cea01f7c1c4427b9263c25 diff --git a/api.md b/api.md index 6cee992..c4cfb8a 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,15 @@ +# AI + +## Generate + +Types: + +- GenerateCreateResponse + +Methods: + +- client.ai.generate.create({ ...params }) -> GenerateCreateResponse + # Convert ## FullToSimple diff --git a/src/client.ts b/src/client.ts index 8044a89..86c7199 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,6 +29,7 @@ import { Templates, } from './resources/templates'; import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; +import { AI } from './resources/ai/ai'; import { Convert } from './resources/convert/convert'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; @@ -801,6 +802,7 @@ export class Unlayer { static toFile = Uploads.toFile; + ai: API.AI = new API.AI(this); convert: API.Convert = new API.Convert(this); /** * Project details and configuration. @@ -816,6 +818,7 @@ export class Unlayer { workspaces: API.Workspaces = new API.Workspaces(this); } +Unlayer.AI = AI; Unlayer.Convert = Convert; Unlayer.Projects = Projects; Unlayer.Templates = Templates; @@ -827,6 +830,8 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { AI as AI }; + export { Convert as Convert }; export { Projects as Projects, type ProjectRetrieveResponse as ProjectRetrieveResponse }; diff --git a/src/resources/ai.ts b/src/resources/ai.ts new file mode 100644 index 0000000..6bea0b9 --- /dev/null +++ b/src/resources/ai.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './ai/index'; diff --git a/src/resources/ai/ai.ts b/src/resources/ai/ai.ts new file mode 100644 index 0000000..c94d536 --- /dev/null +++ b/src/resources/ai/ai.ts @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as GenerateAPI from './generate'; +import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; + +export class AI extends APIResource { + generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); +} + +AI.Generate = Generate; + +export declare namespace AI { + export { + Generate as Generate, + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateParams as GenerateCreateParams, + }; +} diff --git a/src/resources/ai/generate.ts b/src/resources/ai/generate.ts new file mode 100644 index 0000000..b55824c --- /dev/null +++ b/src/resources/ai/generate.ts @@ -0,0 +1,188 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Generate extends APIResource { + /** + * Generate, modify, or import an Unlayer design using AI. Provide typed input + * parts to describe what to generate. + */ + create(params: GenerateCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/ai/generate', { query: { projectId }, body, ...options }); + } +} + +/** + * Successfully generated design + */ +export interface GenerateCreateResponse { + /** + * AI response ID + */ + id?: string; + + model?: string; + + output?: GenerateCreateResponse.Output; + + provider?: string; + + usage?: GenerateCreateResponse.Usage; +} + +export namespace GenerateCreateResponse { + export interface Output { + blockType?: string; + + /** + * Generated design data + */ + data?: { [key: string]: unknown }; + + type?: string; + } + + export interface Usage { + cachedInputTokens?: number; + + inputTokens?: number; + + outputTokens?: number; + + reasoningTokens?: number; + + totalTokens?: number; + } +} + +export interface GenerateCreateParams { + /** + * Body param: Display mode for the design + */ + displayMode: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param: Array of typed input parts (max 50) + */ + input: Array; + + /** + * Body param: What to generate + */ + output: GenerateCreateParams.Output; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param: Editor environment context + */ + context?: GenerateCreateParams.Context; + + /** + * Body param: AI model to use, in provider/model format. Optional — defaults to + * anthropic/claude-opus-4-6. + */ + model?: 'anthropic/claude-opus-4-6' | 'openai/gpt-5.2'; +} + +export namespace GenerateCreateParams { + export interface Input { + /** + * The type of input part + */ + type: 'text' | 'prompt' | 'json' | 'html' | 'image'; + + /** + * Predefined prompt ID: SPELLING, EXPAND, SUMMARIZE, REPHRASE, FRIENDLY, FORMAL + * (for type: "prompt") + */ + id?: string; + + /** + * Block type of the design data (for type: "json") + */ + blockType?: string; + + /** + * Existing design data (object, for type: "json") or base64 image data (string, + * for type: "image") + */ + data?: { [key: string]: unknown } | string; + + /** + * HTML string to import (for type: "html") + */ + html?: string; + + /** + * Design schema version (for type: "json") + */ + schemaVersion?: number; + + /** + * Natural language prompt (for type: "text") + */ + text?: string; + + /** + * Image URL to import (for type: "image") + */ + url?: string; + } + + /** + * What to generate + */ + export interface Output { + /** + * The type of design block to generate + */ + blockType: 'template' | 'page' | 'body' | 'content' | 'row' | 'column'; + + /** + * Output format — currently only "json" is supported + */ + type: 'json'; + } + + /** + * Editor environment context + */ + export interface Context { + /** + * Filter content types available in the generated design + */ + availableTools?: Array; + + /** + * Custom tool declarations with their options + */ + customTools?: Array; + + [k: string]: unknown; + } + + export namespace Context { + export interface CustomTool { + options: { [key: string]: unknown }; + + slug: string; + + [k: string]: unknown; + } + } +} + +export declare namespace Generate { + export { + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateParams as GenerateCreateParams, + }; +} diff --git a/src/resources/ai/index.ts b/src/resources/ai/index.ts new file mode 100644 index 0000000..9a970e8 --- /dev/null +++ b/src/resources/ai/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { AI } from './ai'; +export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; diff --git a/src/resources/index.ts b/src/resources/index.ts index 303eae0..07830a5 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { AI } from './ai/ai'; export { Convert } from './convert/convert'; export { Projects, type ProjectRetrieveResponse } from './projects'; export { diff --git a/tests/api-resources/ai/generate.test.ts b/tests/api-resources/ai/generate.test.ts new file mode 100644 index 0000000..603a967 --- /dev/null +++ b/tests/api-resources/ai/generate.test.ts @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource generate', () => { + test('create: only required params', async () => { + const responsePromise = client.ai.generate.create({ + displayMode: 'email', + input: [{ type: 'text' }], + output: { blockType: 'template', type: 'json' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.ai.generate.create({ + displayMode: 'email', + input: [ + { + type: 'text', + id: 'id', + blockType: 'blockType', + data: { foo: 'bar' }, + html: 'html', + schemaVersion: 0, + text: 'text', + url: 'url', + }, + ], + output: { blockType: 'template', type: 'json' }, + projectId: 'projectId', + context: { + availableTools: ['string'], + customTools: [ + { + options: { foo: 'bar' }, + slug: 'slug', + }, + ], + }, + model: 'anthropic/claude-opus-4-6', + }); + }); +}); From fe33d27e54bee4e11d102e6b43da65bb68813a6f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 03:42:33 +0000 Subject: [PATCH 089/118] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index a8b69ff..2e315f5 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From c8d57f52027580316a607c78494eb6348c223579 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:44:14 +0000 Subject: [PATCH 090/118] chore(internal): codegen related update --- scripts/utils/postprocess-files.cjs | 9 ++++++++- src/client.ts | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs index deae575..a8cdeb7 100644 --- a/scripts/utils/postprocess-files.cjs +++ b/scripts/utils/postprocess-files.cjs @@ -23,12 +23,19 @@ async function postprocess() { // strip out lib="dom", types="node", and types="react" references; these // are needed at build time, but would pollute the user's TS environment - const transformed = code.replace( + let transformed = code.replace( /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', ); + // TypeScript's declaration emitter collapses /** @ts-ignore */ onto the same + // line as the type declaration, which doesn't work. So we convert to // @ts-ignore + // on its own line to properly suppresses errors. + if (file.endsWith('.d.ts') || file.endsWith('.d.mts') || file.endsWith('.d.cts')) { + transformed = transformed.replace(/\/\*\* @ts-ignore\b[^*]*\*\/ /gm, '// @ts-ignore\n'); + } + if (transformed !== code) { console.error(`wrote ${path.relative(process.cwd(), file)}`); await fs.promises.writeFile(file, transformed, 'utf8'); diff --git a/src/client.ts b/src/client.ts index 86c7199..aeee2f8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -193,6 +193,18 @@ export class Unlayer { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('UNLAYER_CUSTOM_HEADERS'); + if (customHeadersEnv) { + const parsed: Record = {}; + for (const line of customHeadersEnv.split('\n')) { + const colon = line.indexOf(':'); + if (colon >= 0) { + parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim(); + } + } + options.defaultHeaders = { ...parsed, ...options.defaultHeaders }; + } + this._options = options; this.apiKey = apiKey; From c6ef2dd515dfd73c85cd0494cdd9462f5e22c186 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 05:27:33 +0000 Subject: [PATCH 091/118] chore(internal): codegen related update --- .github/workflows/release-doctor.yml | 1 - eslint.config.mjs | 3 --- package.json | 1 - scripts/fast-format | 9 +++----- scripts/format | 3 +-- scripts/lint | 3 +++ src/internal/types.ts | 14 ++++++------ yarn.lock | 32 ---------------------------- 8 files changed, 13 insertions(+), 53 deletions(-) diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 71339c4..5ea6b81 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -19,4 +19,3 @@ jobs: bash ./bin/check-release-environment env: NPM_TOKEN: ${{ secrets.UNLAYER_NPM_TOKEN || secrets.NPM_TOKEN }} - diff --git a/eslint.config.mjs b/eslint.config.mjs index e0dbbf8..493d7dc 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index ef78334..581b952 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac..f1873ae 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,7 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" -if ! [ -z "$PRETTIER_FILES" ]; then - echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +if ! [ -z "$FILE_LIST" ]; then + cat "$FILE_LIST" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern --ignore-unknown fi diff --git a/scripts/format b/scripts/format index 7a75640..b1b2c17 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a..1f53254 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc..a050513 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,7 +40,6 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; -/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +62,18 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ type RequestInits = | NotAny diff --git a/yarn.lock b/yarn.lock index f6eae3c..18e7cbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,11 +709,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1515,14 +1510,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" - integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" - eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1674,11 +1661,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2841,13 +2823,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3144,13 +3119,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From 2c599bd882a7b5a85b6bfe104d4d121895101f95 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 07:41:23 +0000 Subject: [PATCH 092/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2750c56..ebf5bb6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer%2Funlayer-a1351fe18005248184e11e2c1d6e4a8df7ecfd0092f9fcfeabaa025a2c5b4986.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-a1351fe18005248184e11e2c1d6e4a8df7ecfd0092f9fcfeabaa025a2c5b4986.yml openapi_spec_hash: 3633a7fdec0e4c3d72dcbadeebaea907 config_hash: 6f1858ca62cea01f7c1c4427b9263c25 From a72317163fc5fb5351fd4052ac849520d0c3119e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 04:38:45 +0000 Subject: [PATCH 093/118] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ebf5bb6..740f0ed 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-a1351fe18005248184e11e2c1d6e4a8df7ecfd0092f9fcfeabaa025a2c5b4986.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-2f1a1daca1014db99ea15fb1caa33e8c7bbeb5ce8dfe3c438f54f85994d16cb3.yml openapi_spec_hash: 3633a7fdec0e4c3d72dcbadeebaea907 config_hash: 6f1858ca62cea01f7c1c4427b9263c25 From 0e85ca9921abc6278d8c7a2bb5b39d35073d0c4a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 05:02:48 +0000 Subject: [PATCH 094/118] chore(internal): codegen related update --- src/internal/utils/log.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 1726922..a2a0730 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -107,6 +107,8 @@ export const formatRequestDetails = (details: { name, ( name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'api-key' || + name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ) ? From 47ae715f0a4d12e3245dc5ddfa39d31d9c809e2a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 08:27:55 +0000 Subject: [PATCH 095/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 740f0ed..0f2f691 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-2f1a1daca1014db99ea15fb1caa33e8c7bbeb5ce8dfe3c438f54f85994d16cb3.yml -openapi_spec_hash: 3633a7fdec0e4c3d72dcbadeebaea907 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-b4c4ec2aa5631a32336e52d2c64dc8dc5bfe262f8630e21900ccbab702071d50.yml +openapi_spec_hash: 12a39212e6991daf3731f164dad85455 config_hash: 6f1858ca62cea01f7c1c4427b9263c25 From 72aa262b26d0e486e741054e4ffb658d8a0efab2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:58:45 +0000 Subject: [PATCH 096/118] chore(internal): codegen related update --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-npm.yml | 4 ++-- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b770d07..05b5c45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' @@ -43,10 +43,10 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/unlayer-typescript' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -80,10 +80,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 8d3b32c..59442f8 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: '20' diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 5ea6b81..4b829da 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'unlayer/unlayer-typescript' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From be66e768b3578cb451bff0e8fedd28a4e5bd4f49 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:55:17 +0000 Subject: [PATCH 097/118] chore(internal): codegen related update --- package.json | 2 +- tests/uploads.test.ts | 1 - yarn.lock | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 581b952..a9085e4 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "tslib": "^2.8.1", "typescript": "5.8.3", diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index 7765432..a29d9c2 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,7 +1,6 @@ import fs from 'fs'; import type { ResponseLike } from '@unlayer/sdk/internal/to-file'; import { toFile } from '@unlayer/sdk/core/uploads'; -import { File } from 'node:buffer'; class MyClass { name: string = 'foo'; diff --git a/yarn.lock b/yarn.lock index 18e7cbd..00842e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3192,9 +3192,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 8428040e086f3660fc1a0e21dfbbf8fc5c09bcf0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 13:19:54 +0000 Subject: [PATCH 098/118] feat(api): api update --- .stats.yml | 8 +- api.md | 46 ++--- src/client.ts | 16 +- src/resources/ai.ts | 3 - src/resources/ai/ai.ts | 19 -- src/resources/ai/index.ts | 4 - src/resources/convert.ts | 3 - src/resources/convert/convert.ts | 29 --- src/resources/convert/index.ts | 13 -- src/resources/convert/simple-to-full.ts | 66 ------- src/resources/index.ts | 4 +- src/resources/templates.ts | 112 +----------- .../convert-full-to-simple.ts} | 29 +-- .../templates/convert-simple-to-full.ts | 69 ++++++++ src/resources/{ai => templates}/generate.ts | 5 +- src/resources/templates/import.ts | 118 +++++++++++++ src/resources/templates/index.ts | 22 +++ src/resources/templates/templates.ts | 165 ++++++++++++++++++ .../convert-full-to-simple.test.ts} | 6 +- .../convert-simple-to-full.test.ts} | 6 +- .../{ai => templates}/generate.test.ts | 4 +- tests/api-resources/templates/import.test.ts | 41 +++++ .../{ => templates}/templates.test.ts | 0 23 files changed, 478 insertions(+), 310 deletions(-) delete mode 100644 src/resources/ai.ts delete mode 100644 src/resources/ai/ai.ts delete mode 100644 src/resources/ai/index.ts delete mode 100644 src/resources/convert.ts delete mode 100644 src/resources/convert/convert.ts delete mode 100644 src/resources/convert/index.ts delete mode 100644 src/resources/convert/simple-to-full.ts rename src/resources/{convert/full-to-simple.ts => templates/convert-full-to-simple.ts} (51%) create mode 100644 src/resources/templates/convert-simple-to-full.ts rename src/resources/{ai => templates}/generate.ts (95%) create mode 100644 src/resources/templates/import.ts create mode 100644 src/resources/templates/index.ts create mode 100644 src/resources/templates/templates.ts rename tests/api-resources/{convert/full-to-simple.test.ts => templates/convert-full-to-simple.test.ts} (80%) rename tests/api-resources/{convert/simple-to-full.test.ts => templates/convert-simple-to-full.test.ts} (81%) rename tests/api-resources/{ai => templates}/generate.test.ts (92%) create mode 100644 tests/api-resources/templates/import.test.ts rename tests/api-resources/{ => templates}/templates.test.ts (100%) diff --git a/.stats.yml b/.stats.yml index 0f2f691..f94ad81 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 8 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-b4c4ec2aa5631a32336e52d2c64dc8dc5bfe262f8630e21900ccbab702071d50.yml -openapi_spec_hash: 12a39212e6991daf3731f164dad85455 -config_hash: 6f1858ca62cea01f7c1c4427b9263c25 +configured_endpoints: 9 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-e87049219505c250c95423461c7fb7aa280a3238f98577973c687c1030da26bf.yml +openapi_spec_hash: 613060b45d55c1ab27b70973e4402dfd +config_hash: 2029dabcdae1b263de41e1a890ee90d8 diff --git a/api.md b/api.md index c4cfb8a..9eef13a 100644 --- a/api.md +++ b/api.md @@ -1,58 +1,64 @@ -# AI - -## Generate +# Projects Types: -- GenerateCreateResponse +- ProjectRetrieveResponse Methods: -- client.ai.generate.create({ ...params }) -> GenerateCreateResponse +- client.projects.retrieve(id) -> ProjectRetrieveResponse -# Convert +# Templates + +Types: -## FullToSimple +- TemplateRetrieveResponse +- TemplateListResponse + +Methods: + +- client.templates.retrieve(id, { ...params }) -> TemplateRetrieveResponse +- client.templates.list({ ...params }) -> TemplateListResponsesCursorPage + +## ConvertFullToSimple Types: -- FullToSimpleCreateResponse +- ConvertFullToSimpleCreateResponse Methods: -- client.convert.fullToSimple.create({ ...params }) -> FullToSimpleCreateResponse +- client.templates.convertFullToSimple.create({ ...params }) -> ConvertFullToSimpleCreateResponse -## SimpleToFull +## ConvertSimpleToFull Types: -- SimpleToFullCreateResponse +- ConvertSimpleToFullCreateResponse Methods: -- client.convert.simpleToFull.create({ ...params }) -> SimpleToFullCreateResponse +- client.templates.convertSimpleToFull.create({ ...params }) -> ConvertSimpleToFullCreateResponse -# Projects +## Generate Types: -- ProjectRetrieveResponse +- GenerateCreateResponse Methods: -- client.projects.retrieve(id) -> ProjectRetrieveResponse +- client.templates.generate.create({ ...params }) -> GenerateCreateResponse -# Templates +## Import Types: -- TemplateRetrieveResponse -- TemplateListResponse +- ImportCreateResponse Methods: -- client.templates.retrieve(id, { ...params }) -> TemplateRetrieveResponse -- client.templates.list({ ...params }) -> TemplateListResponsesCursorPage +- client.templates.import.create({ ...params }) -> ImportCreateResponse # Workspaces diff --git a/src/client.ts b/src/client.ts index aeee2f8..676adad 100644 --- a/src/client.ts +++ b/src/client.ts @@ -20,6 +20,7 @@ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; import { ProjectRetrieveResponse, Projects } from './resources/projects'; +import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; import { TemplateListParams, TemplateListResponse, @@ -27,10 +28,7 @@ import { TemplateRetrieveParams, TemplateRetrieveResponse, Templates, -} from './resources/templates'; -import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; -import { AI } from './resources/ai/ai'; -import { Convert } from './resources/convert/convert'; +} from './resources/templates/templates'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -814,14 +812,12 @@ export class Unlayer { static toFile = Uploads.toFile; - ai: API.AI = new API.AI(this); - convert: API.Convert = new API.Convert(this); /** * Project details and configuration. */ projects: API.Projects = new API.Projects(this); /** - * Template management and retrieval. + * Template management — list, retrieve, generate, import, export, and convert designs. */ templates: API.Templates = new API.Templates(this); /** @@ -830,8 +826,6 @@ export class Unlayer { workspaces: API.Workspaces = new API.Workspaces(this); } -Unlayer.AI = AI; -Unlayer.Convert = Convert; Unlayer.Projects = Projects; Unlayer.Templates = Templates; Unlayer.Workspaces = Workspaces; @@ -842,10 +836,6 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; - export { AI as AI }; - - export { Convert as Convert }; - export { Projects as Projects, type ProjectRetrieveResponse as ProjectRetrieveResponse }; export { diff --git a/src/resources/ai.ts b/src/resources/ai.ts deleted file mode 100644 index 6bea0b9..0000000 --- a/src/resources/ai.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './ai/index'; diff --git a/src/resources/ai/ai.ts b/src/resources/ai/ai.ts deleted file mode 100644 index c94d536..0000000 --- a/src/resources/ai/ai.ts +++ /dev/null @@ -1,19 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as GenerateAPI from './generate'; -import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; - -export class AI extends APIResource { - generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); -} - -AI.Generate = Generate; - -export declare namespace AI { - export { - Generate as Generate, - type GenerateCreateResponse as GenerateCreateResponse, - type GenerateCreateParams as GenerateCreateParams, - }; -} diff --git a/src/resources/ai/index.ts b/src/resources/ai/index.ts deleted file mode 100644 index 9a970e8..0000000 --- a/src/resources/ai/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { AI } from './ai'; -export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; diff --git a/src/resources/convert.ts b/src/resources/convert.ts deleted file mode 100644 index 1334f91..0000000 --- a/src/resources/convert.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './convert/index'; diff --git a/src/resources/convert/convert.ts b/src/resources/convert/convert.ts deleted file mode 100644 index d7930c4..0000000 --- a/src/resources/convert/convert.ts +++ /dev/null @@ -1,29 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as FullToSimpleAPI from './full-to-simple'; -import { FullToSimple, FullToSimpleCreateParams, FullToSimpleCreateResponse } from './full-to-simple'; -import * as SimpleToFullAPI from './simple-to-full'; -import { SimpleToFull, SimpleToFullCreateParams, SimpleToFullCreateResponse } from './simple-to-full'; - -export class Convert extends APIResource { - fullToSimple: FullToSimpleAPI.FullToSimple = new FullToSimpleAPI.FullToSimple(this._client); - simpleToFull: SimpleToFullAPI.SimpleToFull = new SimpleToFullAPI.SimpleToFull(this._client); -} - -Convert.FullToSimple = FullToSimple; -Convert.SimpleToFull = SimpleToFull; - -export declare namespace Convert { - export { - FullToSimple as FullToSimple, - type FullToSimpleCreateResponse as FullToSimpleCreateResponse, - type FullToSimpleCreateParams as FullToSimpleCreateParams, - }; - - export { - SimpleToFull as SimpleToFull, - type SimpleToFullCreateResponse as SimpleToFullCreateResponse, - type SimpleToFullCreateParams as SimpleToFullCreateParams, - }; -} diff --git a/src/resources/convert/index.ts b/src/resources/convert/index.ts deleted file mode 100644 index 833a9fc..0000000 --- a/src/resources/convert/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Convert } from './convert'; -export { - FullToSimple, - type FullToSimpleCreateResponse, - type FullToSimpleCreateParams, -} from './full-to-simple'; -export { - SimpleToFull, - type SimpleToFullCreateResponse, - type SimpleToFullCreateParams, -} from './simple-to-full'; diff --git a/src/resources/convert/simple-to-full.ts b/src/resources/convert/simple-to-full.ts deleted file mode 100644 index 2790174..0000000 --- a/src/resources/convert/simple-to-full.ts +++ /dev/null @@ -1,66 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -/** - * Design schema conversion between Full and Simple formats. - */ -export class SimpleToFull extends APIResource { - /** - * Convert design json from Simple to Full schema. - */ - create(body: SimpleToFullCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/v3/convert/simple-to-full', { body, ...options }); - } -} - -export interface SimpleToFullCreateResponse { - data?: SimpleToFullCreateResponse.Data; - - success?: true; -} - -export namespace SimpleToFullCreateResponse { - export interface Data { - design?: { [key: string]: unknown }; - } -} - -export interface SimpleToFullCreateParams { - design: SimpleToFullCreateParams.Design; - - displayMode?: 'email' | 'web' | 'popup' | 'document'; - - includeDefaultValues?: boolean; -} - -export namespace SimpleToFullCreateParams { - export interface Design { - body: { [key: string]: unknown }; - - _conversion?: Design._Conversion; - - counters?: { [key: string]: unknown }; - - schemaVersion?: number; - - [k: string]: unknown; - } - - export namespace Design { - export interface _Conversion { - data?: string; - - version?: number; - } - } -} - -export declare namespace SimpleToFull { - export { - type SimpleToFullCreateResponse as SimpleToFullCreateResponse, - type SimpleToFullCreateParams as SimpleToFullCreateParams, - }; -} diff --git a/src/resources/index.ts b/src/resources/index.ts index 07830a5..6ca716c 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,7 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { AI } from './ai/ai'; -export { Convert } from './convert/convert'; export { Projects, type ProjectRetrieveResponse } from './projects'; export { Templates, @@ -10,5 +8,5 @@ export { type TemplateRetrieveParams, type TemplateListParams, type TemplateListResponsesCursorPage, -} from './templates'; +} from './templates/templates'; export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/templates.ts b/src/resources/templates.ts index 8d1cbb8..cf710e0 100644 --- a/src/resources/templates.ts +++ b/src/resources/templates.ts @@ -1,113 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -/** - * Template management and retrieval. - */ -export class Templates extends APIResource { - /** - * Get template by ID. - */ - retrieve( - id: string, - query: TemplateRetrieveParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/v3/templates/${id}`, { query, ...options }); - } - - /** - * List templates with cursor-based pagination. Returns templates in descending - * order by update time. - */ - list( - query: TemplateListParams | null | undefined = {}, - options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/v3/templates', CursorPage, { query, ...options }); - } -} - -export type TemplateListResponsesCursorPage = CursorPage; - -export interface TemplateRetrieveResponse { - data?: TemplateRetrieveResponse.Data; -} - -export namespace TemplateRetrieveResponse { - export interface Data { - id?: string; - - createdAt?: string; - - design?: { [key: string]: unknown }; - - displayMode?: 'email' | 'web' | 'document'; - - html?: string | null; - - name?: string; - - updatedAt?: string; - } -} - -export interface TemplateListResponse { - /** - * Template ID - */ - id?: string; - - createdAt?: string; - - /** - * Template type/display mode - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Template name - */ - name?: string; - - updatedAt?: string; -} - -export interface TemplateRetrieveParams { - /** - * The project ID (required for PAT auth, auto-resolved for API key auth) - */ - projectId?: string; -} - -export interface TemplateListParams extends CursorPageParams { - /** - * Filter by template type - */ - displayMode?: 'email' | 'web' | 'document'; - - /** - * Filter by name (case-insensitive search) - */ - name?: string; - - /** - * The project ID to list templates for - */ - projectId?: string; -} - -export declare namespace Templates { - export { - type TemplateRetrieveResponse as TemplateRetrieveResponse, - type TemplateListResponse as TemplateListResponse, - type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, - type TemplateRetrieveParams as TemplateRetrieveParams, - type TemplateListParams as TemplateListParams, - }; -} +export * from './templates/index'; diff --git a/src/resources/convert/full-to-simple.ts b/src/resources/templates/convert-full-to-simple.ts similarity index 51% rename from src/resources/convert/full-to-simple.ts rename to src/resources/templates/convert-full-to-simple.ts index ceb1e69..c8b3e8c 100644 --- a/src/resources/convert/full-to-simple.ts +++ b/src/resources/templates/convert-full-to-simple.ts @@ -5,31 +5,34 @@ import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; /** - * Design schema conversion between Full and Simple formats. + * Template management — list, retrieve, generate, import, export, and convert designs. */ -export class FullToSimple extends APIResource { +export class ConvertFullToSimple extends APIResource { /** * Convert design json from Full to Simple schema. */ - create(body: FullToSimpleCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/v3/convert/full-to-simple', { body, ...options }); + create( + body: ConvertFullToSimpleCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v3/templates/convert/full-to-simple', { body, ...options }); } } -export interface FullToSimpleCreateResponse { - data?: FullToSimpleCreateResponse.Data; +export interface ConvertFullToSimpleCreateResponse { + data?: ConvertFullToSimpleCreateResponse.Data; success?: true; } -export namespace FullToSimpleCreateResponse { +export namespace ConvertFullToSimpleCreateResponse { export interface Data { design?: { [key: string]: unknown }; } } -export interface FullToSimpleCreateParams { - design: FullToSimpleCreateParams.Design; +export interface ConvertFullToSimpleCreateParams { + design: ConvertFullToSimpleCreateParams.Design; displayMode?: 'email' | 'web' | 'popup' | 'document'; @@ -42,7 +45,7 @@ export interface FullToSimpleCreateParams { includeDefaultValues?: boolean; } -export namespace FullToSimpleCreateParams { +export namespace ConvertFullToSimpleCreateParams { export interface Design { body: { [key: string]: unknown }; @@ -54,9 +57,9 @@ export namespace FullToSimpleCreateParams { } } -export declare namespace FullToSimple { +export declare namespace ConvertFullToSimple { export { - type FullToSimpleCreateResponse as FullToSimpleCreateResponse, - type FullToSimpleCreateParams as FullToSimpleCreateParams, + type ConvertFullToSimpleCreateResponse as ConvertFullToSimpleCreateResponse, + type ConvertFullToSimpleCreateParams as ConvertFullToSimpleCreateParams, }; } diff --git a/src/resources/templates/convert-simple-to-full.ts b/src/resources/templates/convert-simple-to-full.ts new file mode 100644 index 0000000..c1c0af0 --- /dev/null +++ b/src/resources/templates/convert-simple-to-full.ts @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ +export class ConvertSimpleToFull extends APIResource { + /** + * Convert design json from Simple to Full schema. + */ + create( + body: ConvertSimpleToFullCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v3/templates/convert/simple-to-full', { body, ...options }); + } +} + +export interface ConvertSimpleToFullCreateResponse { + data?: ConvertSimpleToFullCreateResponse.Data; + + success?: true; +} + +export namespace ConvertSimpleToFullCreateResponse { + export interface Data { + design?: { [key: string]: unknown }; + } +} + +export interface ConvertSimpleToFullCreateParams { + design: ConvertSimpleToFullCreateParams.Design; + + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + includeDefaultValues?: boolean; +} + +export namespace ConvertSimpleToFullCreateParams { + export interface Design { + body: { [key: string]: unknown }; + + _conversion?: Design._Conversion; + + counters?: { [key: string]: unknown }; + + schemaVersion?: number; + + [k: string]: unknown; + } + + export namespace Design { + export interface _Conversion { + data?: string; + + version?: number; + } + } +} + +export declare namespace ConvertSimpleToFull { + export { + type ConvertSimpleToFullCreateResponse as ConvertSimpleToFullCreateResponse, + type ConvertSimpleToFullCreateParams as ConvertSimpleToFullCreateParams, + }; +} diff --git a/src/resources/ai/generate.ts b/src/resources/templates/generate.ts similarity index 95% rename from src/resources/ai/generate.ts rename to src/resources/templates/generate.ts index b55824c..e5f73b6 100644 --- a/src/resources/ai/generate.ts +++ b/src/resources/templates/generate.ts @@ -4,6 +4,9 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ export class Generate extends APIResource { /** * Generate, modify, or import an Unlayer design using AI. Provide typed input @@ -11,7 +14,7 @@ export class Generate extends APIResource { */ create(params: GenerateCreateParams, options?: RequestOptions): APIPromise { const { projectId, ...body } = params; - return this._client.post('/v3/ai/generate', { query: { projectId }, body, ...options }); + return this._client.post('/v3/templates/generate', { query: { projectId }, body, ...options }); } } diff --git a/src/resources/templates/import.ts b/src/resources/templates/import.ts new file mode 100644 index 0000000..66c5f87 --- /dev/null +++ b/src/resources/templates/import.ts @@ -0,0 +1,118 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ +export class Import extends APIResource { + /** + * Import an existing template from HTML or an image (URL or base64) and return the + * resulting Unlayer design JSON. No template DB entry is created. + */ + create(params: ImportCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/templates/import', { query: { projectId }, body, ...options }); + } +} + +/** + * Successfully imported template + */ +export interface ImportCreateResponse { + id?: string; + + model?: string; + + output?: ImportCreateResponse.Output; + + provider?: string; + + usage?: ImportCreateResponse.Usage; +} + +export namespace ImportCreateResponse { + export interface Output { + blockType?: string; + + /** + * Imported design data + */ + data?: { [key: string]: unknown }; + + type?: string; + } + + export interface Usage { + cachedInputTokens?: number; + + inputTokens?: number; + + outputTokens?: number; + + reasoningTokens?: number; + + totalTokens?: number; + } +} + +export interface ImportCreateParams { + /** + * Body param: Display mode for the imported design + */ + displayMode: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param: Array of input parts. Must contain exactly one "html" or "image" + * part; may also contain one or more "text" parts with optional instructions. + */ + input: Array; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param: AI model to use, in provider/model format. Optional — defaults to + * anthropic/claude-opus-4-6. + */ + model?: 'anthropic/claude-opus-4-6' | 'openai/gpt-5.2'; +} + +export namespace ImportCreateParams { + export interface Input { + /** + * The type of input part. "html" or "image" carries the source content; "text" + * carries optional instructions to apply during import. + */ + type: 'html' | 'image' | 'text'; + + /** + * Base64 image data URL, e.g. "data:image/png;base64,…" (for type: "image") + */ + data?: string; + + /** + * HTML string to import (for type: "html") + */ + html?: string; + + /** + * Optional natural-language instructions to apply during import (for type: "text") + */ + text?: string; + + /** + * Image URL to import (for type: "image") + */ + url?: string; + } +} + +export declare namespace Import { + export { type ImportCreateResponse as ImportCreateResponse, type ImportCreateParams as ImportCreateParams }; +} diff --git a/src/resources/templates/index.ts b/src/resources/templates/index.ts new file mode 100644 index 0000000..b4f6e4e --- /dev/null +++ b/src/resources/templates/index.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + ConvertFullToSimple, + type ConvertFullToSimpleCreateResponse, + type ConvertFullToSimpleCreateParams, +} from './convert-full-to-simple'; +export { + ConvertSimpleToFull, + type ConvertSimpleToFullCreateResponse, + type ConvertSimpleToFullCreateParams, +} from './convert-simple-to-full'; +export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; +export { Import, type ImportCreateResponse, type ImportCreateParams } from './import'; +export { + Templates, + type TemplateRetrieveResponse, + type TemplateListResponse, + type TemplateRetrieveParams, + type TemplateListParams, + type TemplateListResponsesCursorPage, +} from './templates'; diff --git a/src/resources/templates/templates.ts b/src/resources/templates/templates.ts new file mode 100644 index 0000000..fd15c00 --- /dev/null +++ b/src/resources/templates/templates.ts @@ -0,0 +1,165 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as ConvertFullToSimpleAPI from './convert-full-to-simple'; +import { + ConvertFullToSimple, + ConvertFullToSimpleCreateParams, + ConvertFullToSimpleCreateResponse, +} from './convert-full-to-simple'; +import * as ConvertSimpleToFullAPI from './convert-simple-to-full'; +import { + ConvertSimpleToFull, + ConvertSimpleToFullCreateParams, + ConvertSimpleToFullCreateResponse, +} from './convert-simple-to-full'; +import * as GenerateAPI from './generate'; +import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; +import * as ImportAPI from './import'; +import { Import, ImportCreateParams, ImportCreateResponse } from './import'; +import { APIPromise } from '../../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ +export class Templates extends APIResource { + convertFullToSimple: ConvertFullToSimpleAPI.ConvertFullToSimple = + new ConvertFullToSimpleAPI.ConvertFullToSimple(this._client); + convertSimpleToFull: ConvertSimpleToFullAPI.ConvertSimpleToFull = + new ConvertSimpleToFullAPI.ConvertSimpleToFull(this._client); + generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); + import: ImportAPI.Import = new ImportAPI.Import(this._client); + + /** + * Get template by ID. + */ + retrieve( + id: string, + query: TemplateRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/v3/templates/${id}`, { query, ...options }); + } + + /** + * List templates with cursor-based pagination. Returns templates in descending + * order by update time. + */ + list( + query: TemplateListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/v3/templates', CursorPage, { query, ...options }); + } +} + +export type TemplateListResponsesCursorPage = CursorPage; + +export interface TemplateRetrieveResponse { + data?: TemplateRetrieveResponse.Data; +} + +export namespace TemplateRetrieveResponse { + export interface Data { + id?: string; + + createdAt?: string; + + design?: { [key: string]: unknown }; + + displayMode?: 'email' | 'web' | 'document'; + + html?: string | null; + + name?: string; + + updatedAt?: string; + } +} + +export interface TemplateListResponse { + /** + * Template ID + */ + id?: string; + + createdAt?: string; + + /** + * Template type/display mode + */ + displayMode?: 'email' | 'web' | 'document'; + + /** + * Template name + */ + name?: string; + + updatedAt?: string; +} + +export interface TemplateRetrieveParams { + /** + * The project ID (required for PAT auth, auto-resolved for API key auth) + */ + projectId?: string; +} + +export interface TemplateListParams extends CursorPageParams { + /** + * Filter by template type + */ + displayMode?: 'email' | 'web' | 'document'; + + /** + * Filter by name (case-insensitive search) + */ + name?: string; + + /** + * The project ID to list templates for + */ + projectId?: string; +} + +Templates.ConvertFullToSimple = ConvertFullToSimple; +Templates.ConvertSimpleToFull = ConvertSimpleToFull; +Templates.Generate = Generate; +Templates.Import = Import; + +export declare namespace Templates { + export { + type TemplateRetrieveResponse as TemplateRetrieveResponse, + type TemplateListResponse as TemplateListResponse, + type TemplateListResponsesCursorPage as TemplateListResponsesCursorPage, + type TemplateRetrieveParams as TemplateRetrieveParams, + type TemplateListParams as TemplateListParams, + }; + + export { + ConvertFullToSimple as ConvertFullToSimple, + type ConvertFullToSimpleCreateResponse as ConvertFullToSimpleCreateResponse, + type ConvertFullToSimpleCreateParams as ConvertFullToSimpleCreateParams, + }; + + export { + ConvertSimpleToFull as ConvertSimpleToFull, + type ConvertSimpleToFullCreateResponse as ConvertSimpleToFullCreateResponse, + type ConvertSimpleToFullCreateParams as ConvertSimpleToFullCreateParams, + }; + + export { + Generate as Generate, + type GenerateCreateResponse as GenerateCreateResponse, + type GenerateCreateParams as GenerateCreateParams, + }; + + export { + Import as Import, + type ImportCreateResponse as ImportCreateResponse, + type ImportCreateParams as ImportCreateParams, + }; +} diff --git a/tests/api-resources/convert/full-to-simple.test.ts b/tests/api-resources/templates/convert-full-to-simple.test.ts similarity index 80% rename from tests/api-resources/convert/full-to-simple.test.ts rename to tests/api-resources/templates/convert-full-to-simple.test.ts index 831b256..4936e57 100644 --- a/tests/api-resources/convert/full-to-simple.test.ts +++ b/tests/api-resources/templates/convert-full-to-simple.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource fullToSimple', () => { +describe('resource convertFullToSimple', () => { test('create: only required params', async () => { - const responsePromise = client.convert.fullToSimple.create({ design: { body: { foo: 'bar' } } }); + const responsePromise = client.templates.convertFullToSimple.create({ design: { body: { foo: 'bar' } } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource fullToSimple', () => { }); test('create: required and optional params', async () => { - const response = await client.convert.fullToSimple.create({ + const response = await client.templates.convertFullToSimple.create({ design: { body: { foo: 'bar' }, counters: { foo: 'bar' }, diff --git a/tests/api-resources/convert/simple-to-full.test.ts b/tests/api-resources/templates/convert-simple-to-full.test.ts similarity index 81% rename from tests/api-resources/convert/simple-to-full.test.ts rename to tests/api-resources/templates/convert-simple-to-full.test.ts index a5f33bd..4c80e0d 100644 --- a/tests/api-resources/convert/simple-to-full.test.ts +++ b/tests/api-resources/templates/convert-simple-to-full.test.ts @@ -7,9 +7,9 @@ const client = new Unlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', }); -describe('resource simpleToFull', () => { +describe('resource convertSimpleToFull', () => { test('create: only required params', async () => { - const responsePromise = client.convert.simpleToFull.create({ design: { body: { foo: 'bar' } } }); + const responsePromise = client.templates.convertSimpleToFull.create({ design: { body: { foo: 'bar' } } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,7 +20,7 @@ describe('resource simpleToFull', () => { }); test('create: required and optional params', async () => { - const response = await client.convert.simpleToFull.create({ + const response = await client.templates.convertSimpleToFull.create({ design: { body: { foo: 'bar' }, _conversion: { data: 'data', version: 0 }, diff --git a/tests/api-resources/ai/generate.test.ts b/tests/api-resources/templates/generate.test.ts similarity index 92% rename from tests/api-resources/ai/generate.test.ts rename to tests/api-resources/templates/generate.test.ts index 603a967..2e38f11 100644 --- a/tests/api-resources/ai/generate.test.ts +++ b/tests/api-resources/templates/generate.test.ts @@ -9,7 +9,7 @@ const client = new Unlayer({ describe('resource generate', () => { test('create: only required params', async () => { - const responsePromise = client.ai.generate.create({ + const responsePromise = client.templates.generate.create({ displayMode: 'email', input: [{ type: 'text' }], output: { blockType: 'template', type: 'json' }, @@ -24,7 +24,7 @@ describe('resource generate', () => { }); test('create: required and optional params', async () => { - const response = await client.ai.generate.create({ + const response = await client.templates.generate.create({ displayMode: 'email', input: [ { diff --git a/tests/api-resources/templates/import.test.ts b/tests/api-resources/templates/import.test.ts new file mode 100644 index 0000000..7ac14b8 --- /dev/null +++ b/tests/api-resources/templates/import.test.ts @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource import', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.import.create({ + displayMode: 'email', + input: [{ type: 'html' }], + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.import.create({ + displayMode: 'email', + input: [ + { + type: 'html', + data: 'data', + html: 'html', + text: 'text', + url: 'url', + }, + ], + projectId: 'projectId', + model: 'anthropic/claude-opus-4-6', + }); + }); +}); diff --git a/tests/api-resources/templates.test.ts b/tests/api-resources/templates/templates.test.ts similarity index 100% rename from tests/api-resources/templates.test.ts rename to tests/api-resources/templates/templates.test.ts From 491864748c146d2034f2b6742fbedbdc72cb3853 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 11:49:59 +0000 Subject: [PATCH 099/118] feat(api): api update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 00842e3..06fc108 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== dependencies: balanced-match "^1.0.0" From eb91c61c951b38aff5f495221a9da79d2c89f8ae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 02:22:52 +0000 Subject: [PATCH 100/118] feat(api): api update --- .stats.yml | 8 +- api.md | 1 + src/resources/templates/generate.ts | 219 +++++++++++------- src/resources/templates/import.ts | 9 +- .../api-resources/templates/generate.test.ts | 53 +++-- tests/api-resources/templates/import.test.ts | 2 +- 6 files changed, 188 insertions(+), 104 deletions(-) diff --git a/.stats.yml b/.stats.yml index f94ad81..eb0d57f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 9 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-e87049219505c250c95423461c7fb7aa280a3238f98577973c687c1030da26bf.yml -openapi_spec_hash: 613060b45d55c1ab27b70973e4402dfd -config_hash: 2029dabcdae1b263de41e1a890ee90d8 +configured_endpoints: 10 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-35699cec89167aa9ce539f8008695911611f8bdf923234ed701ee3dbc0c5bcd2.yml +openapi_spec_hash: 2ec4eef9500ac0007e1740f431835931 +config_hash: 20e7fbba9d423291aaf676f6a629dcaf diff --git a/api.md b/api.md index 9eef13a..9e7e057 100644 --- a/api.md +++ b/api.md @@ -49,6 +49,7 @@ Types: Methods: - client.templates.generate.create({ ...params }) -> GenerateCreateResponse +- client.templates.generate.retrieve() -> void ## Import diff --git a/src/resources/templates/generate.ts b/src/resources/templates/generate.ts index e5f73b6..a5b06ca 100644 --- a/src/resources/templates/generate.ts +++ b/src/resources/templates/generate.ts @@ -2,55 +2,102 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; -/** - * Template management — list, retrieve, generate, import, export, and convert designs. - */ export class Generate extends APIResource { /** - * Generate, modify, or import an Unlayer design using AI. Provide typed input - * parts to describe what to generate. + * Generate or modify an Unlayer design using AI. Send the conversation as + * `messages` (today only the last user message is consumed; earlier turns are + * accepted as chat history) and describe the target with `output.kind` + + * `output.displayMode`. Pass the current canvas state in `context` (full design + * JSON + selection pointer) to modify an existing design. Only `anthropic` and + * `openai` models are supported. To import existing HTML or an image instead, use + * POST /v3/templates/import. */ create(params: GenerateCreateParams, options?: RequestOptions): APIPromise { const { projectId, ...body } = params; return this._client.post('/v3/templates/generate', { query: { projectId }, body, ...options }); } + + retrieve(options?: RequestOptions): APIPromise { + return this._client.get('/v3/templates/generate', { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } } /** - * Successfully generated design + * The generated (or modified) design plus model metadata and optional usage + * metadata. */ export interface GenerateCreateResponse { /** - * AI response ID + * Provider response id for the generation turn. */ id?: string; - model?: string; + /** + * The provider + model that actually produced the output (may differ from the + * requested model after failover). + */ + model?: GenerateCreateResponse.Model; + /** + * The generated output for the requested block. + */ output?: GenerateCreateResponse.Output; - provider?: string; - + /** + * Aggregate token usage for the turn when exposed by the caller. Builder copilot + * endpoints expose it only in local/dev/QA and omit it in staging/production. + */ usage?: GenerateCreateResponse.Usage; } export namespace GenerateCreateResponse { - export interface Output { - blockType?: string; + /** + * The provider + model that actually produced the output (may differ from the + * requested model after failover). + */ + export interface Model { + /** + * Resolved model id, e.g. "claude-opus-4-7". + */ + id?: string; /** - * Generated design data + * e.g. "anthropic", "openai". + */ + provider?: string; + } + + /** + * The generated output for the requested block. + */ + export interface Output { + /** + * The generated design JSON, scoped to the requested kind (the full design for + * template/page/body; the row/column/content/element for narrower kinds). */ data?: { [key: string]: unknown }; - type?: string; + /** + * Echoes the requested `output.kind`. + */ + kind?: string; } + /** + * Aggregate token usage for the turn when exposed by the caller. Builder copilot + * endpoints expose it only in local/dev/QA and omit it in staging/production. + */ export interface Usage { cachedInputTokens?: number; + estimatedCostMicroUsd?: number; + inputTokens?: number; outputTokens?: number; @@ -63,17 +110,16 @@ export namespace GenerateCreateResponse { export interface GenerateCreateParams { /** - * Body param: Display mode for the design - */ - displayMode: 'email' | 'web' | 'popup' | 'document'; - - /** - * Body param: Array of typed input parts (max 50) + * Body param: Conversation messages in chronological order, capped at 10 messages. + * The last `user` message is the prompt for this turn; any earlier + * `user`/`assistant` text turns are forwarded to the model as prior chat context. + * A `user` message may carry a predefined prompt action via `metadata.action.id` + * (e.g. SPELLING, REPHRASE). */ - input: Array; + messages: Array; /** - * Body param: What to generate + * Body param */ output: GenerateCreateParams.Output; @@ -84,91 +130,92 @@ export interface GenerateCreateParams { projectId?: string; /** - * Body param: Editor environment context + * Body param */ context?: GenerateCreateParams.Context; /** - * Body param: AI model to use, in provider/model format. Optional — defaults to - * anthropic/claude-opus-4-6. + * Body param: Reserved for future server-side conversation memory. */ - model?: 'anthropic/claude-opus-4-6' | 'openai/gpt-5.2'; + conversationId?: string; + + /** + * Body param: BCP-47 fallback locale for AI status messages. + */ + locale?: string; + + /** + * Body param: AI model in "provider/id" form, e.g. "anthropic/claude-opus-4-7". + * Optional — server resolves a default per output kind. + */ + model?: string; } export namespace GenerateCreateParams { - export interface Input { - /** - * The type of input part - */ - type: 'text' | 'prompt' | 'json' | 'html' | 'image'; + export interface Message { + content: Array; - /** - * Predefined prompt ID: SPELLING, EXPAND, SUMMARIZE, REPHRASE, FRIENDLY, FORMAL - * (for type: "prompt") - */ - id?: string; + role: 'user' | 'assistant' | 'system'; - /** - * Block type of the design data (for type: "json") - */ - blockType?: string; + metadata?: Message.Metadata; + } - /** - * Existing design data (object, for type: "json") or base64 image data (string, - * for type: "image") - */ - data?: { [key: string]: unknown } | string; + export namespace Message { + export interface Content { + type: 'text' | 'image' | 'file'; - /** - * HTML string to import (for type: "html") - */ - html?: string; + file?: Content.File; - /** - * Design schema version (for type: "json") - */ - schemaVersion?: number; + /** + * URL or data URL of the image + */ + image?: string; - /** - * Natural language prompt (for type: "text") - */ - text?: string; + text?: string; + } - /** - * Image URL to import (for type: "image") - */ - url?: string; + export namespace Content { + export interface File { + url: string; + + mediaType?: string; + + [k: string]: unknown; + } + } + + export interface Metadata { + action?: Metadata.Action; + + [k: string]: unknown; + } + + export namespace Metadata { + export interface Action { + id: string; + + [k: string]: unknown; + } + } } - /** - * What to generate - */ export interface Output { - /** - * The type of design block to generate - */ - blockType: 'template' | 'page' | 'body' | 'content' | 'row' | 'column'; + displayMode: 'email' | 'web' | 'popup' | 'document'; - /** - * Output format — currently only "json" is supported - */ - type: 'json'; + kind: 'template' | 'page' | 'body' | 'header' | 'footer' | 'row' | 'column' | 'content' | 'text'; + + schemaVersion?: number; } - /** - * Editor environment context - */ export interface Context { - /** - * Filter content types available in the generated design - */ availableTools?: Array; - /** - * Custom tool declarations with their options - */ customTools?: Array; + fullDesign?: { [key: string]: unknown } | null; + + selection?: Context.Selection | null; + [k: string]: unknown; } @@ -180,6 +227,16 @@ export namespace GenerateCreateParams { [k: string]: unknown; } + + export interface Selection { + id: string | number; + + collection: 'pages' | 'bodies' | 'rows' | 'columns' | 'contents' | 'headers' | 'footers'; + + value?: string; + + [k: string]: unknown; + } } } diff --git a/src/resources/templates/import.ts b/src/resources/templates/import.ts index 66c5f87..1060f2c 100644 --- a/src/resources/templates/import.ts +++ b/src/resources/templates/import.ts @@ -77,10 +77,13 @@ export interface ImportCreateParams { projectId?: string; /** - * Body param: AI model to use, in provider/model format. Optional — defaults to - * anthropic/claude-opus-4-6. + * Body param: AI model to use. Accepts a provider/model string (e.g. + * "anthropic/claude-opus-4-7", "openai/gpt-5.5"), a bare provider ("anthropic", + * "openai") which uses that provider's default model, or a bare model id + * ("claude-opus-4-7", "gpt-5.5") with the provider inferred from the name. + * Optional — defaults to anthropic/claude-opus-4-7. */ - model?: 'anthropic/claude-opus-4-6' | 'openai/gpt-5.2'; + model?: string; } export namespace ImportCreateParams { diff --git a/tests/api-resources/templates/generate.test.ts b/tests/api-resources/templates/generate.test.ts index 2e38f11..c6526f4 100644 --- a/tests/api-resources/templates/generate.test.ts +++ b/tests/api-resources/templates/generate.test.ts @@ -10,9 +10,8 @@ const client = new Unlayer({ describe('resource generate', () => { test('create: only required params', async () => { const responsePromise = client.templates.generate.create({ - displayMode: 'email', - input: [{ type: 'text' }], - output: { blockType: 'template', type: 'json' }, + messages: [{ content: [{ type: 'text' }], role: 'user' }], + output: { displayMode: 'email', kind: 'template' }, }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -25,20 +24,25 @@ describe('resource generate', () => { test('create: required and optional params', async () => { const response = await client.templates.generate.create({ - displayMode: 'email', - input: [ + messages: [ { - type: 'text', - id: 'id', - blockType: 'blockType', - data: { foo: 'bar' }, - html: 'html', - schemaVersion: 0, - text: 'text', - url: 'url', + content: [ + { + type: 'text', + file: { url: 'url', mediaType: 'mediaType' }, + image: 'image', + text: 'text', + }, + ], + role: 'user', + metadata: { action: { id: 'id' } }, }, ], - output: { blockType: 'template', type: 'json' }, + output: { + displayMode: 'email', + kind: 'template', + schemaVersion: 0, + }, projectId: 'projectId', context: { availableTools: ['string'], @@ -48,8 +52,27 @@ describe('resource generate', () => { slug: 'slug', }, ], + fullDesign: { foo: 'bar' }, + selection: { + id: 'string', + collection: 'pages', + value: 'value', + }, }, - model: 'anthropic/claude-opus-4-6', + conversationId: 'conversationId', + locale: 'locale', + model: 'model', }); }); + + test('retrieve', async () => { + const responsePromise = client.templates.generate.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); }); diff --git a/tests/api-resources/templates/import.test.ts b/tests/api-resources/templates/import.test.ts index 7ac14b8..6f66884 100644 --- a/tests/api-resources/templates/import.test.ts +++ b/tests/api-resources/templates/import.test.ts @@ -35,7 +35,7 @@ describe('resource import', () => { }, ], projectId: 'projectId', - model: 'anthropic/claude-opus-4-6', + model: 'model', }); }); }); From b13b2a4ba0b7df51e49f4ae1a6f91eda874ac14f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:16:03 +0000 Subject: [PATCH 101/118] fix(client): send content-type header for requests with an omitted optional body --- src/client.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 676adad..ad86390 100644 --- a/src/client.ts +++ b/src/client.ts @@ -748,11 +748,19 @@ export class Unlayer { return () => controller.abort(); } - private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + private buildBody({ options }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; } { + const { body, headers: rawHeaders } = options; if (!body) { + // A resource method always passes a `body` key when its operation defines a + // request body, even if the caller omitted an optional body param. Keep the + // content-type for those, and only elide it for operations with no body at + // all (e.g. GET/DELETE). + if (body == null && 'body' in options) { + return this.#encoder({ body, headers: buildHeaders([rawHeaders]) }); + } return { bodyHeaders: undefined, body: undefined }; } const headers = buildHeaders([rawHeaders]); From 15fad4b969be1640b158741a03b254567c0d0cf4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 05:37:24 +0000 Subject: [PATCH 102/118] feat(api): api update --- .stats.yml | 4 ++-- src/resources/templates/generate.ts | 12 ++++++++++-- src/resources/templates/import.ts | 9 ++++++++- tests/api-resources/templates/generate.test.ts | 1 + tests/api-resources/templates/import.test.ts | 1 + 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index eb0d57f..13a7855 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-35699cec89167aa9ce539f8008695911611f8bdf923234ed701ee3dbc0c5bcd2.yml -openapi_spec_hash: 2ec4eef9500ac0007e1740f431835931 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-091234302d1c0907a6e2c646ad31f2757e832985758314af9171390851ffc12f.yml +openapi_spec_hash: bbac170e82fb6bb60e0db638457623d1 config_hash: 20e7fbba9d423291aaf676f6a629dcaf diff --git a/src/resources/templates/generate.ts b/src/resources/templates/generate.ts index a5b06ca..d5e60bf 100644 --- a/src/resources/templates/generate.ts +++ b/src/resources/templates/generate.ts @@ -139,14 +139,22 @@ export interface GenerateCreateParams { */ conversationId?: string; + /** + * Body param: Transient-outage fallback controls. Omit to use Unlayer defaults + * only when no model is pinned; true always uses Unlayer defaults; false disables + * the outage tail; an ordered array replaces the default provider/model strings. + */ + fallbackModels?: boolean | Array; + /** * Body param: BCP-47 fallback locale for AI status messages. */ locale?: string; /** - * Body param: AI model in "provider/id" form, e.g. "anthropic/claude-opus-4-7". - * Optional — server resolves a default per output kind. + * Body param: Preferred AI model in "provider/id" form, e.g. + * "anthropic/claude-opus-4-7". Optional — server resolves a default per output + * kind. */ model?: string; } diff --git a/src/resources/templates/import.ts b/src/resources/templates/import.ts index 1060f2c..4e00541 100644 --- a/src/resources/templates/import.ts +++ b/src/resources/templates/import.ts @@ -77,7 +77,14 @@ export interface ImportCreateParams { projectId?: string; /** - * Body param: AI model to use. Accepts a provider/model string (e.g. + * Body param: Transient-outage fallback controls. Omit to use Unlayer defaults + * only when no model is pinned; true always uses Unlayer defaults; false disables + * the outage tail; an ordered array replaces the default provider/model strings. + */ + fallbackModels?: boolean | Array; + + /** + * Body param: Preferred AI model. Accepts a provider/model string (e.g. * "anthropic/claude-opus-4-7", "openai/gpt-5.5"), a bare provider ("anthropic", * "openai") which uses that provider's default model, or a bare model id * ("claude-opus-4-7", "gpt-5.5") with the provider inferred from the name. diff --git a/tests/api-resources/templates/generate.test.ts b/tests/api-resources/templates/generate.test.ts index c6526f4..e383821 100644 --- a/tests/api-resources/templates/generate.test.ts +++ b/tests/api-resources/templates/generate.test.ts @@ -60,6 +60,7 @@ describe('resource generate', () => { }, }, conversationId: 'conversationId', + fallbackModels: true, locale: 'locale', model: 'model', }); diff --git a/tests/api-resources/templates/import.test.ts b/tests/api-resources/templates/import.test.ts index 6f66884..2101af0 100644 --- a/tests/api-resources/templates/import.test.ts +++ b/tests/api-resources/templates/import.test.ts @@ -35,6 +35,7 @@ describe('resource import', () => { }, ], projectId: 'projectId', + fallbackModels: true, model: 'model', }); }); From de4b76ed56f2430d07231d1c829eedeab1222c21 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 07:02:55 +0000 Subject: [PATCH 103/118] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 13a7855..6f038da 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-091234302d1c0907a6e2c646ad31f2757e832985758314af9171390851ffc12f.yml -openapi_spec_hash: bbac170e82fb6bb60e0db638457623d1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-3d1f50d8fdb57c0bbafaa16aeffc061ee7532ed5a9823bacbce1cc0916c008b9.yml +openapi_spec_hash: 97d36fb19154cc936e9ef2558965e290 config_hash: 20e7fbba9d423291aaf676f6a629dcaf From e704af7adbae8c12726a51e4721e1f7c141e171b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:53:16 +0000 Subject: [PATCH 104/118] feat(api): api update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 06fc108..38236e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" - integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + version "2.1.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2" + integrity sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA== dependencies: balanced-match "^1.0.0" From d73c0742de76d42f42d8bcd8c5b0788350f6c896 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:42:46 +0000 Subject: [PATCH 105/118] feat(api): api update --- .stats.yml | 8 +- api.md | 40 ++++++ src/resources/templates/export-html.ts | 111 +++++++++++++++++ src/resources/templates/export-image.ts | 117 ++++++++++++++++++ src/resources/templates/export-pdf.ts | 107 ++++++++++++++++ src/resources/templates/export-zip.ts | 97 +++++++++++++++ src/resources/templates/index.ts | 4 + src/resources/templates/templates.ts | 40 ++++++ .../templates/export-html.test.ts | 38 ++++++ .../templates/export-image.test.ts | 42 +++++++ .../templates/export-pdf.test.ts | 40 ++++++ .../templates/export-zip.test.ts | 38 ++++++ 12 files changed, 678 insertions(+), 4 deletions(-) create mode 100644 src/resources/templates/export-html.ts create mode 100644 src/resources/templates/export-image.ts create mode 100644 src/resources/templates/export-pdf.ts create mode 100644 src/resources/templates/export-zip.ts create mode 100644 tests/api-resources/templates/export-html.test.ts create mode 100644 tests/api-resources/templates/export-image.test.ts create mode 100644 tests/api-resources/templates/export-pdf.test.ts create mode 100644 tests/api-resources/templates/export-zip.test.ts diff --git a/.stats.yml b/.stats.yml index 6f038da..2e4bbbe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-3d1f50d8fdb57c0bbafaa16aeffc061ee7532ed5a9823bacbce1cc0916c008b9.yml -openapi_spec_hash: 97d36fb19154cc936e9ef2558965e290 -config_hash: 20e7fbba9d423291aaf676f6a629dcaf +configured_endpoints: 14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-8f62b635191810fa318afdeaabbbb0276b0e1f85f18b5ff2ddaad9a18241f047.yml +openapi_spec_hash: e80a61e80827f2a822db46f4ba82c15d +config_hash: 2949daec69cb6f5d34ae232544245952 diff --git a/api.md b/api.md index 9e7e057..95b16ff 100644 --- a/api.md +++ b/api.md @@ -40,6 +40,46 @@ Methods: - client.templates.convertSimpleToFull.create({ ...params }) -> ConvertSimpleToFullCreateResponse +## ExportHTML + +Types: + +- ExportHTMLCreateResponse + +Methods: + +- client.templates.exportHTML.create({ ...params }) -> ExportHTMLCreateResponse + +## ExportImage + +Types: + +- ExportImageCreateResponse + +Methods: + +- client.templates.exportImage.create({ ...params }) -> ExportImageCreateResponse + +## ExportPdf + +Types: + +- ExportPdfCreateResponse + +Methods: + +- client.templates.exportPdf.create({ ...params }) -> ExportPdfCreateResponse + +## ExportZip + +Types: + +- ExportZipCreateResponse + +Methods: + +- client.templates.exportZip.create({ ...params }) -> ExportZipCreateResponse + ## Generate Types: diff --git a/src/resources/templates/export-html.ts b/src/resources/templates/export-html.ts new file mode 100644 index 0000000..a6329af --- /dev/null +++ b/src/resources/templates/export-html.ts @@ -0,0 +1,111 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class ExportHTML extends APIResource { + /** + * Export a design as rendered HTML. + */ + create(params: ExportHTMLCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/templates/export/html', { query: { projectId }, body, ...options }); + } +} + +export interface ExportHTMLCreateResponse { + data?: ExportHTMLCreateResponse.Data; + + success?: boolean; +} + +export namespace ExportHTMLCreateResponse { + export interface Data { + chunks?: Data.Chunks; + + html?: string; + } + + export namespace Data { + export interface Chunks { + body?: string; + + css?: string; + + fonts?: Array; + + js?: string; + } + } +} + +export interface ExportHTMLCreateParams { + /** + * Body param: Unlayer design JSON + */ + design: unknown; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param + */ + customJS?: string | Array; + + /** + * Body param + */ + designTags?: unknown; + + /** + * Body param + */ + designTagsConfig?: unknown; + + /** + * Body param + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param + */ + editorVersion?: string; + + /** + * Body param + */ + language?: string; + + /** + * Body param + */ + languages?: Array; + + /** + * Body param + */ + mergeTags?: unknown; + + /** + * Body param + */ + mergeTagsSchema?: unknown; + + /** + * Body param + */ + safeHtml?: boolean; +} + +export declare namespace ExportHTML { + export { + type ExportHTMLCreateResponse as ExportHTMLCreateResponse, + type ExportHTMLCreateParams as ExportHTMLCreateParams, + }; +} diff --git a/src/resources/templates/export-image.ts b/src/resources/templates/export-image.ts new file mode 100644 index 0000000..d6b0046 --- /dev/null +++ b/src/resources/templates/export-image.ts @@ -0,0 +1,117 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class ExportImage extends APIResource { + /** + * Export a design as a PNG image. + */ + create(params: ExportImageCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/templates/export/image', { query: { projectId }, body, ...options }); + } +} + +export interface ExportImageCreateResponse { + data?: ExportImageCreateResponse.Data; + + success?: boolean; +} + +export namespace ExportImageCreateResponse { + export interface Data { + url?: string; + } +} + +export interface ExportImageCreateParams { + /** + * Body param: Unlayer design JSON + */ + design: unknown; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param + */ + customJS?: string | Array; + + /** + * Body param + */ + designTags?: unknown; + + /** + * Body param + */ + designTagsConfig?: unknown; + + /** + * Body param + */ + deviceScaleFactor?: number; + + /** + * Body param + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param + */ + editorVersion?: string; + + /** + * Body param + */ + fullPage?: boolean; + + /** + * Body param + */ + height?: number; + + /** + * Body param + */ + language?: string; + + /** + * Body param + */ + languages?: Array; + + /** + * Body param + */ + mergeTags?: unknown; + + /** + * Body param + */ + mergeTagsSchema?: unknown; + + /** + * Body param + */ + safeHtml?: boolean; + + /** + * Body param + */ + width?: number; +} + +export declare namespace ExportImage { + export { + type ExportImageCreateResponse as ExportImageCreateResponse, + type ExportImageCreateParams as ExportImageCreateParams, + }; +} diff --git a/src/resources/templates/export-pdf.ts b/src/resources/templates/export-pdf.ts new file mode 100644 index 0000000..597d1f7 --- /dev/null +++ b/src/resources/templates/export-pdf.ts @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class ExportPdf extends APIResource { + /** + * Export a design as a PDF document. + */ + create(params: ExportPdfCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/templates/export/pdf', { query: { projectId }, body, ...options }); + } +} + +export interface ExportPdfCreateResponse { + data?: ExportPdfCreateResponse.Data; + + success?: boolean; +} + +export namespace ExportPdfCreateResponse { + export interface Data { + url?: string; + } +} + +export interface ExportPdfCreateParams { + /** + * Body param: Unlayer design JSON + */ + design: unknown; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param + */ + contentWidth?: number | 'full'; + + /** + * Body param + */ + customJS?: string | Array; + + /** + * Body param + */ + designTags?: unknown; + + /** + * Body param + */ + designTagsConfig?: unknown; + + /** + * Body param + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param + */ + editorVersion?: string; + + /** + * Body param + */ + language?: string; + + /** + * Body param + */ + languages?: Array; + + /** + * Body param + */ + mergeTags?: unknown; + + /** + * Body param + */ + mergeTagsSchema?: unknown; + + /** + * Body param + */ + pageSize?: 'Letter' | 'Legal' | 'Tabloid' | 'Ledger' | 'A0' | 'A1' | 'A2' | 'A3' | 'A4' | 'A5' | 'A6'; + + /** + * Body param + */ + safeHtml?: boolean; +} + +export declare namespace ExportPdf { + export { + type ExportPdfCreateResponse as ExportPdfCreateResponse, + type ExportPdfCreateParams as ExportPdfCreateParams, + }; +} diff --git a/src/resources/templates/export-zip.ts b/src/resources/templates/export-zip.ts new file mode 100644 index 0000000..00f07a6 --- /dev/null +++ b/src/resources/templates/export-zip.ts @@ -0,0 +1,97 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class ExportZip extends APIResource { + /** + * Export a design as a ZIP archive containing HTML and assets. + */ + create(params: ExportZipCreateParams, options?: RequestOptions): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/templates/export/zip', { query: { projectId }, body, ...options }); + } +} + +export interface ExportZipCreateResponse { + data?: ExportZipCreateResponse.Data; + + success?: boolean; +} + +export namespace ExportZipCreateResponse { + export interface Data { + url?: string; + } +} + +export interface ExportZipCreateParams { + /** + * Body param: Unlayer design JSON + */ + design: unknown; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param + */ + customJS?: string | Array; + + /** + * Body param + */ + designTags?: unknown; + + /** + * Body param + */ + designTagsConfig?: unknown; + + /** + * Body param + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * Body param + */ + editorVersion?: string; + + /** + * Body param + */ + language?: string; + + /** + * Body param + */ + languages?: Array; + + /** + * Body param + */ + mergeTags?: unknown; + + /** + * Body param + */ + mergeTagsSchema?: unknown; + + /** + * Body param + */ + safeHtml?: boolean; +} + +export declare namespace ExportZip { + export { + type ExportZipCreateResponse as ExportZipCreateResponse, + type ExportZipCreateParams as ExportZipCreateParams, + }; +} diff --git a/src/resources/templates/index.ts b/src/resources/templates/index.ts index b4f6e4e..c07698b 100644 --- a/src/resources/templates/index.ts +++ b/src/resources/templates/index.ts @@ -10,6 +10,10 @@ export { type ConvertSimpleToFullCreateResponse, type ConvertSimpleToFullCreateParams, } from './convert-simple-to-full'; +export { ExportHTML, type ExportHTMLCreateResponse, type ExportHTMLCreateParams } from './export-html'; +export { ExportImage, type ExportImageCreateResponse, type ExportImageCreateParams } from './export-image'; +export { ExportPdf, type ExportPdfCreateResponse, type ExportPdfCreateParams } from './export-pdf'; +export { ExportZip, type ExportZipCreateResponse, type ExportZipCreateParams } from './export-zip'; export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; export { Import, type ImportCreateResponse, type ImportCreateParams } from './import'; export { diff --git a/src/resources/templates/templates.ts b/src/resources/templates/templates.ts index fd15c00..96b914f 100644 --- a/src/resources/templates/templates.ts +++ b/src/resources/templates/templates.ts @@ -13,6 +13,14 @@ import { ConvertSimpleToFullCreateParams, ConvertSimpleToFullCreateResponse, } from './convert-simple-to-full'; +import * as ExportHTMLAPI from './export-html'; +import { ExportHTML, ExportHTMLCreateParams, ExportHTMLCreateResponse } from './export-html'; +import * as ExportImageAPI from './export-image'; +import { ExportImage, ExportImageCreateParams, ExportImageCreateResponse } from './export-image'; +import * as ExportPdfAPI from './export-pdf'; +import { ExportPdf, ExportPdfCreateParams, ExportPdfCreateResponse } from './export-pdf'; +import * as ExportZipAPI from './export-zip'; +import { ExportZip, ExportZipCreateParams, ExportZipCreateResponse } from './export-zip'; import * as GenerateAPI from './generate'; import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; import * as ImportAPI from './import'; @@ -30,6 +38,10 @@ export class Templates extends APIResource { new ConvertFullToSimpleAPI.ConvertFullToSimple(this._client); convertSimpleToFull: ConvertSimpleToFullAPI.ConvertSimpleToFull = new ConvertSimpleToFullAPI.ConvertSimpleToFull(this._client); + exportHTML: ExportHTMLAPI.ExportHTML = new ExportHTMLAPI.ExportHTML(this._client); + exportImage: ExportImageAPI.ExportImage = new ExportImageAPI.ExportImage(this._client); + exportPdf: ExportPdfAPI.ExportPdf = new ExportPdfAPI.ExportPdf(this._client); + exportZip: ExportZipAPI.ExportZip = new ExportZipAPI.ExportZip(this._client); generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); import: ImportAPI.Import = new ImportAPI.Import(this._client); @@ -127,6 +139,10 @@ export interface TemplateListParams extends CursorPageParams { Templates.ConvertFullToSimple = ConvertFullToSimple; Templates.ConvertSimpleToFull = ConvertSimpleToFull; +Templates.ExportHTML = ExportHTML; +Templates.ExportImage = ExportImage; +Templates.ExportPdf = ExportPdf; +Templates.ExportZip = ExportZip; Templates.Generate = Generate; Templates.Import = Import; @@ -151,6 +167,30 @@ export declare namespace Templates { type ConvertSimpleToFullCreateParams as ConvertSimpleToFullCreateParams, }; + export { + ExportHTML as ExportHTML, + type ExportHTMLCreateResponse as ExportHTMLCreateResponse, + type ExportHTMLCreateParams as ExportHTMLCreateParams, + }; + + export { + ExportImage as ExportImage, + type ExportImageCreateResponse as ExportImageCreateResponse, + type ExportImageCreateParams as ExportImageCreateParams, + }; + + export { + ExportPdf as ExportPdf, + type ExportPdfCreateResponse as ExportPdfCreateResponse, + type ExportPdfCreateParams as ExportPdfCreateParams, + }; + + export { + ExportZip as ExportZip, + type ExportZipCreateResponse as ExportZipCreateResponse, + type ExportZipCreateParams as ExportZipCreateParams, + }; + export { Generate as Generate, type GenerateCreateResponse as GenerateCreateResponse, diff --git a/tests/api-resources/templates/export-html.test.ts b/tests/api-resources/templates/export-html.test.ts new file mode 100644 index 0000000..f12a201 --- /dev/null +++ b/tests/api-resources/templates/export-html.test.ts @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource exportHTML', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.exportHTML.create({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.exportHTML.create({ + design: {}, + projectId: 'projectId', + customJS: 'string', + designTags: {}, + designTagsConfig: {}, + displayMode: 'email', + editorVersion: 'editorVersion', + language: 'language', + languages: ['string'], + mergeTags: {}, + mergeTagsSchema: {}, + safeHtml: true, + }); + }); +}); diff --git a/tests/api-resources/templates/export-image.test.ts b/tests/api-resources/templates/export-image.test.ts new file mode 100644 index 0000000..69dbd4d --- /dev/null +++ b/tests/api-resources/templates/export-image.test.ts @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource exportImage', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.exportImage.create({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.exportImage.create({ + design: {}, + projectId: 'projectId', + customJS: 'string', + designTags: {}, + designTagsConfig: {}, + deviceScaleFactor: 0, + displayMode: 'email', + editorVersion: 'editorVersion', + fullPage: true, + height: 0, + language: 'language', + languages: ['string'], + mergeTags: {}, + mergeTagsSchema: {}, + safeHtml: true, + width: 0, + }); + }); +}); diff --git a/tests/api-resources/templates/export-pdf.test.ts b/tests/api-resources/templates/export-pdf.test.ts new file mode 100644 index 0000000..8415fd7 --- /dev/null +++ b/tests/api-resources/templates/export-pdf.test.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource exportPdf', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.exportPdf.create({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.exportPdf.create({ + design: {}, + projectId: 'projectId', + contentWidth: 'full', + customJS: 'string', + designTags: {}, + designTagsConfig: {}, + displayMode: 'email', + editorVersion: 'editorVersion', + language: 'language', + languages: ['string'], + mergeTags: {}, + mergeTagsSchema: {}, + pageSize: 'Letter', + safeHtml: true, + }); + }); +}); diff --git a/tests/api-resources/templates/export-zip.test.ts b/tests/api-resources/templates/export-zip.test.ts new file mode 100644 index 0000000..3f4366c --- /dev/null +++ b/tests/api-resources/templates/export-zip.test.ts @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource exportZip', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.exportZip.create({ design: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.exportZip.create({ + design: {}, + projectId: 'projectId', + customJS: 'string', + designTags: {}, + designTagsConfig: {}, + displayMode: 'email', + editorVersion: 'editorVersion', + language: 'language', + languages: ['string'], + mergeTags: {}, + mergeTagsSchema: {}, + safeHtml: true, + }); + }); +}); From a7b1eceea81b2940501385cf5b50dbf74d858b24 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 02:21:41 +0000 Subject: [PATCH 106/118] fix(ci): bump @arethetypeswrong/cli to ^0.18.0 and run CI workflows on Node 24 --- .github/workflows/ci.yml | 6 ++-- .github/workflows/publish-npm.yml | 2 +- package.json | 2 +- yarn.lock | 51 +++++++++++++++++++------------ 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05b5c45..0579bd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap @@ -48,7 +48,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap @@ -85,7 +85,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 59442f8..17e1064 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Node uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: - node-version: '20' + node-version: '24' - name: Install dependencies run: | diff --git a/package.json b/package.json index a9085e4..3544a8f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "dependencies": {}, "devDependencies": { - "@arethetypeswrong/cli": "^0.17.0", + "@arethetypeswrong/cli": "^0.18.0", "@swc/core": "^1.3.102", "@swc/jest": "^0.2.29", "@types/jest": "^29.4.0", diff --git a/yarn.lock b/yarn.lock index 38236e6..443cc05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,12 +12,12 @@ resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== -"@arethetypeswrong/cli@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" - integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== +"@arethetypeswrong/cli@^0.18.0": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.18.4.tgz#c31f54f3b0d0e0f3256ab3edb6530beeb5e64b4b" + integrity sha512-kNWo6LTzGAuLYPpJ7Sgo63whSUeeSuKMlYx6IBgzs4ONEG807gW4hSSENvpeCHzO2H2wIzG5EFl0OKBbqGBAyA== dependencies: - "@arethetypeswrong/core" "0.17.0" + "@arethetypeswrong/core" "0.18.4" chalk "^4.1.2" cli-table3 "^0.6.3" commander "^10.0.1" @@ -25,15 +25,16 @@ marked-terminal "^7.1.0" semver "^7.5.4" -"@arethetypeswrong/core@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" - integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== +"@arethetypeswrong/core@0.18.4": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.18.4.tgz#24edea3d651dea7d32bf6f1cc9ee9a00db39de49" + integrity sha512-M5F0ePyN6h2Z6XxRiyIPqjGbltotXLjR0CKA0uKspsDu0QmgTNYvRb4RSQPMUs2ZXZHCCYpbaZbFbYOXLxCjUA== dependencies: "@andrewbranch/untar.js" "^1.0.3" + "@loaderkit/resolve" "^1.0.2" cjs-module-lexer "^1.2.3" - fflate "^0.8.2" - lru-cache "^10.4.3" + fflate "^0.8.3" + lru-cache "^11.0.1" semver "^7.5.4" typescript "5.6.1-rc" validate-npm-package-name "^5.0.0" @@ -306,6 +307,11 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@braidai/lang@^1.0.0": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@braidai/lang/-/lang-1.1.2.tgz#65bc2bc1db6d00e153b95ac7006f4573e289e9be" + integrity sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -688,6 +694,13 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@loaderkit/resolve@^1.0.2": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@loaderkit/resolve/-/resolve-1.0.6.tgz#8d45341e688faecc25b3ae919c0f45d94c4e26c9" + integrity sha512-G8FdIoF5CypfwmD9rl8BXod5HDn8JqB0CCNBXDTaRZ+yRYhARrrSToX1zg1zy9jX3zLqigsELwhT4gNtkdQAUg== + dependencies: + "@braidai/lang" "^1.0.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1696,10 +1709,10 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fflate@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" - integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== +fflate@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.3.tgz#bc27d8eb30343d4d512abb03480202ce65d825fc" + integrity sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA== file-entry-cache@^8.0.0: version "8.0.0" @@ -2490,10 +2503,10 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lru-cache@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.0.1: + version "11.5.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.5.2.tgz#00e16665c90c620fba14a3c368732a976493f760" + integrity sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g== lru-cache@^5.1.1: version "5.1.1" From 3fb50e4df4f25439d3b11f516b43ef4dfcb9b456 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:14:28 +0000 Subject: [PATCH 107/118] feat(stlc): configurable CI runner and private-production-repo support in workflow templates --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0579bd7..a15001b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -37,7 +37,7 @@ jobs: build: timeout-minutes: 5 name: build - runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') permissions: contents: read @@ -77,7 +77,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/unlayer-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From 75258de0f000740913fda85b504bddc04636999a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:12:56 +0000 Subject: [PATCH 108/118] feat(api): api update --- .stats.yml | 8 +-- api.md | 22 +++++++ src/client.ts | 18 ++++++ src/resources/editor-sessions.ts | 58 ++++++++++++++++++ src/resources/index.ts | 6 ++ src/resources/me.ts | 3 + src/resources/me/index.ts | 8 +++ src/resources/me/me.ts | 19 ++++++ src/resources/me/subscription.ts | 67 +++++++++++++++++++++ tests/api-resources/editor-sessions.test.ts | 29 +++++++++ tests/api-resources/me/subscription.test.ts | 28 +++++++++ 11 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 src/resources/editor-sessions.ts create mode 100644 src/resources/me.ts create mode 100644 src/resources/me/index.ts create mode 100644 src/resources/me/me.ts create mode 100644 src/resources/me/subscription.ts create mode 100644 tests/api-resources/editor-sessions.test.ts create mode 100644 tests/api-resources/me/subscription.test.ts diff --git a/.stats.yml b/.stats.yml index 2e4bbbe..61fd7e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-8f62b635191810fa318afdeaabbbb0276b0e1f85f18b5ff2ddaad9a18241f047.yml -openapi_spec_hash: e80a61e80827f2a822db46f4ba82c15d -config_hash: 2949daec69cb6f5d34ae232544245952 +configured_endpoints: 16 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-bccf7c265777474ad23af36d8613e0c738575733ba2335e42129def19d09c021.yml +openapi_spec_hash: 28687f1755511828bc8323d621eba251 +config_hash: de0fdd9f4e2afbb6886dfabb1e7306fa diff --git a/api.md b/api.md index 95b16ff..10cecef 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,25 @@ +# EditorSessions + +Types: + +- EditorSessionCreateResponse + +Methods: + +- client.editorSessions.create({ ...params }) -> EditorSessionCreateResponse + +# Me + +## Subscription + +Types: + +- SubscriptionRetrieveResponse + +Methods: + +- client.me.subscription.retrieve({ ...params }) -> SubscriptionRetrieveResponse + # Projects Types: diff --git a/src/client.ts b/src/client.ts index ad86390..60c6975 100644 --- a/src/client.ts +++ b/src/client.ts @@ -19,8 +19,14 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { + EditorSessionCreateParams, + EditorSessionCreateResponse, + EditorSessions, +} from './resources/editor-sessions'; import { ProjectRetrieveResponse, Projects } from './resources/projects'; import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; +import { Me } from './resources/me/me'; import { TemplateListParams, TemplateListResponse, @@ -820,6 +826,8 @@ export class Unlayer { static toFile = Uploads.toFile; + editorSessions: API.EditorSessions = new API.EditorSessions(this); + me: API.Me = new API.Me(this); /** * Project details and configuration. */ @@ -834,6 +842,8 @@ export class Unlayer { workspaces: API.Workspaces = new API.Workspaces(this); } +Unlayer.EditorSessions = EditorSessions; +Unlayer.Me = Me; Unlayer.Projects = Projects; Unlayer.Templates = Templates; Unlayer.Workspaces = Workspaces; @@ -844,6 +854,14 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { + EditorSessions as EditorSessions, + type EditorSessionCreateResponse as EditorSessionCreateResponse, + type EditorSessionCreateParams as EditorSessionCreateParams, + }; + + export { Me as Me }; + export { Projects as Projects, type ProjectRetrieveResponse as ProjectRetrieveResponse }; export { diff --git a/src/resources/editor-sessions.ts b/src/resources/editor-sessions.ts new file mode 100644 index 0000000..dd297aa --- /dev/null +++ b/src/resources/editor-sessions.ts @@ -0,0 +1,58 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class EditorSessions extends APIResource { + /** + * Create an ephemeral, no-DB editor session for a design and return a hosted + * editor URL the user can open to edit it in the real Unlayer editor. + */ + create( + params: EditorSessionCreateParams, + options?: RequestOptions, + ): APIPromise { + const { projectId, ...body } = params; + return this._client.post('/v3/editor-sessions', { query: { projectId }, body, ...options }); + } +} + +export interface EditorSessionCreateResponse { + data?: EditorSessionCreateResponse.Data; +} + +export namespace EditorSessionCreateResponse { + export interface Data { + token?: string; + + editorUrl?: string; + + expiresAt?: string; + } +} + +export interface EditorSessionCreateParams { + /** + * Body param: Design JSON to load into the editor. + */ + design: { [key: string]: unknown }; + + /** + * Query param: The project ID (required for PAT auth, auto-resolved for API key + * auth) + */ + projectId?: string; + + /** + * Body param: Editor display mode. Defaults to email. + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; +} + +export declare namespace EditorSessions { + export { + type EditorSessionCreateResponse as EditorSessionCreateResponse, + type EditorSessionCreateParams as EditorSessionCreateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 6ca716c..8b2cd41 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,5 +1,11 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { + EditorSessions, + type EditorSessionCreateResponse, + type EditorSessionCreateParams, +} from './editor-sessions'; +export { Me } from './me/me'; export { Projects, type ProjectRetrieveResponse } from './projects'; export { Templates, diff --git a/src/resources/me.ts b/src/resources/me.ts new file mode 100644 index 0000000..54b12df --- /dev/null +++ b/src/resources/me.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './me/index'; diff --git a/src/resources/me/index.ts b/src/resources/me/index.ts new file mode 100644 index 0000000..f62121d --- /dev/null +++ b/src/resources/me/index.ts @@ -0,0 +1,8 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Me } from './me'; +export { + Subscription, + type SubscriptionRetrieveResponse, + type SubscriptionRetrieveParams, +} from './subscription'; diff --git a/src/resources/me/me.ts b/src/resources/me/me.ts new file mode 100644 index 0000000..5a001fe --- /dev/null +++ b/src/resources/me/me.ts @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as SubscriptionAPI from './subscription'; +import { Subscription, SubscriptionRetrieveParams, SubscriptionRetrieveResponse } from './subscription'; + +export class Me extends APIResource { + subscription: SubscriptionAPI.Subscription = new SubscriptionAPI.Subscription(this._client); +} + +Me.Subscription = Subscription; + +export declare namespace Me { + export { + Subscription as Subscription, + type SubscriptionRetrieveResponse as SubscriptionRetrieveResponse, + type SubscriptionRetrieveParams as SubscriptionRetrieveParams, + }; +} diff --git a/src/resources/me/subscription.ts b/src/resources/me/subscription.ts new file mode 100644 index 0000000..bac4e56 --- /dev/null +++ b/src/resources/me/subscription.ts @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Subscription extends APIResource { + /** + * Get the current plan, feature availability, and limits for a project. Used to + * answer "can I do X" / "what plan do I need" questions with ground-truth data + * instead of guessing. + */ + retrieve( + query: SubscriptionRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/me/subscription', { query, ...options }); + } +} + +export interface SubscriptionRetrieveResponse { + data?: SubscriptionRetrieveResponse.Data; +} + +export namespace SubscriptionRetrieveResponse { + export interface Data { + expiresAt?: string | null; + + features?: Array; + + limits?: Array; + + planName?: string | null; + + status?: string | null; + } + + export namespace Data { + export interface Feature { + available?: boolean; + + name?: string; + } + + export interface Limit { + name?: string; + + unit?: string; + + value?: number; + } + } +} + +export interface SubscriptionRetrieveParams { + /** + * The project ID (required for PAT auth, auto-resolved for API key auth) + */ + projectId?: string; +} + +export declare namespace Subscription { + export { + type SubscriptionRetrieveResponse as SubscriptionRetrieveResponse, + type SubscriptionRetrieveParams as SubscriptionRetrieveParams, + }; +} diff --git a/tests/api-resources/editor-sessions.test.ts b/tests/api-resources/editor-sessions.test.ts new file mode 100644 index 0000000..aaea1a4 --- /dev/null +++ b/tests/api-resources/editor-sessions.test.ts @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource editorSessions', () => { + test('create: only required params', async () => { + const responsePromise = client.editorSessions.create({ design: { foo: 'bar' } }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.editorSessions.create({ + design: { foo: 'bar' }, + projectId: 'projectId', + displayMode: 'email', + }); + }); +}); diff --git a/tests/api-resources/me/subscription.test.ts b/tests/api-resources/me/subscription.test.ts new file mode 100644 index 0000000..6898f7c --- /dev/null +++ b/tests/api-resources/me/subscription.test.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource subscription', () => { + test('retrieve', async () => { + const responsePromise = client.me.subscription.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.me.subscription.retrieve({ projectId: 'projectId' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); From 29db7f565529f7a9aca2dd06b7fe0500ab6b0ae0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 07:55:57 +0000 Subject: [PATCH 109/118] feat(api): api update --- .stats.yml | 4 ++-- src/resources/templates/export-html.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 61fd7e3..b7f1d1a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-bccf7c265777474ad23af36d8613e0c738575733ba2335e42129def19d09c021.yml -openapi_spec_hash: 28687f1755511828bc8323d621eba251 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-aa551455ecbd91da3298aa03a688686374e19650fb3fce54f437fb4086eef3ba.yml +openapi_spec_hash: c44982974f0272a5fa34de8b2d8d759d config_hash: de0fdd9f4e2afbb6886dfabb1e7306fa diff --git a/src/resources/templates/export-html.ts b/src/resources/templates/export-html.ts index a6329af..7803e53 100644 --- a/src/resources/templates/export-html.ts +++ b/src/resources/templates/export-html.ts @@ -22,8 +22,12 @@ export interface ExportHTMLCreateResponse { export namespace ExportHTMLCreateResponse { export interface Data { + amp?: { [key: string]: unknown }; + chunks?: Data.Chunks; + design?: { [key: string]: unknown }; + html?: string; } @@ -36,6 +40,8 @@ export namespace ExportHTMLCreateResponse { fonts?: Array; js?: string; + + tags?: Array; } } } From 859f7066ebc312a0ab21531b8f1ef940ecc41c87 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:25:13 +0000 Subject: [PATCH 110/118] feat(api): api update --- .stats.yml | 8 +- api.md | 76 ++++++++- src/client.ts | 2 +- src/resources/index.ts | 2 +- src/resources/projects.ts | 59 +------ .../ai-credits-settings-rotate-secret.ts | 31 ++++ src/resources/projects/ai-credits-settings.ts | 85 ++++++++++ src/resources/projects/ai-credits-usage.ts | 109 ++++++++++++ .../ai-credits-webhooks-deliveries.ts | 84 ++++++++++ .../ai-credits-webhooks-deliveriesattempts.ts | 73 ++++++++ .../ai-credits-webhooks-deliveriesretry.ts | 46 +++++ src/resources/projects/ai-credits.ts | 47 ++++++ src/resources/projects/index.ts | 34 ++++ src/resources/projects/projects.ts | 158 ++++++++++++++++++ .../ai-credits-settings-rotate-secret.test.ts | 21 +++ .../projects/ai-credits-settings.test.ts | 47 ++++++ .../projects/ai-credits-usage.test.ts | 41 +++++ .../ai-credits-webhooks-deliveries.test.ts | 37 ++++ ...redits-webhooks-deliveriesattempts.test.ts | 31 ++++ ...i-credits-webhooks-deliveriesretry.test.ts | 29 ++++ .../api-resources/projects/ai-credits.test.ts | 21 +++ .../{ => projects}/projects.test.ts | 0 22 files changed, 975 insertions(+), 66 deletions(-) create mode 100644 src/resources/projects/ai-credits-settings-rotate-secret.ts create mode 100644 src/resources/projects/ai-credits-settings.ts create mode 100644 src/resources/projects/ai-credits-usage.ts create mode 100644 src/resources/projects/ai-credits-webhooks-deliveries.ts create mode 100644 src/resources/projects/ai-credits-webhooks-deliveriesattempts.ts create mode 100644 src/resources/projects/ai-credits-webhooks-deliveriesretry.ts create mode 100644 src/resources/projects/ai-credits.ts create mode 100644 src/resources/projects/index.ts create mode 100644 src/resources/projects/projects.ts create mode 100644 tests/api-resources/projects/ai-credits-settings-rotate-secret.test.ts create mode 100644 tests/api-resources/projects/ai-credits-settings.test.ts create mode 100644 tests/api-resources/projects/ai-credits-usage.test.ts create mode 100644 tests/api-resources/projects/ai-credits-webhooks-deliveries.test.ts create mode 100644 tests/api-resources/projects/ai-credits-webhooks-deliveriesattempts.test.ts create mode 100644 tests/api-resources/projects/ai-credits-webhooks-deliveriesretry.test.ts create mode 100644 tests/api-resources/projects/ai-credits.test.ts rename tests/api-resources/{ => projects}/projects.test.ts (100%) diff --git a/.stats.yml b/.stats.yml index b7f1d1a..568730e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-aa551455ecbd91da3298aa03a688686374e19650fb3fce54f437fb4086eef3ba.yml -openapi_spec_hash: c44982974f0272a5fa34de8b2d8d759d -config_hash: de0fdd9f4e2afbb6886dfabb1e7306fa +configured_endpoints: 24 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-b42187e1b2fff52630a33946829067dcc76dd842a7fb85d826ee9ccc4f44175d.yml +openapi_spec_hash: 7f0c95f3bb404716e0a77878c0c21b91 +config_hash: ee438ad5d5e9b8446d21fc7cb50eff95 diff --git a/api.md b/api.md index 10cecef..b795cb7 100644 --- a/api.md +++ b/api.md @@ -24,11 +24,83 @@ Methods: Types: -- ProjectRetrieveResponse +- ProjectRetrieveResponse Methods: -- client.projects.retrieve(id) -> ProjectRetrieveResponse +- client.projects.retrieve(id) -> ProjectRetrieveResponse + +## AICredits + +Types: + +- AICreditRetrieveResponse + +Methods: + +- client.projects.aiCredits.retrieve(id) -> AICreditRetrieveResponse + +## AICreditsSettings + +Types: + +- AICreditsSettingRetrieveResponse +- AICreditsSettingUpdateResponse + +Methods: + +- client.projects.aiCreditsSettings.retrieve(id) -> AICreditsSettingRetrieveResponse +- client.projects.aiCreditsSettings.update(id, { ...params }) -> AICreditsSettingUpdateResponse + +## AICreditsSettingsRotateSecret + +Types: + +- AICreditsSettingsRotateSecretCreateResponse + +Methods: + +- client.projects.aiCreditsSettingsRotateSecret.create(id) -> AICreditsSettingsRotateSecretCreateResponse + +## AICreditsUsage + +Types: + +- AICreditsUsageRetrieveResponse + +Methods: + +- client.projects.aiCreditsUsage.retrieve(id, { ...params }) -> AICreditsUsageRetrieveResponse + +## AICreditsWebhooksDeliveries + +Types: + +- AICreditsWebhooksDeliveryRetrieveResponse + +Methods: + +- client.projects.aiCreditsWebhooksDeliveries.retrieve(id, { ...params }) -> AICreditsWebhooksDeliveryRetrieveResponse + +## AICreditsWebhooksDeliveriesattempts + +Types: + +- AICreditsWebhooksDeliveriesattemptRetrieveResponse + +Methods: + +- client.projects.aiCreditsWebhooksDeliveriesattempts.retrieve(deliveryID, { ...params }) -> AICreditsWebhooksDeliveriesattemptRetrieveResponse + +## AICreditsWebhooksDeliveriesretry + +Types: + +- AICreditsWebhooksDeliveriesretryCreateResponse + +Methods: + +- client.projects.aiCreditsWebhooksDeliveriesretry.create(deliveryID, { ...params }) -> AICreditsWebhooksDeliveriesretryCreateResponse # Templates diff --git a/src/client.ts b/src/client.ts index 60c6975..5440607 100644 --- a/src/client.ts +++ b/src/client.ts @@ -24,9 +24,9 @@ import { EditorSessionCreateResponse, EditorSessions, } from './resources/editor-sessions'; -import { ProjectRetrieveResponse, Projects } from './resources/projects'; import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; import { Me } from './resources/me/me'; +import { ProjectRetrieveResponse, Projects } from './resources/projects/projects'; import { TemplateListParams, TemplateListResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index 8b2cd41..c4ba5a4 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -6,7 +6,7 @@ export { type EditorSessionCreateParams, } from './editor-sessions'; export { Me } from './me/me'; -export { Projects, type ProjectRetrieveResponse } from './projects'; +export { Projects, type ProjectRetrieveResponse } from './projects/projects'; export { Templates, type TemplateRetrieveResponse, diff --git a/src/resources/projects.ts b/src/resources/projects.ts index 0d15122..f9985fc 100644 --- a/src/resources/projects.ts +++ b/src/resources/projects.ts @@ -1,60 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; - -/** - * Project details and configuration. - */ -export class Projects extends APIResource { - /** - * Get project details by ID. - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/v3/projects/${id}`, options); - } -} - -export interface ProjectRetrieveResponse { - data?: ProjectRetrieveResponse.Data; -} - -export namespace ProjectRetrieveResponse { - export interface Data { - /** - * The project ID. - */ - id?: number; - - /** - * When the project was created. - */ - createdAt?: string; - - /** - * The project name. - */ - name?: string; - - /** - * The project status. - */ - status?: string; - - workspace?: Data.Workspace; - } - - export namespace Data { - export interface Workspace { - id?: number; - - name?: string; - } - } -} - -export declare namespace Projects { - export { type ProjectRetrieveResponse as ProjectRetrieveResponse }; -} +export * from './projects/index'; diff --git a/src/resources/projects/ai-credits-settings-rotate-secret.ts b/src/resources/projects/ai-credits-settings-rotate-secret.ts new file mode 100644 index 0000000..b23ff6d --- /dev/null +++ b/src/resources/projects/ai-credits-settings-rotate-secret.ts @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsSettingsRotateSecret extends APIResource { + /** + * Generates a new HMAC signing secret for the project and returns it exactly once. + * The previous secret stops working immediately, so update your webhook + * verification before rotating. Requires a webhook URL to be configured first. + */ + create(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v3/projects/${id}/ai-credits/settings/rotate-secret`, options); + } +} + +export interface AICreditsSettingsRotateSecretCreateResponse { + /** + * The new HMAC signing secret. Shown only once. + */ + signing_secret?: string; +} + +export declare namespace AICreditsSettingsRotateSecret { + export { type AICreditsSettingsRotateSecretCreateResponse as AICreditsSettingsRotateSecretCreateResponse }; +} diff --git a/src/resources/projects/ai-credits-settings.ts b/src/resources/projects/ai-credits-settings.ts new file mode 100644 index 0000000..d6bc6ef --- /dev/null +++ b/src/resources/projects/ai-credits-settings.ts @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsSettings extends APIResource { + /** + * Returns a project's AI credit exhaustion behavior, alert thresholds, and webhook + * endpoint. The signing secret is never returned — only whether one exists + * (`has_signing_secret`). + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/projects/${id}/ai-credits/settings`, options); + } + + /** + * Configures AI credit exhaustion behavior, usage alert thresholds, and the + * webhook endpoint for a project. The HMAC signing secret is generated the first + * time a webhook URL is set and returned exactly once in the response — store it + * securely; it is never shown again. + */ + update( + id: string, + body: AICreditsSettingUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/v3/projects/${id}/ai-credits/settings`, { body, ...options }); + } +} + +export interface AICreditsSettingRetrieveResponse { + exhaustion_behavior?: string; + + has_signing_secret?: boolean; + + threshold_alerts?: Array; + + webhook_url?: string | null; +} + +export interface AICreditsSettingUpdateResponse { + exhaustion_behavior?: string; + + has_signing_secret?: boolean; + + /** + * The HMAC signing secret. Returned ONLY on the response that first generates it. + */ + signing_secret?: string; + + threshold_alerts?: Array; + + webhook_url?: string | null; +} + +export interface AICreditsSettingUpdateParams { + /** + * What the editor does when the credit balance is exhausted. + */ + exhaustion_behavior?: 'disable' | 'show_error'; + + /** + * Usage percentages (1-100) at which a threshold_reached webhook fires, once per + * crossing per period. + */ + threshold_alerts?: Array; + + /** + * HTTPS endpoint that receives AI credit webhooks. + */ + webhook_url?: string | null; +} + +export declare namespace AICreditsSettings { + export { + type AICreditsSettingRetrieveResponse as AICreditsSettingRetrieveResponse, + type AICreditsSettingUpdateResponse as AICreditsSettingUpdateResponse, + type AICreditsSettingUpdateParams as AICreditsSettingUpdateParams, + }; +} diff --git a/src/resources/projects/ai-credits-usage.ts b/src/resources/projects/ai-credits-usage.ts new file mode 100644 index 0000000..38bec77 --- /dev/null +++ b/src/resources/projects/ai-credits-usage.ts @@ -0,0 +1,109 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsUsage extends APIResource { + /** + * Returns AI credit consumption for the project, broken down by end user and + * feature type. Filterable by date range, end user, and feature type. Defaults to + * the current billing period. Only credit counts are returned; token counts, model + * names, and costs are never exposed. Per-end-user attribution requires the + * partner to pass `endUserId` on editor initialization. + */ + retrieve( + id: string, + query: AICreditsUsageRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/v3/projects/${id}/ai-credits/usage`, { query, ...options }); + } +} + +export interface AICreditsUsageRetrieveResponse { + breakdown?: Array; + + /** + * Number of breakdown rows matching the filter (ignores paging). + */ + total?: number; + + /** + * Total AI credits used across the full filtered range (not just the returned + * page). + */ + total_credits_used?: number; +} + +export namespace AICreditsUsageRetrieveResponse { + export interface Breakdown { + /** + * AI credits used by this end user and feature type. + */ + credits?: number; + + /** + * The end user id, or null for unattributed usage. + */ + end_user_id?: string | null; + + /** + * The partner-facing feature type. + */ + feature_type?: 'full_template_gen' | 'block_edit' | 'html_import' | 'image_import' | 'image_generation'; + } +} + +export interface AICreditsUsageRetrieveParams { + /** + * End date (inclusive), YYYY-MM-DD. + */ + end?: string; + + /** + * Filter to a single end user id. + */ + end_user_id?: string; + + /** + * Filter to a single feature type. + */ + feature_type?: 'full_template_gen' | 'block_edit' | 'html_import' | 'image_import' | 'image_generation'; + + /** + * Max breakdown rows to return (1-1000). + */ + limit?: number; + + /** + * Number of breakdown rows to skip (pagination). + */ + offset?: number; + + /** + * Sort direction. Defaults to desc (highest credits first). + */ + order?: 'asc' | 'desc'; + + /** + * Field the breakdown is ordered by. Defaults to credits. + */ + sort?: 'credits' | 'end_user_id' | 'feature_type'; + + /** + * Start date (inclusive), YYYY-MM-DD. + */ + start?: string; +} + +export declare namespace AICreditsUsage { + export { + type AICreditsUsageRetrieveResponse as AICreditsUsageRetrieveResponse, + type AICreditsUsageRetrieveParams as AICreditsUsageRetrieveParams, + }; +} diff --git a/src/resources/projects/ai-credits-webhooks-deliveries.ts b/src/resources/projects/ai-credits-webhooks-deliveries.ts new file mode 100644 index 0000000..7202cf1 --- /dev/null +++ b/src/resources/projects/ai-credits-webhooks-deliveries.ts @@ -0,0 +1,84 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsWebhooksDeliveries extends APIResource { + /** + * Returns the webhook delivery history for the project, newest first — the event, + * delivery status, attempt count, and last response code for each. Use it to spot + * failed deliveries and drive the retry endpoint. Payloads expose credits only. + */ + retrieve( + id: string, + query: AICreditsWebhooksDeliveryRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/v3/projects/${id}/ai-credits/webhooks/deliveries`, { query, ...options }); + } +} + +export interface AICreditsWebhooksDeliveryRetrieveResponse { + deliveries?: Array; + + /** + * Total deliveries matching the filter (ignores limit/offset). + */ + total?: number; +} + +export namespace AICreditsWebhooksDeliveryRetrieveResponse { + export interface Delivery { + id?: string; + + attempts?: number; + + created_at?: string; + + delivered_at?: string | null; + + end_user_id?: string | null; + + event?: string; + + last_status_code?: number | null; + + payload?: { [key: string]: unknown }; + + status?: 'pending' | 'delivered' | 'failed'; + } +} + +export interface AICreditsWebhooksDeliveryRetrieveParams { + /** + * Filter to a single event type. + */ + event?: 'ai.credits.usage_recorded' | 'ai.credits.threshold_reached' | 'ai.credits.exhausted'; + + /** + * Max deliveries to return (1-100). + */ + limit?: number; + + /** + * Number of deliveries to skip (pagination). + */ + offset?: number; + + /** + * Filter to a single delivery status. + */ + status?: 'pending' | 'delivered' | 'failed'; +} + +export declare namespace AICreditsWebhooksDeliveries { + export { + type AICreditsWebhooksDeliveryRetrieveResponse as AICreditsWebhooksDeliveryRetrieveResponse, + type AICreditsWebhooksDeliveryRetrieveParams as AICreditsWebhooksDeliveryRetrieveParams, + }; +} diff --git a/src/resources/projects/ai-credits-webhooks-deliveriesattempts.ts b/src/resources/projects/ai-credits-webhooks-deliveriesattempts.ts new file mode 100644 index 0000000..7605382 --- /dev/null +++ b/src/resources/projects/ai-credits-webhooks-deliveriesattempts.ts @@ -0,0 +1,73 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsWebhooksDeliveriesattempts extends APIResource { + /** + * Returns the per-attempt history for a single delivery, newest attempt first — + * the response code, error, and time of each POST (including automatic retries). + * Returns 404 if the delivery is not found for this project. + */ + retrieve( + deliveryID: string, + params: AICreditsWebhooksDeliveriesattemptRetrieveParams, + options?: RequestOptions, + ): APIPromise { + const { id, ...query } = params; + return this._client.get(path`/v3/projects/${id}/ai-credits/webhooks/deliveries/${deliveryID}/attempts`, { + query, + ...options, + }); + } +} + +export interface AICreditsWebhooksDeliveriesattemptRetrieveResponse { + attempts?: Array; + + /** + * Total attempts for the delivery (ignores limit/offset). + */ + total?: number; +} + +export namespace AICreditsWebhooksDeliveriesattemptRetrieveResponse { + export interface Attempt { + attempt?: number; + + attempted_at?: string; + + error?: string | null; + + status_code?: number | null; + } +} + +export interface AICreditsWebhooksDeliveriesattemptRetrieveParams { + /** + * Path param: The project ID + */ + id: string; + + /** + * Query param: Max attempts to return (1-100). + */ + limit?: number; + + /** + * Query param: Number of attempts to skip (pagination). + */ + offset?: number; +} + +export declare namespace AICreditsWebhooksDeliveriesattempts { + export { + type AICreditsWebhooksDeliveriesattemptRetrieveResponse as AICreditsWebhooksDeliveriesattemptRetrieveResponse, + type AICreditsWebhooksDeliveriesattemptRetrieveParams as AICreditsWebhooksDeliveriesattemptRetrieveParams, + }; +} diff --git a/src/resources/projects/ai-credits-webhooks-deliveriesretry.ts b/src/resources/projects/ai-credits-webhooks-deliveriesretry.ts new file mode 100644 index 0000000..931522d --- /dev/null +++ b/src/resources/projects/ai-credits-webhooks-deliveriesretry.ts @@ -0,0 +1,46 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICreditsWebhooksDeliveriesretry extends APIResource { + /** + * Re-queues a single previously-failed (or pending) webhook delivery for another + * attempt. Returns 404 if the delivery is not found for this project, and 409 if + * it was already delivered. + */ + create( + deliveryID: string, + params: AICreditsWebhooksDeliveriesretryCreateParams, + options?: RequestOptions, + ): APIPromise { + const { id } = params; + return this._client.post( + path`/v3/projects/${id}/ai-credits/webhooks/deliveries/${deliveryID}/retry`, + options, + ); + } +} + +export interface AICreditsWebhooksDeliveriesretryCreateResponse { + status?: 'requeued'; +} + +export interface AICreditsWebhooksDeliveriesretryCreateParams { + /** + * The project ID + */ + id: string; +} + +export declare namespace AICreditsWebhooksDeliveriesretry { + export { + type AICreditsWebhooksDeliveriesretryCreateResponse as AICreditsWebhooksDeliveriesretryCreateResponse, + type AICreditsWebhooksDeliveriesretryCreateParams as AICreditsWebhooksDeliveriesretryCreateParams, + }; +} diff --git a/src/resources/projects/ai-credits.ts b/src/resources/projects/ai-credits.ts new file mode 100644 index 0000000..1c2d220 --- /dev/null +++ b/src/resources/projects/ai-credits.ts @@ -0,0 +1,47 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * AI credit balance, usage breakdown, and webhook/alert settings. Credits are pooled per workspace; settings are per project. + */ +export class AICredits extends APIResource { + /** + * Returns the current AI credit balance for the project. Credits are pooled per + * workspace — every project in a workspace shares one balance. Only credit counts + * are returned; token counts, model names, and costs are never exposed. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/projects/${id}/ai-credits`, options); + } +} + +export interface AICreditRetrieveResponse { + /** + * AI credits remaining in the current period. + */ + credits_remaining?: number; + + /** + * Total AI credits available for the current period. + */ + credits_total?: number; + + /** + * AI credits consumed so far in the current period. + */ + credits_used?: number; + + /** + * When the current credit period resets, or null if there is no active billing + * period — including once a subscription is cancelled or its term has ended. + */ + reset_date?: string | null; +} + +export declare namespace AICredits { + export { type AICreditRetrieveResponse as AICreditRetrieveResponse }; +} diff --git a/src/resources/projects/index.ts b/src/resources/projects/index.ts new file mode 100644 index 0000000..5a8e575 --- /dev/null +++ b/src/resources/projects/index.ts @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { AICredits, type AICreditRetrieveResponse } from './ai-credits'; +export { + AICreditsSettings, + type AICreditsSettingRetrieveResponse, + type AICreditsSettingUpdateResponse, + type AICreditsSettingUpdateParams, +} from './ai-credits-settings'; +export { + AICreditsSettingsRotateSecret, + type AICreditsSettingsRotateSecretCreateResponse, +} from './ai-credits-settings-rotate-secret'; +export { + AICreditsUsage, + type AICreditsUsageRetrieveResponse, + type AICreditsUsageRetrieveParams, +} from './ai-credits-usage'; +export { + AICreditsWebhooksDeliveries, + type AICreditsWebhooksDeliveryRetrieveResponse, + type AICreditsWebhooksDeliveryRetrieveParams, +} from './ai-credits-webhooks-deliveries'; +export { + AICreditsWebhooksDeliveriesattempts, + type AICreditsWebhooksDeliveriesattemptRetrieveResponse, + type AICreditsWebhooksDeliveriesattemptRetrieveParams, +} from './ai-credits-webhooks-deliveriesattempts'; +export { + AICreditsWebhooksDeliveriesretry, + type AICreditsWebhooksDeliveriesretryCreateResponse, + type AICreditsWebhooksDeliveriesretryCreateParams, +} from './ai-credits-webhooks-deliveriesretry'; +export { Projects, type ProjectRetrieveResponse } from './projects'; diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts new file mode 100644 index 0000000..2a5de9e --- /dev/null +++ b/src/resources/projects/projects.ts @@ -0,0 +1,158 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as AICreditsAPI from './ai-credits'; +import { AICreditRetrieveResponse, AICredits } from './ai-credits'; +import * as AICreditsSettingsAPI from './ai-credits-settings'; +import { + AICreditsSettingRetrieveResponse, + AICreditsSettingUpdateParams, + AICreditsSettingUpdateResponse, + AICreditsSettings, +} from './ai-credits-settings'; +import * as AICreditsSettingsRotateSecretAPI from './ai-credits-settings-rotate-secret'; +import { + AICreditsSettingsRotateSecret, + AICreditsSettingsRotateSecretCreateResponse, +} from './ai-credits-settings-rotate-secret'; +import * as AICreditsUsageAPI from './ai-credits-usage'; +import { + AICreditsUsage, + AICreditsUsageRetrieveParams, + AICreditsUsageRetrieveResponse, +} from './ai-credits-usage'; +import * as AICreditsWebhooksDeliveriesAPI from './ai-credits-webhooks-deliveries'; +import { + AICreditsWebhooksDeliveries, + AICreditsWebhooksDeliveryRetrieveParams, + AICreditsWebhooksDeliveryRetrieveResponse, +} from './ai-credits-webhooks-deliveries'; +import * as AICreditsWebhooksDeliveriesattemptsAPI from './ai-credits-webhooks-deliveriesattempts'; +import { + AICreditsWebhooksDeliveriesattemptRetrieveParams, + AICreditsWebhooksDeliveriesattemptRetrieveResponse, + AICreditsWebhooksDeliveriesattempts, +} from './ai-credits-webhooks-deliveriesattempts'; +import * as AICreditsWebhooksDeliveriesretryAPI from './ai-credits-webhooks-deliveriesretry'; +import { + AICreditsWebhooksDeliveriesretry, + AICreditsWebhooksDeliveriesretryCreateParams, + AICreditsWebhooksDeliveriesretryCreateResponse, +} from './ai-credits-webhooks-deliveriesretry'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Project details and configuration. + */ +export class Projects extends APIResource { + aiCredits: AICreditsAPI.AICredits = new AICreditsAPI.AICredits(this._client); + aiCreditsSettings: AICreditsSettingsAPI.AICreditsSettings = new AICreditsSettingsAPI.AICreditsSettings( + this._client, + ); + aiCreditsSettingsRotateSecret: AICreditsSettingsRotateSecretAPI.AICreditsSettingsRotateSecret = + new AICreditsSettingsRotateSecretAPI.AICreditsSettingsRotateSecret(this._client); + aiCreditsUsage: AICreditsUsageAPI.AICreditsUsage = new AICreditsUsageAPI.AICreditsUsage(this._client); + aiCreditsWebhooksDeliveries: AICreditsWebhooksDeliveriesAPI.AICreditsWebhooksDeliveries = + new AICreditsWebhooksDeliveriesAPI.AICreditsWebhooksDeliveries(this._client); + aiCreditsWebhooksDeliveriesattempts: AICreditsWebhooksDeliveriesattemptsAPI.AICreditsWebhooksDeliveriesattempts = + new AICreditsWebhooksDeliveriesattemptsAPI.AICreditsWebhooksDeliveriesattempts(this._client); + aiCreditsWebhooksDeliveriesretry: AICreditsWebhooksDeliveriesretryAPI.AICreditsWebhooksDeliveriesretry = + new AICreditsWebhooksDeliveriesretryAPI.AICreditsWebhooksDeliveriesretry(this._client); + + /** + * Get project details by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/projects/${id}`, options); + } +} + +export interface ProjectRetrieveResponse { + data?: ProjectRetrieveResponse.Data; +} + +export namespace ProjectRetrieveResponse { + export interface Data { + /** + * The project ID. + */ + id?: number; + + /** + * When the project was created. + */ + createdAt?: string; + + /** + * The project name. + */ + name?: string; + + /** + * The project status. + */ + status?: string; + + workspace?: Data.Workspace; + } + + export namespace Data { + export interface Workspace { + id?: number; + + name?: string; + } + } +} + +Projects.AICredits = AICredits; +Projects.AICreditsSettings = AICreditsSettings; +Projects.AICreditsSettingsRotateSecret = AICreditsSettingsRotateSecret; +Projects.AICreditsUsage = AICreditsUsage; +Projects.AICreditsWebhooksDeliveries = AICreditsWebhooksDeliveries; +Projects.AICreditsWebhooksDeliveriesattempts = AICreditsWebhooksDeliveriesattempts; +Projects.AICreditsWebhooksDeliveriesretry = AICreditsWebhooksDeliveriesretry; + +export declare namespace Projects { + export { type ProjectRetrieveResponse as ProjectRetrieveResponse }; + + export { AICredits as AICredits, type AICreditRetrieveResponse as AICreditRetrieveResponse }; + + export { + AICreditsSettings as AICreditsSettings, + type AICreditsSettingRetrieveResponse as AICreditsSettingRetrieveResponse, + type AICreditsSettingUpdateResponse as AICreditsSettingUpdateResponse, + type AICreditsSettingUpdateParams as AICreditsSettingUpdateParams, + }; + + export { + AICreditsSettingsRotateSecret as AICreditsSettingsRotateSecret, + type AICreditsSettingsRotateSecretCreateResponse as AICreditsSettingsRotateSecretCreateResponse, + }; + + export { + AICreditsUsage as AICreditsUsage, + type AICreditsUsageRetrieveResponse as AICreditsUsageRetrieveResponse, + type AICreditsUsageRetrieveParams as AICreditsUsageRetrieveParams, + }; + + export { + AICreditsWebhooksDeliveries as AICreditsWebhooksDeliveries, + type AICreditsWebhooksDeliveryRetrieveResponse as AICreditsWebhooksDeliveryRetrieveResponse, + type AICreditsWebhooksDeliveryRetrieveParams as AICreditsWebhooksDeliveryRetrieveParams, + }; + + export { + AICreditsWebhooksDeliveriesattempts as AICreditsWebhooksDeliveriesattempts, + type AICreditsWebhooksDeliveriesattemptRetrieveResponse as AICreditsWebhooksDeliveriesattemptRetrieveResponse, + type AICreditsWebhooksDeliveriesattemptRetrieveParams as AICreditsWebhooksDeliveriesattemptRetrieveParams, + }; + + export { + AICreditsWebhooksDeliveriesretry as AICreditsWebhooksDeliveriesretry, + type AICreditsWebhooksDeliveriesretryCreateResponse as AICreditsWebhooksDeliveriesretryCreateResponse, + type AICreditsWebhooksDeliveriesretryCreateParams as AICreditsWebhooksDeliveriesretryCreateParams, + }; +} diff --git a/tests/api-resources/projects/ai-credits-settings-rotate-secret.test.ts b/tests/api-resources/projects/ai-credits-settings-rotate-secret.test.ts new file mode 100644 index 0000000..bff10b9 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-settings-rotate-secret.test.ts @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsSettingsRotateSecret', () => { + test('create', async () => { + const responsePromise = client.projects.aiCreditsSettingsRotateSecret.create('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/projects/ai-credits-settings.test.ts b/tests/api-resources/projects/ai-credits-settings.test.ts new file mode 100644 index 0000000..a23a269 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-settings.test.ts @@ -0,0 +1,47 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsSettings', () => { + test('retrieve', async () => { + const responsePromise = client.projects.aiCreditsSettings.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update', async () => { + const responsePromise = client.projects.aiCreditsSettings.update('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projects.aiCreditsSettings.update( + 'id', + { + exhaustion_behavior: 'disable', + threshold_alerts: [1], + webhook_url: 'https://example.com', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/projects/ai-credits-usage.test.ts b/tests/api-resources/projects/ai-credits-usage.test.ts new file mode 100644 index 0000000..58cde36 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-usage.test.ts @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsUsage', () => { + test('retrieve', async () => { + const responsePromise = client.projects.aiCreditsUsage.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projects.aiCreditsUsage.retrieve( + 'id', + { + end: '7321-69-10', + end_user_id: 'end_user_id', + feature_type: 'full_template_gen', + limit: 1, + offset: 0, + order: 'asc', + sort: 'credits', + start: '7321-69-10', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/projects/ai-credits-webhooks-deliveries.test.ts b/tests/api-resources/projects/ai-credits-webhooks-deliveries.test.ts new file mode 100644 index 0000000..17178f1 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-webhooks-deliveries.test.ts @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsWebhooksDeliveries', () => { + test('retrieve', async () => { + const responsePromise = client.projects.aiCreditsWebhooksDeliveries.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.projects.aiCreditsWebhooksDeliveries.retrieve( + 'id', + { + event: 'ai.credits.usage_recorded', + limit: 1, + offset: 0, + status: 'pending', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/projects/ai-credits-webhooks-deliveriesattempts.test.ts b/tests/api-resources/projects/ai-credits-webhooks-deliveriesattempts.test.ts new file mode 100644 index 0000000..bacd5f8 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-webhooks-deliveriesattempts.test.ts @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsWebhooksDeliveriesattempts', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.projects.aiCreditsWebhooksDeliveriesattempts.retrieve('deliveryId', { + id: 'id', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.projects.aiCreditsWebhooksDeliveriesattempts.retrieve('deliveryId', { + id: 'id', + limit: 1, + offset: 0, + }); + }); +}); diff --git a/tests/api-resources/projects/ai-credits-webhooks-deliveriesretry.test.ts b/tests/api-resources/projects/ai-credits-webhooks-deliveriesretry.test.ts new file mode 100644 index 0000000..2c1e805 --- /dev/null +++ b/tests/api-resources/projects/ai-credits-webhooks-deliveriesretry.test.ts @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCreditsWebhooksDeliveriesretry', () => { + test('create: only required params', async () => { + const responsePromise = client.projects.aiCreditsWebhooksDeliveriesretry.create('deliveryId', { + id: 'id', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.projects.aiCreditsWebhooksDeliveriesretry.create('deliveryId', { + id: 'id', + }); + }); +}); diff --git a/tests/api-resources/projects/ai-credits.test.ts b/tests/api-resources/projects/ai-credits.test.ts new file mode 100644 index 0000000..377cc15 --- /dev/null +++ b/tests/api-resources/projects/ai-credits.test.ts @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource aiCredits', () => { + test('retrieve', async () => { + const responsePromise = client.projects.aiCredits.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/projects.test.ts b/tests/api-resources/projects/projects.test.ts similarity index 100% rename from tests/api-resources/projects.test.ts rename to tests/api-resources/projects/projects.test.ts From dfc5cbe4a49c6d508efb07d30c53f8061bc3ede1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 12:05:13 +0000 Subject: [PATCH 111/118] feat(api): api update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 443cc05..957aa46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,9 +1228,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2" - integrity sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA== + version "2.1.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.3.tgz#1bf69aacdf6a4380ca17c284d9f928d4aa6401bc" + integrity sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A== dependencies: balanced-match "^1.0.0" From b7cbc7f39da90b79aa4637cd93845351cc34b701 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 02:11:07 +0000 Subject: [PATCH 112/118] fix(stlc): stop hand-edited CI workflows from blocking seals and builds Editing the generated CI/release workflows in an SDK repo is supported: stlc writes them once and then leaves them under the repo's ownership. Two safety checks did not account for that and could refuse to seal custom code, or refuse to build, over workflow edits that were never at risk of being overwritten. The seal refusal could not be cleared by rebuilding. Sealing is also now recorded in place rather than under a new filename each time, so an interrupted build can no longer leave a workspace with no record of its sealed custom code, and sealing one branch no longer discards the record for another. --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 957aa46..f16b683 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,9 +1228,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.3.tgz#1bf69aacdf6a4380ca17c284d9f928d4aa6401bc" - integrity sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A== + version "2.1.4" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.4.tgz#589dab11c0018d0366be64cd8bf12c8dbecc8326" + integrity sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg== dependencies: balanced-match "^1.0.0" From 41920feed154ac4ec17082ef7cd498d33fac0a2d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 2 Aug 2026 08:03:13 +0000 Subject: [PATCH 113/118] feat(api): api update --- .stats.yml | 8 +- api.md | 160 +++++++ src/client.ts | 61 +++ src/resources/domains.ts | 3 + src/resources/domains/domains.ts | 160 +++++++ src/resources/domains/index.ts | 11 + src/resources/domains/verify.ts | 51 +++ src/resources/emails.ts | 3 + src/resources/emails/emails.ts | 414 ++++++++++++++++++ src/resources/emails/events.ts | 38 ++ src/resources/emails/index.ts | 34 ++ src/resources/emails/render.ts | 49 +++ src/resources/emails/settings.ts | 86 ++++ src/resources/emails/stats.ts | 120 +++++ src/resources/emails/suppressions-check.ts | 49 +++ src/resources/emails/suppressions.ts | 126 ++++++ src/resources/emails/template.ts | 201 +++++++++ src/resources/index.ts | 26 ++ .../templates/convert-full-to-simple.ts | 6 + .../templates/convert-simple-to-full.ts | 6 + src/resources/templates/index.ts | 2 + src/resources/templates/schema.ts | 44 ++ src/resources/templates/templates.ts | 16 + src/resources/templates/validate.ts | 132 ++++++ src/resources/webhooks.ts | 3 + src/resources/webhooks/index.ts | 13 + src/resources/webhooks/rotate-secret.ts | 37 ++ src/resources/webhooks/webhooks.ts | 255 +++++++++++ tests/api-resources/domains/domains.test.ts | 58 +++ tests/api-resources/domains/verify.test.ts | 21 + tests/api-resources/emails/emails.test.ts | 90 ++++ tests/api-resources/emails/events.test.ts | 21 + tests/api-resources/emails/render.test.ts | 28 ++ tests/api-resources/emails/settings.test.ts | 42 ++ tests/api-resources/emails/stats.test.ts | 35 ++ .../emails/suppressions-check.test.ts | 28 ++ .../api-resources/emails/suppressions.test.ts | 65 +++ tests/api-resources/emails/template.test.ts | 49 +++ tests/api-resources/templates/schema.test.ts | 31 ++ .../api-resources/templates/validate.test.ts | 40 ++ .../webhooks/rotate-secret.test.ts | 21 + tests/api-resources/webhooks/webhooks.test.ts | 88 ++++ 42 files changed, 2727 insertions(+), 4 deletions(-) create mode 100644 src/resources/domains.ts create mode 100644 src/resources/domains/domains.ts create mode 100644 src/resources/domains/index.ts create mode 100644 src/resources/domains/verify.ts create mode 100644 src/resources/emails.ts create mode 100644 src/resources/emails/emails.ts create mode 100644 src/resources/emails/events.ts create mode 100644 src/resources/emails/index.ts create mode 100644 src/resources/emails/render.ts create mode 100644 src/resources/emails/settings.ts create mode 100644 src/resources/emails/stats.ts create mode 100644 src/resources/emails/suppressions-check.ts create mode 100644 src/resources/emails/suppressions.ts create mode 100644 src/resources/emails/template.ts create mode 100644 src/resources/templates/schema.ts create mode 100644 src/resources/templates/validate.ts create mode 100644 src/resources/webhooks.ts create mode 100644 src/resources/webhooks/index.ts create mode 100644 src/resources/webhooks/rotate-secret.ts create mode 100644 src/resources/webhooks/webhooks.ts create mode 100644 tests/api-resources/domains/domains.test.ts create mode 100644 tests/api-resources/domains/verify.test.ts create mode 100644 tests/api-resources/emails/emails.test.ts create mode 100644 tests/api-resources/emails/events.test.ts create mode 100644 tests/api-resources/emails/render.test.ts create mode 100644 tests/api-resources/emails/settings.test.ts create mode 100644 tests/api-resources/emails/stats.test.ts create mode 100644 tests/api-resources/emails/suppressions-check.test.ts create mode 100644 tests/api-resources/emails/suppressions.test.ts create mode 100644 tests/api-resources/emails/template.test.ts create mode 100644 tests/api-resources/templates/schema.test.ts create mode 100644 tests/api-resources/templates/validate.test.ts create mode 100644 tests/api-resources/webhooks/rotate-secret.test.ts create mode 100644 tests/api-resources/webhooks/webhooks.test.ts diff --git a/.stats.yml b/.stats.yml index 568730e..b5c4710 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-b42187e1b2fff52630a33946829067dcc76dd842a7fb85d826ee9ccc4f44175d.yml -openapi_spec_hash: 7f0c95f3bb404716e0a77878c0c21b91 -config_hash: ee438ad5d5e9b8446d21fc7cb50eff95 +configured_endpoints: 50 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-112356d364a4c9b7cf7f8d272937732568d750f9574ecc0c07516eca112cdddf.yml +openapi_spec_hash: 283e15c9bc02c4d7c69189873b1da9d4 +config_hash: c65b47a2f20400d392a50837c0a10945 diff --git a/api.md b/api.md index b795cb7..66d02c4 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,29 @@ +# Domains + +Types: + +- DomainCreateResponse +- DomainRetrieveResponse +- DomainListResponse +- DomainDeleteResponse + +Methods: + +- client.domains.create({ ...params }) -> DomainCreateResponse +- client.domains.retrieve(id) -> DomainRetrieveResponse +- client.domains.list() -> DomainListResponse +- client.domains.delete(id) -> DomainDeleteResponse + +## Verify + +Types: + +- VerifyCreateResponse + +Methods: + +- client.domains.verify.create(id) -> VerifyCreateResponse + # EditorSessions Types: @@ -8,6 +34,96 @@ Methods: - client.editorSessions.create({ ...params }) -> EditorSessionCreateResponse +# Emails + +Types: + +- EmailCreateResponse +- EmailRetrieveResponse +- EmailListResponse + +Methods: + +- client.emails.create({ ...params }) -> EmailCreateResponse +- client.emails.retrieve(id) -> EmailRetrieveResponse +- client.emails.list({ ...params }) -> EmailListResponse + +## Events + +Types: + +- EventRetrieveResponse + +Methods: + +- client.emails.events.retrieve(id) -> EventRetrieveResponse + +## Render + +Types: + +- RenderCreateResponse + +Methods: + +- client.emails.render.create({ ...params }) -> RenderCreateResponse + +## Settings + +Types: + +- SettingRetrieveResponse +- SettingUpdateResponse + +Methods: + +- client.emails.settings.retrieve() -> SettingRetrieveResponse +- client.emails.settings.update({ ...params }) -> SettingUpdateResponse + +## Stats + +Types: + +- StatRetrieveResponse + +Methods: + +- client.emails.stats.retrieve({ ...params }) -> StatRetrieveResponse + +## Suppressions + +Types: + +- SuppressionCreateResponse +- SuppressionRetrieveResponse +- SuppressionDeleteResponse + +Methods: + +- client.emails.suppressions.create({ ...params }) -> SuppressionCreateResponse +- client.emails.suppressions.retrieve({ ...params }) -> SuppressionRetrieveResponse +- client.emails.suppressions.delete({ ...params }) -> SuppressionDeleteResponse + +## SuppressionsCheck + +Types: + +- SuppressionsCheckRetrieveResponse + +Methods: + +- client.emails.suppressionsCheck.retrieve({ ...params }) -> SuppressionsCheckRetrieveResponse + +## Template + +Types: + +- TemplateCreateResponse + +Methods: + +- client.emails.template.create({ ...params }) -> TemplateCreateResponse + # Me ## Subscription @@ -195,6 +311,50 @@ Methods: - client.templates.import.create({ ...params }) -> ImportCreateResponse +## Schema + +Methods: + +- client.templates.schema.retrieve({ ...params }) -> void + +## Validate + +Types: + +- ValidateCreateResponse + +Methods: + +- client.templates.validate.create({ ...params }) -> ValidateCreateResponse + +# Webhooks + +Types: + +- WebhookCreateResponse +- WebhookRetrieveResponse +- WebhookUpdateResponse +- WebhookListResponse +- WebhookDeleteResponse + +Methods: + +- client.webhooks.create({ ...params }) -> WebhookCreateResponse +- client.webhooks.retrieve(id) -> WebhookRetrieveResponse +- client.webhooks.update(id, { ...params }) -> WebhookUpdateResponse +- client.webhooks.list() -> WebhookListResponse +- client.webhooks.delete(id) -> WebhookDeleteResponse + +## RotateSecret + +Types: + +- RotateSecretCreateResponse + +Methods: + +- client.webhooks.rotateSecret.create(id) -> RotateSecretCreateResponse + # Workspaces Types: diff --git a/src/client.ts b/src/client.ts index 5440607..be8e975 100644 --- a/src/client.ts +++ b/src/client.ts @@ -25,6 +25,22 @@ import { EditorSessions, } from './resources/editor-sessions'; import { WorkspaceListResponse, WorkspaceRetrieveResponse, Workspaces } from './resources/workspaces'; +import { + DomainCreateParams, + DomainCreateResponse, + DomainDeleteResponse, + DomainListResponse, + DomainRetrieveResponse, + Domains, +} from './resources/domains/domains'; +import { + EmailCreateParams, + EmailCreateResponse, + EmailListParams, + EmailListResponse, + EmailRetrieveResponse, + Emails, +} from './resources/emails/emails'; import { Me } from './resources/me/me'; import { ProjectRetrieveResponse, Projects } from './resources/projects/projects'; import { @@ -35,6 +51,16 @@ import { TemplateRetrieveResponse, Templates, } from './resources/templates/templates'; +import { + WebhookCreateParams, + WebhookCreateResponse, + WebhookDeleteResponse, + WebhookListResponse, + WebhookRetrieveResponse, + WebhookUpdateParams, + WebhookUpdateResponse, + Webhooks, +} from './resources/webhooks/webhooks'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -826,7 +852,9 @@ export class Unlayer { static toFile = Uploads.toFile; + domains: API.Domains = new API.Domains(this); editorSessions: API.EditorSessions = new API.EditorSessions(this); + emails: API.Emails = new API.Emails(this); me: API.Me = new API.Me(this); /** * Project details and configuration. @@ -836,16 +864,20 @@ export class Unlayer { * Template management — list, retrieve, generate, import, export, and convert designs. */ templates: API.Templates = new API.Templates(this); + webhooks: API.Webhooks = new API.Webhooks(this); /** * Workspace access and management. */ workspaces: API.Workspaces = new API.Workspaces(this); } +Unlayer.Domains = Domains; Unlayer.EditorSessions = EditorSessions; +Unlayer.Emails = Emails; Unlayer.Me = Me; Unlayer.Projects = Projects; Unlayer.Templates = Templates; +Unlayer.Webhooks = Webhooks; Unlayer.Workspaces = Workspaces; export declare namespace Unlayer { @@ -854,12 +886,30 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { + Domains as Domains, + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainListResponse as DomainListResponse, + type DomainDeleteResponse as DomainDeleteResponse, + type DomainCreateParams as DomainCreateParams, + }; + export { EditorSessions as EditorSessions, type EditorSessionCreateResponse as EditorSessionCreateResponse, type EditorSessionCreateParams as EditorSessionCreateParams, }; + export { + Emails as Emails, + type EmailCreateResponse as EmailCreateResponse, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailListResponse as EmailListResponse, + type EmailCreateParams as EmailCreateParams, + type EmailListParams as EmailListParams, + }; + export { Me as Me }; export { Projects as Projects, type ProjectRetrieveResponse as ProjectRetrieveResponse }; @@ -873,6 +923,17 @@ export declare namespace Unlayer { type TemplateListParams as TemplateListParams, }; + export { + Webhooks as Webhooks, + type WebhookCreateResponse as WebhookCreateResponse, + type WebhookRetrieveResponse as WebhookRetrieveResponse, + type WebhookUpdateResponse as WebhookUpdateResponse, + type WebhookListResponse as WebhookListResponse, + type WebhookDeleteResponse as WebhookDeleteResponse, + type WebhookCreateParams as WebhookCreateParams, + type WebhookUpdateParams as WebhookUpdateParams, + }; + export { Workspaces as Workspaces, type WorkspaceRetrieveResponse as WorkspaceRetrieveResponse, diff --git a/src/resources/domains.ts b/src/resources/domains.ts new file mode 100644 index 0000000..5c8cf7e --- /dev/null +++ b/src/resources/domains.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './domains/index'; diff --git a/src/resources/domains/domains.ts b/src/resources/domains/domains.ts new file mode 100644 index 0000000..bbba212 --- /dev/null +++ b/src/resources/domains/domains.ts @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as VerifyAPI from './verify'; +import { Verify, VerifyCreateResponse } from './verify'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Domains extends APIResource { + verify: VerifyAPI.Verify = new VerifyAPI.Verify(this._client); + + /** + * Register a sender domain shared by every Developer Email API project in the + * workspace. Requires a personal access token belonging to a workspace owner or + * admin. Verification requires the workspace-specific TXT record and the returned + * SES DKIM records. + */ + create(body: DomainCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v3/domains', { body, ...options }); + } + + /** + * Get the ownership TXT challenge and SES DKIM records for a sender domain shared + * by every Developer Email API project in the workspace. Requires a personal + * access token belonging to a workspace owner or admin. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/domains/${id}`, options); + } + + /** + * List sender domains shared by every Developer Email API project in the + * workspace. Requires a personal access token belonging to a workspace owner or + * admin; project API keys cannot manage domains. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v3/domains', options); + } + + /** + * Delete a sender domain shared by every Developer Email API project in the + * workspace. Requires a personal access token belonging to a workspace owner or + * admin. The SES identity remains so a later reconciler can clean it up safely. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v3/domains/${id}`, options); + } +} + +export interface DomainCreateResponse { + data: DomainCreateResponse.Data; +} + +export namespace DomainCreateResponse { + export interface Data { + id?: number; + + createdAt?: string; + + dkimTokens?: Array; + + dnsRecords?: Array; + + domain?: string; + + status?: 'pending' | 'verified' | 'failed'; + } + + export namespace Data { + export interface DNSRecord { + name?: string; + + purpose?: string; + + type?: string; + + value?: string; + } + } +} + +export interface DomainRetrieveResponse { + data: DomainRetrieveResponse.Data; +} + +export namespace DomainRetrieveResponse { + export interface Data { + id?: number; + + createdAt?: string; + + dkimTokens?: Array; + + dnsRecords?: Array; + + domain?: string; + + status?: string; + } + + export namespace Data { + export interface DNSRecord { + name?: string; + + purpose?: string; + + type?: string; + + value?: string; + } + } +} + +export interface DomainListResponse { + data: Array; +} + +export namespace DomainListResponse { + export interface Data { + id?: number; + + createdAt?: string; + + domain?: string; + + status?: 'pending' | 'verified' | 'failed'; + } +} + +export interface DomainDeleteResponse { + data?: DomainDeleteResponse.Data; +} + +export namespace DomainDeleteResponse { + export interface Data { + success?: boolean; + } +} + +export interface DomainCreateParams { + /** + * Domain name to register, such as example.com. + */ + domain: string; +} + +Domains.Verify = Verify; + +export declare namespace Domains { + export { + type DomainCreateResponse as DomainCreateResponse, + type DomainRetrieveResponse as DomainRetrieveResponse, + type DomainListResponse as DomainListResponse, + type DomainDeleteResponse as DomainDeleteResponse, + type DomainCreateParams as DomainCreateParams, + }; + + export { Verify as Verify, type VerifyCreateResponse as VerifyCreateResponse }; +} diff --git a/src/resources/domains/index.ts b/src/resources/domains/index.ts new file mode 100644 index 0000000..fae2293 --- /dev/null +++ b/src/resources/domains/index.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Domains, + type DomainCreateResponse, + type DomainRetrieveResponse, + type DomainListResponse, + type DomainDeleteResponse, + type DomainCreateParams, +} from './domains'; +export { Verify, type VerifyCreateResponse } from './verify'; diff --git a/src/resources/domains/verify.ts b/src/resources/domains/verify.ts new file mode 100644 index 0000000..c11fe69 --- /dev/null +++ b/src/resources/domains/verify.ts @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Verify extends APIResource { + /** + * Verify the ownership TXT challenge and SES DKIM identity for a sender domain + * shared by every Developer Email API project in the workspace. Requires a + * personal access token belonging to a workspace owner or admin. + */ + create(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v3/domains/${id}/verify`, options); + } +} + +export interface VerifyCreateResponse { + data: VerifyCreateResponse.Data; +} + +export namespace VerifyCreateResponse { + export interface Data { + id?: number; + + dkim?: Data.Dkim; + + domain?: string; + + ownership?: Data.Ownership; + + status?: string; + } + + export namespace Data { + export interface Dkim { + status?: string; + + tokens?: Array; + } + + export interface Ownership { + verified?: boolean; + } + } +} + +export declare namespace Verify { + export { type VerifyCreateResponse as VerifyCreateResponse }; +} diff --git a/src/resources/emails.ts b/src/resources/emails.ts new file mode 100644 index 0000000..bd0ec59 --- /dev/null +++ b/src/resources/emails.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './emails/index'; diff --git a/src/resources/emails/emails.ts b/src/resources/emails/emails.ts new file mode 100644 index 0000000..ffecad2 --- /dev/null +++ b/src/resources/emails/emails.ts @@ -0,0 +1,414 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as EventsAPI from './events'; +import { EventRetrieveResponse, Events } from './events'; +import * as RenderAPI from './render'; +import { Render, RenderCreateParams, RenderCreateResponse } from './render'; +import * as SettingsAPI from './settings'; +import { SettingRetrieveResponse, SettingUpdateParams, SettingUpdateResponse, Settings } from './settings'; +import * as StatsAPI from './stats'; +import { StatRetrieveParams, StatRetrieveResponse, Stats } from './stats'; +import * as SuppressionsAPI from './suppressions'; +import { + SuppressionCreateParams, + SuppressionCreateResponse, + SuppressionDeleteParams, + SuppressionDeleteResponse, + SuppressionRetrieveParams, + SuppressionRetrieveResponse, + Suppressions, +} from './suppressions'; +import * as SuppressionsCheckAPI from './suppressions-check'; +import { + SuppressionsCheck, + SuppressionsCheckRetrieveParams, + SuppressionsCheckRetrieveResponse, +} from './suppressions-check'; +import * as TemplateAPI from './template'; +import { Template, TemplateCreateParams, TemplateCreateResponse } from './template'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Emails extends APIResource { + events: EventsAPI.Events = new EventsAPI.Events(this._client); + render: RenderAPI.Render = new RenderAPI.Render(this._client); + settings: SettingsAPI.Settings = new SettingsAPI.Settings(this._client); + stats: StatsAPI.Stats = new StatsAPI.Stats(this._client); + suppressions: SuppressionsAPI.Suppressions = new SuppressionsAPI.Suppressions(this._client); + suppressionsCheck: SuppressionsCheckAPI.SuppressionsCheck = new SuppressionsCheckAPI.SuppressionsCheck( + this._client, + ); + template: TemplateAPI.Template = new TemplateAPI.Template(this._client); + + /** + * Send a transactional email with raw HTML content. The sender domain must be + * verified in the project workspace; verified sender domains are shared by every + * Developer Email API project in that workspace. + */ + create(params: EmailCreateParams, options?: RequestOptions): APIPromise { + const { 'idempotency-key': idempotencyKey, ...body } = params; + return this._client.post('/v3/emails', { + body, + ...options, + headers: buildHeaders([ + { ...(idempotencyKey != null ? { 'idempotency-key': idempotencyKey } : undefined) }, + options?.headers, + ]), + }); + } + + /** + * Retrieve details of a sent email, including its current delivery status, during + * the rolling 90-day history window. Expired emails return 404. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/emails/${id}`, options); + } + + /** + * List emails sent from this project within the rolling 90-day history window. + * Without a status filter, results and date bounds use acceptance time. With a + * status filter, results and date bounds use the time each email entered that + * status. + */ + list( + query: EmailListParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/emails', { query, ...options }); + } +} + +/** + * Email accepted and queued for delivery + */ +export interface EmailCreateResponse { + data: EmailCreateResponse.Data; +} + +export namespace EmailCreateResponse { + export interface Data { + /** + * Unique email ID (UUID). Use this with GET /v3/emails/:id to retrieve delivery + * status and events. + */ + id?: string; + + /** + * When the email was accepted and queued for delivery (ISO-8601). + */ + createdAt?: string; + + /** + * The sender address the email was sent from, either a plain email or "Name + * " format. + */ + from?: string; + + /** + * Usually "queued" for a fresh send. An idempotent replay of a previously accepted + * request returns that email's current status instead. Use webhooks or GET + * /v3/emails/:id for live delivery status. + */ + status?: 'queued' | 'sending' | 'sent' | 'delivered' | 'bounced' | 'complained' | 'failed'; + + /** + * The subject line of the email that was sent. + */ + subject?: string; + + /** + * The single accepted recipient address. + */ + to?: Array; + } +} + +export interface EmailRetrieveResponse { + data: EmailRetrieveResponse.Data; +} + +export namespace EmailRetrieveResponse { + export interface Data { + id?: string; + + bcc?: Array | null; + + cc?: Array | null; + + createdAt?: string; + + failureReason?: string | null; + + from?: string; + + status?: string; + + subject?: string | null; + + tags?: { [key: string]: string } | null; + + to?: unknown; + } +} + +export interface EmailListResponse { + data: Array; + + /** + * Whether there are more results after this page + */ + has_more: boolean; + + /** + * Cursor for the next page. Null if no more results. + */ + next_cursor?: string | null; +} + +export namespace EmailListResponse { + export interface Data { + id?: string; + + createdAt?: string; + + from?: string; + + status?: string; + + /** + * When the email entered its current status. For a newly queued email, this equals + * createdAt. + */ + statusUpdatedAt?: string; + + subject?: string | null; + + to?: unknown; + } +} + +export interface EmailCreateParams { + /** + * Body param: Sender email address or "Name " format. Domain must be + * verified. + */ + from: string; + + /** + * Body param: HTML content of the email + */ + html: string; + + /** + * Body param: Email subject line + */ + subject: string; + + /** + * Body param: Exactly one recipient. Each request creates one independently + * tracked delivery. + */ + to: Array; + + /** + * Body param: File attachments. Max 10 files per email, max 5 MB total payload + * size (including headers and base64 overhead). + */ + attachments?: Array; + + /** + * Body param: BCC is not supported by this endpoint. + */ + bcc?: Array; + + /** + * Body param: CC is not supported by this endpoint. + */ + cc?: Array; + + /** + * Body param: Custom email headers. Up to 9 printable-ASCII X-\* headers are + * allowed (e.g. {"X-Entity-Ref-ID": "abc123"}). Header names may contain up to 126 + * characters and each name plus value may contain up to 996 characters. + */ + headers?: { [key: string]: string }; + + /** + * Body param: Reply-To email address + */ + replyTo?: string; + + /** + * Body param: Key-value tags for categorizing the email (e.g. {"campaign": + * "welcome"}). Max 10 tags. Keys (1-64 chars) and values (up to 256 chars) may + * only contain letters, numbers, underscores, and hyphens (the Amazon SES + * message-tag character set). + */ + tags?: { [key: string]: string }; + + /** + * Body param: Plain text version of the email. If provided, a + * multipart/alternative message is sent. + */ + text?: string; + + /** + * Header param: Unique key for idempotent sends (max 255 characters). If provided, + * duplicate requests within 24 hours return the cached response. + */ + 'idempotency-key'?: string; +} + +export namespace EmailCreateParams { + export interface Attachment { + /** + * Base64-encoded file content. Whitespace and MIME line wrapping are removed + * before validation; invalid base64 is rejected with a 400 error. + */ + content: string; + + /** + * MIME type of the attachment. Required; must be one of the allowed types. + */ + contentType: + | 'application/pdf' + | 'application/zip' + | 'application/json' + | 'application/xml' + | 'application/csv' + | 'application/msword' + | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + | 'application/vnd.ms-excel' + | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + | 'application/vnd.ms-powerpoint' + | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' + | 'text/plain' + | 'text/html' + | 'text/csv' + | 'text/xml' + | 'text/calendar' + | 'image/png' + | 'image/jpeg' + | 'image/gif' + | 'image/webp' + | 'image/svg+xml' + | 'audio/mpeg' + | 'audio/wav' + | 'video/mp4'; + + /** + * The filename as it will appear to the recipient. Line breaks are rejected; + * quotes are stripped before it is written into the message. + */ + filename: string; + } +} + +export interface EmailListParams { + /** + * Pagination cursor from previous response + */ + cursor?: string; + + /** + * Start date (ISO date). Bounds acceptance time normally, or status transition + * time when status is supplied. + */ + from?: string; + + /** + * Number of emails to return (1-100) + */ + limit?: number; + + /** + * Project ID (auto-resolved for API key auth) + */ + projectId?: string; + + /** + * Search recipient addresses and subjects by case-sensitive substring + */ + search?: string; + + /** + * Filter by email delivery status + */ + status?: 'queued' | 'sending' | 'sent' | 'delivered' | 'bounced' | 'complained' | 'failed'; + + /** + * Filter by tag in "key=value" format (e.g. "campaign=welcome") + */ + tag?: string; + + /** + * End date (ISO date). Bounds acceptance time normally, or status transition time + * when status is supplied. + */ + to?: string; +} + +Emails.Events = Events; +Emails.Render = Render; +Emails.Settings = Settings; +Emails.Stats = Stats; +Emails.Suppressions = Suppressions; +Emails.SuppressionsCheck = SuppressionsCheck; +Emails.Template = Template; + +export declare namespace Emails { + export { + type EmailCreateResponse as EmailCreateResponse, + type EmailRetrieveResponse as EmailRetrieveResponse, + type EmailListResponse as EmailListResponse, + type EmailCreateParams as EmailCreateParams, + type EmailListParams as EmailListParams, + }; + + export { Events as Events, type EventRetrieveResponse as EventRetrieveResponse }; + + export { + Render as Render, + type RenderCreateResponse as RenderCreateResponse, + type RenderCreateParams as RenderCreateParams, + }; + + export { + Settings as Settings, + type SettingRetrieveResponse as SettingRetrieveResponse, + type SettingUpdateResponse as SettingUpdateResponse, + type SettingUpdateParams as SettingUpdateParams, + }; + + export { + Stats as Stats, + type StatRetrieveResponse as StatRetrieveResponse, + type StatRetrieveParams as StatRetrieveParams, + }; + + export { + Suppressions as Suppressions, + type SuppressionCreateResponse as SuppressionCreateResponse, + type SuppressionRetrieveResponse as SuppressionRetrieveResponse, + type SuppressionDeleteResponse as SuppressionDeleteResponse, + type SuppressionCreateParams as SuppressionCreateParams, + type SuppressionRetrieveParams as SuppressionRetrieveParams, + type SuppressionDeleteParams as SuppressionDeleteParams, + }; + + export { + SuppressionsCheck as SuppressionsCheck, + type SuppressionsCheckRetrieveResponse as SuppressionsCheckRetrieveResponse, + type SuppressionsCheckRetrieveParams as SuppressionsCheckRetrieveParams, + }; + + export { + Template as Template, + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateCreateParams as TemplateCreateParams, + }; +} diff --git a/src/resources/emails/events.ts b/src/resources/emails/events.ts new file mode 100644 index 0000000..3fe709a --- /dev/null +++ b/src/resources/emails/events.ts @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Events extends APIResource { + /** + * Retrieve the operational event timeline for a sent email, showing send, + * delivery, bounce, and complaint events in chronological order during the rolling + * 90-day history window. Expired emails return 404. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/emails/${id}/events`, options); + } +} + +export interface EventRetrieveResponse { + data: Array; +} + +export namespace EventRetrieveResponse { + export interface Data { + metadata?: { [key: string]: unknown } | null; + + timestamp?: string; + + /** + * Event type (send, delivery, bounce, complaint) + */ + type?: string; + } +} + +export declare namespace Events { + export { type EventRetrieveResponse as EventRetrieveResponse }; +} diff --git a/src/resources/emails/index.ts b/src/resources/emails/index.ts new file mode 100644 index 0000000..c0b2b7a --- /dev/null +++ b/src/resources/emails/index.ts @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Emails, + type EmailCreateResponse, + type EmailRetrieveResponse, + type EmailListResponse, + type EmailCreateParams, + type EmailListParams, +} from './emails'; +export { Events, type EventRetrieveResponse } from './events'; +export { Render, type RenderCreateResponse, type RenderCreateParams } from './render'; +export { + Settings, + type SettingRetrieveResponse, + type SettingUpdateResponse, + type SettingUpdateParams, +} from './settings'; +export { Stats, type StatRetrieveResponse, type StatRetrieveParams } from './stats'; +export { + Suppressions, + type SuppressionCreateResponse, + type SuppressionRetrieveResponse, + type SuppressionDeleteResponse, + type SuppressionCreateParams, + type SuppressionRetrieveParams, + type SuppressionDeleteParams, +} from './suppressions'; +export { + SuppressionsCheck, + type SuppressionsCheckRetrieveResponse, + type SuppressionsCheckRetrieveParams, +} from './suppressions-check'; +export { Template, type TemplateCreateResponse, type TemplateCreateParams } from './template'; diff --git a/src/resources/emails/render.ts b/src/resources/emails/render.ts new file mode 100644 index 0000000..e1ea2c2 --- /dev/null +++ b/src/resources/emails/render.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Render extends APIResource { + /** + * Render a saved email template with optional merge variables. Returns the final + * HTML without sending. Useful for previewing emails before sending. + */ + create(body: RenderCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v3/emails/render', { body, ...options }); + } +} + +export interface RenderCreateResponse { + data: RenderCreateResponse.Data; +} + +export namespace RenderCreateResponse { + export interface Data { + /** + * Rendered HTML content + */ + html?: string; + + /** + * Template name (can be used as default subject) + */ + subject?: string | null; + } +} + +export interface RenderCreateParams { + /** + * Template ID to render + */ + templateId: string; + + /** + * Merge variables to substitute. Use {{key}} syntax in your template. + */ + variables?: { [key: string]: string }; +} + +export declare namespace Render { + export { type RenderCreateResponse as RenderCreateResponse, type RenderCreateParams as RenderCreateParams }; +} diff --git a/src/resources/emails/settings.ts b/src/resources/emails/settings.ts new file mode 100644 index 0000000..dd07f31 --- /dev/null +++ b/src/resources/emails/settings.ts @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Settings extends APIResource { + /** + * Get the email sender settings for this project. + */ + retrieve(options?: RequestOptions): APIPromise { + return this._client.get('/v3/emails/settings', options); + } + + /** + * Update the email sending configuration for this project. Only include the fields + * you want to change. + */ + update( + body: SettingUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.patch('/v3/emails/settings', { body, ...options }); + } +} + +export interface SettingRetrieveResponse { + data: SettingRetrieveResponse.Data; +} + +export namespace SettingRetrieveResponse { + export interface Data { + /** + * When the settings row was first created. + */ + createdAt?: string; + + /** + * Default sender display name + */ + defaultFromName?: string; + + /** + * When the settings were last updated. + */ + updatedAt?: string; + } +} + +export interface SettingUpdateResponse { + data: SettingUpdateResponse.Data; +} + +export namespace SettingUpdateResponse { + export interface Data { + /** + * When the settings row was first created. + */ + createdAt?: string; + + /** + * Default sender display name + */ + defaultFromName?: string; + + /** + * When the settings were last updated. + */ + updatedAt?: string; + } +} + +export interface SettingUpdateParams { + /** + * Default sender display name + */ + defaultFromName?: string; +} + +export declare namespace Settings { + export { + type SettingRetrieveResponse as SettingRetrieveResponse, + type SettingUpdateResponse as SettingUpdateResponse, + type SettingUpdateParams as SettingUpdateParams, + }; +} diff --git a/src/resources/emails/stats.ts b/src/resources/emails/stats.ts new file mode 100644 index 0000000..eb0f0e1 --- /dev/null +++ b/src/resources/emails/stats.ts @@ -0,0 +1,120 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Stats extends APIResource { + /** + * Get aggregated email delivery statistics for a project. Returns totals or daily + * breakdown for the specified period. Statistics are asynchronous and may lag by + * about one hour. + */ + retrieve( + query: StatRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/emails/stats', { query, ...options }); + } +} + +/** + * Email statistics. Shape depends on the `groupBy` query parameter: an aggregated + * totals object by default, or a daily breakdown array when groupBy=day. + */ +export interface StatRetrieveResponse { + /** + * Aggregated totals for the requested period (default response). + */ + data: StatRetrieveResponse.UnionMember0 | Array; +} + +export namespace StatRetrieveResponse { + /** + * Aggregated totals for the requested period (default response). + */ + export interface UnionMember0 { + /** + * Number of emails that were bounced by the recipient mail server. + */ + bounced?: number; + + /** + * Bounced / sent as a percentage (0-100, 2 decimal places). + */ + bounceRate?: number; + + /** + * Number of spam complaint events received. + */ + complained?: number; + + /** + * Number of successfully delivered emails. + */ + delivered?: number; + + /** + * Delivered / sent as a percentage (0-100, 2 decimal places). + */ + deliveryRate?: number; + + /** + * The period these stats cover. + */ + period?: '7d' | '30d' | '90d'; + + /** + * Total emails sent (one per recipient). + */ + sent?: number; + } + + export interface UnionMember1 { + /** + * Emails bounced on this day. + */ + bounced?: number; + + /** + * Spam complaints received for this send cohort. + */ + complained?: number; + + /** + * The email send-cohort day in YYYY-MM-DD format. + */ + date?: string; + + /** + * Emails from this send cohort that were delivered. + */ + delivered?: number; + + /** + * Emails sent on this day. + */ + sent?: number; + } +} + +export interface StatRetrieveParams { + /** + * Group results by day for chart data + */ + groupBy?: 'day'; + + /** + * Time period for stats + */ + period?: '7d' | '30d' | '90d'; + + /** + * Project ID (auto-resolved for API key auth) + */ + projectId?: string; +} + +export declare namespace Stats { + export { type StatRetrieveResponse as StatRetrieveResponse, type StatRetrieveParams as StatRetrieveParams }; +} diff --git a/src/resources/emails/suppressions-check.ts b/src/resources/emails/suppressions-check.ts new file mode 100644 index 0000000..22a5cf2 --- /dev/null +++ b/src/resources/emails/suppressions-check.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class SuppressionsCheck extends APIResource { + /** + * Look up a specific email address to see if it is currently on the suppression + * list. + */ + retrieve( + query: SuppressionsCheckRetrieveParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/emails/suppressions/check', { query, ...options }); + } +} + +export interface SuppressionsCheckRetrieveResponse { + data: SuppressionsCheckRetrieveResponse.Data; +} + +export namespace SuppressionsCheckRetrieveResponse { + export interface Data { + email?: string; + + suppressed?: boolean; + } +} + +export interface SuppressionsCheckRetrieveParams { + /** + * Email address to check + */ + email: string; + + /** + * Project ID (auto-resolved for API key auth) + */ + projectId?: string; +} + +export declare namespace SuppressionsCheck { + export { + type SuppressionsCheckRetrieveResponse as SuppressionsCheckRetrieveResponse, + type SuppressionsCheckRetrieveParams as SuppressionsCheckRetrieveParams, + }; +} diff --git a/src/resources/emails/suppressions.ts b/src/resources/emails/suppressions.ts new file mode 100644 index 0000000..96a9efc --- /dev/null +++ b/src/resources/emails/suppressions.ts @@ -0,0 +1,126 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +export class Suppressions extends APIResource { + /** + * Manually add an email address to the suppression list. Future sends to this + * address will be blocked. + */ + create(body: SuppressionCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v3/emails/suppressions', { body, ...options }); + } + + /** + * List all email addresses suppressed for this project due to bounces, complaints, + * or manual suppression. Cursor-paginated. + */ + retrieve( + query: SuppressionRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/emails/suppressions', { query, ...options }); + } + + /** + * Remove an email address from the suppression list so it can receive emails + * again. + */ + delete(params: SuppressionDeleteParams, options?: RequestOptions): APIPromise { + const { email, projectId } = params; + return this._client.delete('/v3/emails/suppressions', { query: { email, projectId }, ...options }); + } +} + +export interface SuppressionCreateResponse { + data: SuppressionCreateResponse.Data; +} + +export namespace SuppressionCreateResponse { + export interface Data { + createdAt?: string; + + email?: string; + + reason?: string; + } +} + +export interface SuppressionRetrieveResponse { + data: Array; + + has_more: boolean; + + next_cursor?: string | null; +} + +export namespace SuppressionRetrieveResponse { + export interface Data { + createdAt?: string; + + email?: string; + + reason?: 'hard_bounce' | 'complaint' | 'manual' | 'unsubscribe'; + } +} + +export interface SuppressionDeleteResponse { + data: SuppressionDeleteResponse.Data; +} + +export namespace SuppressionDeleteResponse { + export interface Data { + email?: string; + + removed?: boolean; + } +} + +export interface SuppressionCreateParams { + /** + * Email address to suppress + */ + email: string; +} + +export interface SuppressionRetrieveParams { + /** + * Pagination cursor from a previous response. Omit to start from the beginning. + */ + cursor?: string; + + /** + * Max number of results (1-200) + */ + limit?: number; + + /** + * Project ID (auto-resolved for API key auth) + */ + projectId?: string; +} + +export interface SuppressionDeleteParams { + /** + * Email address to unsuppress + */ + email: string; + + /** + * Project ID (auto-resolved for API key auth) + */ + projectId?: string; +} + +export declare namespace Suppressions { + export { + type SuppressionCreateResponse as SuppressionCreateResponse, + type SuppressionRetrieveResponse as SuppressionRetrieveResponse, + type SuppressionDeleteResponse as SuppressionDeleteResponse, + type SuppressionCreateParams as SuppressionCreateParams, + type SuppressionRetrieveParams as SuppressionRetrieveParams, + type SuppressionDeleteParams as SuppressionDeleteParams, + }; +} diff --git a/src/resources/emails/template.ts b/src/resources/emails/template.ts new file mode 100644 index 0000000..fd8906f --- /dev/null +++ b/src/resources/emails/template.ts @@ -0,0 +1,201 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; + +export class Template extends APIResource { + /** + * Send a transactional email by rendering a saved template with optional merge + * variables. The template must have rendered HTML (saved at least once in the + * editor). The sender domain must be verified in the project workspace; verified + * sender domains are shared by every Developer Email API project in that + * workspace. + */ + create(params: TemplateCreateParams, options?: RequestOptions): APIPromise { + const { 'idempotency-key': idempotencyKey, ...body } = params; + return this._client.post('/v3/emails/template', { + body, + ...options, + headers: buildHeaders([ + { ...(idempotencyKey != null ? { 'idempotency-key': idempotencyKey } : undefined) }, + options?.headers, + ]), + }); + } +} + +/** + * Email accepted and queued for delivery + */ +export interface TemplateCreateResponse { + data: TemplateCreateResponse.Data; +} + +export namespace TemplateCreateResponse { + export interface Data { + /** + * Unique email ID (UUID). Use this with GET /v3/emails/:id to retrieve delivery + * status and events. + */ + id?: string; + + /** + * When the email was accepted and queued for delivery (ISO-8601). + */ + createdAt?: string; + + /** + * The sender address the email was sent from. + */ + from?: string; + + /** + * Usually "queued" for a fresh send. An idempotent replay of a previously accepted + * request returns that email's current status instead. Use webhooks or GET + * /v3/emails/:id for live delivery status. + */ + status?: 'queued' | 'sending' | 'sent' | 'delivered' | 'bounced' | 'complained' | 'failed'; + + /** + * The resolved subject line after merge variables were applied. + */ + subject?: string; + + /** + * The single accepted recipient address. + */ + to?: Array; + } +} + +export interface TemplateCreateParams { + /** + * Body param: Sender email address or "Name " format. Domain must be + * verified. + */ + from: string; + + /** + * Body param: Template ID to use for the email body + */ + templateId: string; + + /** + * Body param: Exactly one recipient. Each request creates one independently + * tracked delivery. + */ + to: Array; + + /** + * Body param: File attachments. Max 10 files per email, max 5 MB total payload + * size. + */ + attachments?: Array; + + /** + * Body param: BCC is not supported by this endpoint. + */ + bcc?: Array; + + /** + * Body param: CC is not supported by this endpoint. + */ + cc?: Array; + + /** + * Body param: Custom email headers. Up to 9 printable-ASCII X-\* headers are + * allowed. Header names may contain up to 126 characters and each name plus value + * may contain up to 996 characters. + */ + headers?: { [key: string]: string }; + + /** + * Body param: Reply-To email address + */ + replyTo?: string; + + /** + * Body param: Email subject line. Supports {{variable}} merge syntax. Defaults to + * template name if omitted. + */ + subject?: string; + + /** + * Body param: Key-value tags for categorizing the email (e.g. {"campaign": + * "welcome"}). Max 10 tags. Keys (1-64 chars) and values (up to 256 chars) may + * only contain letters, numbers, underscores, and hyphens (the Amazon SES + * message-tag character set). + */ + tags?: { [key: string]: string }; + + /** + * Body param: Plain text version of the email. Supports {{variable}} merge syntax. + */ + text?: string; + + /** + * Body param: Merge variables to substitute in the template and subject. Use + * {{key}} syntax in your template. + */ + variables?: { [key: string]: string }; + + /** + * Header param: Unique key for idempotent sends (max 255 characters). Duplicate + * requests within 24 hours return the cached response. + */ + 'idempotency-key'?: string; +} + +export namespace TemplateCreateParams { + export interface Attachment { + /** + * Base64-encoded file content. Whitespace and MIME line wrapping are removed + * before validation; invalid base64 is rejected with a 400 error. + */ + content: string; + + /** + * MIME type of the attachment. Required; must be one of the allowed types. + */ + contentType: + | 'application/pdf' + | 'application/zip' + | 'application/json' + | 'application/xml' + | 'application/csv' + | 'application/msword' + | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + | 'application/vnd.ms-excel' + | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + | 'application/vnd.ms-powerpoint' + | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' + | 'text/plain' + | 'text/html' + | 'text/csv' + | 'text/xml' + | 'text/calendar' + | 'image/png' + | 'image/jpeg' + | 'image/gif' + | 'image/webp' + | 'image/svg+xml' + | 'audio/mpeg' + | 'audio/wav' + | 'video/mp4'; + + /** + * The filename as it will appear to the recipient. Line breaks are rejected; + * quotes are stripped before it is written into the message. + */ + filename: string; + } +} + +export declare namespace Template { + export { + type TemplateCreateResponse as TemplateCreateResponse, + type TemplateCreateParams as TemplateCreateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index c4ba5a4..6fadd48 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,10 +1,26 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { + Domains, + type DomainCreateResponse, + type DomainRetrieveResponse, + type DomainListResponse, + type DomainDeleteResponse, + type DomainCreateParams, +} from './domains/domains'; export { EditorSessions, type EditorSessionCreateResponse, type EditorSessionCreateParams, } from './editor-sessions'; +export { + Emails, + type EmailCreateResponse, + type EmailRetrieveResponse, + type EmailListResponse, + type EmailCreateParams, + type EmailListParams, +} from './emails/emails'; export { Me } from './me/me'; export { Projects, type ProjectRetrieveResponse } from './projects/projects'; export { @@ -15,4 +31,14 @@ export { type TemplateListParams, type TemplateListResponsesCursorPage, } from './templates/templates'; +export { + Webhooks, + type WebhookCreateResponse, + type WebhookRetrieveResponse, + type WebhookUpdateResponse, + type WebhookListResponse, + type WebhookDeleteResponse, + type WebhookCreateParams, + type WebhookUpdateParams, +} from './webhooks/webhooks'; export { Workspaces, type WorkspaceRetrieveResponse, type WorkspaceListResponse } from './workspaces'; diff --git a/src/resources/templates/convert-full-to-simple.ts b/src/resources/templates/convert-full-to-simple.ts index c8b3e8c..e5a3c08 100644 --- a/src/resources/templates/convert-full-to-simple.ts +++ b/src/resources/templates/convert-full-to-simple.ts @@ -34,6 +34,12 @@ export namespace ConvertFullToSimpleCreateResponse { export interface ConvertFullToSimpleCreateParams { design: ConvertFullToSimpleCreateParams.Design; + /** + * Display mode of the design (email, web, document, popup). Defaults to "email", + * matching /v3/templates/validate. Mode-specific repairs apply during conversion + * (email caps contentWidth at 900px, for example), so pass the design's actual + * mode — a web design converted under the email default can be altered. + */ displayMode?: 'email' | 'web' | 'popup' | 'document'; /** diff --git a/src/resources/templates/convert-simple-to-full.ts b/src/resources/templates/convert-simple-to-full.ts index c1c0af0..0e848d5 100644 --- a/src/resources/templates/convert-simple-to-full.ts +++ b/src/resources/templates/convert-simple-to-full.ts @@ -34,6 +34,12 @@ export namespace ConvertSimpleToFullCreateResponse { export interface ConvertSimpleToFullCreateParams { design: ConvertSimpleToFullCreateParams.Design; + /** + * Display mode of the design (email, web, document, popup). Defaults to "email", + * matching /v3/templates/validate. Mode-specific repairs apply during conversion + * (email caps contentWidth at 900px, for example), so pass the design's actual + * mode — a web design converted under the email default can be altered. + */ displayMode?: 'email' | 'web' | 'popup' | 'document'; includeDefaultValues?: boolean; diff --git a/src/resources/templates/index.ts b/src/resources/templates/index.ts index c07698b..62ba98f 100644 --- a/src/resources/templates/index.ts +++ b/src/resources/templates/index.ts @@ -16,6 +16,7 @@ export { ExportPdf, type ExportPdfCreateResponse, type ExportPdfCreateParams } f export { ExportZip, type ExportZipCreateResponse, type ExportZipCreateParams } from './export-zip'; export { Generate, type GenerateCreateResponse, type GenerateCreateParams } from './generate'; export { Import, type ImportCreateResponse, type ImportCreateParams } from './import'; +export { Schema, type SchemaRetrieveParams } from './schema'; export { Templates, type TemplateRetrieveResponse, @@ -24,3 +25,4 @@ export { type TemplateListParams, type TemplateListResponsesCursorPage, } from './templates'; +export { Validate, type ValidateCreateResponse, type ValidateCreateParams } from './validate'; diff --git a/src/resources/templates/schema.ts b/src/resources/templates/schema.ts new file mode 100644 index 0000000..d6d4bce --- /dev/null +++ b/src/resources/templates/schema.ts @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ +export class Schema extends APIResource { + /** + * Returns the canonical design schema as a standard JSON Schema document — the + * exact schema POST /v3/templates/validate checks against, ready to plug into any + * JSON Schema validator or editor tooling. Serves the Full schema by default; pass + * simple=true for the compact Simple schema. No authentication required. Responses + * carry a strong ETag and long-lived cache headers; send If-None-Match to + * revalidate for free. + */ + retrieve(query: SchemaRetrieveParams | null | undefined = {}, options?: RequestOptions): APIPromise { + return this._client.get('/v3/templates/schema', { + query, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface SchemaRetrieveParams { + /** + * Display mode whose rules the schema describes (email, web, document, popup). + * Defaults to "email". + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * When true, returns the Simple schema instead of the Full schema. + */ + simple?: boolean; +} + +export declare namespace Schema { + export { type SchemaRetrieveParams as SchemaRetrieveParams }; +} diff --git a/src/resources/templates/templates.ts b/src/resources/templates/templates.ts index 96b914f..45f8f0f 100644 --- a/src/resources/templates/templates.ts +++ b/src/resources/templates/templates.ts @@ -25,6 +25,10 @@ import * as GenerateAPI from './generate'; import { Generate, GenerateCreateParams, GenerateCreateResponse } from './generate'; import * as ImportAPI from './import'; import { Import, ImportCreateParams, ImportCreateResponse } from './import'; +import * as SchemaAPI from './schema'; +import { Schema, SchemaRetrieveParams } from './schema'; +import * as ValidateAPI from './validate'; +import { Validate, ValidateCreateParams, ValidateCreateResponse } from './validate'; import { APIPromise } from '../../core/api-promise'; import { CursorPage, type CursorPageParams, PagePromise } from '../../core/pagination'; import { RequestOptions } from '../../internal/request-options'; @@ -44,6 +48,8 @@ export class Templates extends APIResource { exportZip: ExportZipAPI.ExportZip = new ExportZipAPI.ExportZip(this._client); generate: GenerateAPI.Generate = new GenerateAPI.Generate(this._client); import: ImportAPI.Import = new ImportAPI.Import(this._client); + schema: SchemaAPI.Schema = new SchemaAPI.Schema(this._client); + validate: ValidateAPI.Validate = new ValidateAPI.Validate(this._client); /** * Get template by ID. @@ -145,6 +151,8 @@ Templates.ExportPdf = ExportPdf; Templates.ExportZip = ExportZip; Templates.Generate = Generate; Templates.Import = Import; +Templates.Schema = Schema; +Templates.Validate = Validate; export declare namespace Templates { export { @@ -202,4 +210,12 @@ export declare namespace Templates { type ImportCreateResponse as ImportCreateResponse, type ImportCreateParams as ImportCreateParams, }; + + export { Schema as Schema, type SchemaRetrieveParams as SchemaRetrieveParams }; + + export { + Validate as Validate, + type ValidateCreateResponse as ValidateCreateResponse, + type ValidateCreateParams as ValidateCreateParams, + }; } diff --git a/src/resources/templates/validate.ts b/src/resources/templates/validate.ts new file mode 100644 index 0000000..66832dc --- /dev/null +++ b/src/resources/templates/validate.ts @@ -0,0 +1,132 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Template management — list, retrieve, generate, import, export, and convert designs. + */ +export class Validate extends APIResource { + /** + * Validate a design JSON against the Unlayer design schema. Returns { success: + * true, data: { valid: true } } when the payload conforms; otherwise data is { + * valid: false, errors: [...] } with descriptive issues. Every checked design gets + * HTTP 200 — `data.valid` is the source of truth, not the status code. Only + * malformed requests (e.g. a missing design field or an unknown displayMode) fail + * request validation with 400 VALIDATION_ERROR. + */ + create(body: ValidateCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v3/templates/validate', { body, ...options }); + } +} + +export interface ValidateCreateResponse { + data: ValidateCreateResponse.Data; + + success: true; +} + +export namespace ValidateCreateResponse { + export interface Data { + valid: boolean; + + /** + * Total number of issues found; greater than errors.length when the list was + * capped. + */ + errorCount?: number; + + /** + * Populated when valid is false, capped at 100 entries. Each issue carries the + * dotted path to the offending field, a human-readable message, and the underlying + * Zod issue code. + */ + errors?: Array; + + /** + * Present when the design was upgraded from an older schemaVersion before + * validation; carries the original version number. + */ + migratedFrom?: number; + } + + export namespace Data { + export interface Error { + code: string; + + message: string; + + path: string; + } + } +} + +export interface ValidateCreateParams { + /** + * The design JSON to validate. + */ + design: { [key: string]: unknown }; + + /** + * Custom tool declarations, in the same shape passed to unlayer.registerTool. When + * provided, blocks matching a declared tool have their values checked against the + * tool's declared options (wrong types are reported at their exact path). Blocks + * of undeclared tools keep envelope-only validation. + */ + customTools?: Array; + + /** + * Display mode for the design (email, web, document, popup). Some validation rules + * differ per mode. Defaults to "email" — without a default, options from every + * mode would apply at once, the strictest possible check, and real editor-saved + * designs could be reported invalid. + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * When true (default), a full-form design with an older schemaVersion is upgraded + * to the current schema before validating — matching how the editor and the + * convert endpoints treat stored designs. Designs without a schemaVersion predate + * versioning and are fully migrated the same way. Set to false to check strict + * conformance with the current schema version. Designs with a newer schemaVersion + * than this API knows are validated as-if-current. + */ + migrate?: boolean; + + /** + * Which form of the schema to validate against. Defaults to "full". + */ + schema?: 'full' | 'simple'; +} + +export namespace ValidateCreateParams { + export interface CustomTool { + options: { [key: string]: CustomTool.Options }; + + slug: string; + + label?: string; + + supportedDisplayModes?: Array<'email' | 'web' | 'popup' | 'document'>; + + type?: string; + + values?: { [key: string]: unknown }; + + [k: string]: unknown; + } + + export namespace CustomTool { + export interface Options { + options?: unknown; + } + } +} + +export declare namespace Validate { + export { + type ValidateCreateResponse as ValidateCreateResponse, + type ValidateCreateParams as ValidateCreateParams, + }; +} diff --git a/src/resources/webhooks.ts b/src/resources/webhooks.ts new file mode 100644 index 0000000..8aad965 --- /dev/null +++ b/src/resources/webhooks.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './webhooks/index'; diff --git a/src/resources/webhooks/index.ts b/src/resources/webhooks/index.ts new file mode 100644 index 0000000..cb1800e --- /dev/null +++ b/src/resources/webhooks/index.ts @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { RotateSecret, type RotateSecretCreateResponse } from './rotate-secret'; +export { + Webhooks, + type WebhookCreateResponse, + type WebhookRetrieveResponse, + type WebhookUpdateResponse, + type WebhookListResponse, + type WebhookDeleteResponse, + type WebhookCreateParams, + type WebhookUpdateParams, +} from './webhooks'; diff --git a/src/resources/webhooks/rotate-secret.ts b/src/resources/webhooks/rotate-secret.ts new file mode 100644 index 0000000..f8342ff --- /dev/null +++ b/src/resources/webhooks/rotate-secret.ts @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class RotateSecret extends APIResource { + /** + * Generate a new signing secret for a webhook. The new secret is returned once — + * store it securely. The old secret is invalidated immediately. + */ + create(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v3/webhooks/${id}/rotate-secret`, options); + } +} + +export interface RotateSecretCreateResponse { + data: RotateSecretCreateResponse.Data; +} + +export namespace RotateSecretCreateResponse { + export interface Data { + id?: number; + + /** + * New signing secret — only returned once. Store it securely. + */ + secret?: string; + + updatedAt?: string; + } +} + +export declare namespace RotateSecret { + export { type RotateSecretCreateResponse as RotateSecretCreateResponse }; +} diff --git a/src/resources/webhooks/webhooks.ts b/src/resources/webhooks/webhooks.ts new file mode 100644 index 0000000..87b2e95 --- /dev/null +++ b/src/resources/webhooks/webhooks.ts @@ -0,0 +1,255 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as RotateSecretAPI from './rotate-secret'; +import { RotateSecret, RotateSecretCreateResponse } from './rotate-secret'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Webhooks extends APIResource { + rotateSecret: RotateSecretAPI.RotateSecret = new RotateSecretAPI.RotateSecret(this._client); + + /** + * Create a new webhook endpoint. A signing secret is auto-generated and returned + * once. Use it to verify webhook signatures. + */ + create(body: WebhookCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v3/webhooks', { body, ...options }); + } + + /** + * Get details of a specific webhook endpoint. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v3/webhooks/${id}`, options); + } + + /** + * Update a webhook endpoint URL, events, or active status. + */ + update( + id: string, + body: WebhookUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/v3/webhooks/${id}`, { body, ...options }); + } + + /** + * List all webhook endpoints configured for a project. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v3/webhooks', options); + } + + /** + * Delete a webhook endpoint. It will no longer receive events. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v3/webhooks/${id}`, options); + } +} + +export interface WebhookCreateResponse { + data: WebhookCreateResponse.Data; +} + +export namespace WebhookCreateResponse { + export interface Data { + /** + * Webhook ID + */ + id?: number; + + /** + * Whether the webhook is actively receiving events + */ + active?: boolean; + + /** + * When the webhook was created + */ + createdAt?: string; + + /** + * Event types this webhook is subscribed to + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; + + /** + * Signing secret — only returned on creation. Store it securely; you will not be + * able to retrieve it again. + */ + secret?: string; + + /** + * The HTTPS URL receiving webhook events + */ + url?: string; + } +} + +export interface WebhookRetrieveResponse { + data: WebhookRetrieveResponse.Data; +} + +export namespace WebhookRetrieveResponse { + export interface Data { + /** + * Webhook ID + */ + id?: number; + + /** + * Whether the webhook is actively receiving events + */ + active?: boolean; + + /** + * When the webhook was created + */ + createdAt?: string; + + /** + * Event types this webhook is subscribed to + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; + + /** + * When the webhook was last updated + */ + updatedAt?: string; + + /** + * The HTTPS URL receiving webhook events + */ + url?: string; + } +} + +export interface WebhookUpdateResponse { + data: WebhookUpdateResponse.Data; +} + +export namespace WebhookUpdateResponse { + export interface Data { + /** + * Webhook ID + */ + id?: number; + + /** + * Whether the webhook is actively receiving events + */ + active?: boolean; + + /** + * Event types this webhook is subscribed to + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; + + /** + * When the webhook was last updated + */ + updatedAt?: string; + + /** + * The HTTPS URL receiving webhook events + */ + url?: string; + } +} + +export interface WebhookListResponse { + data: Array; +} + +export namespace WebhookListResponse { + export interface Data { + /** + * Webhook ID + */ + id?: number; + + /** + * Whether the webhook is actively receiving events + */ + active?: boolean; + + /** + * When the webhook was created + */ + createdAt?: string; + + /** + * Event types this webhook is subscribed to + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; + + /** + * The HTTPS URL receiving webhook events + */ + url?: string; + } +} + +export interface WebhookDeleteResponse { + data?: WebhookDeleteResponse.Data; +} + +export namespace WebhookDeleteResponse { + export interface Data { + success?: boolean; + } +} + +export interface WebhookCreateParams { + /** + * The HTTPS URL to receive webhook events + */ + url: string; + + /** + * Whether the webhook is active + */ + active?: boolean; + + /** + * Event types to subscribe to. If omitted or empty, all events are sent. + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; +} + +export interface WebhookUpdateParams { + /** + * Whether the webhook is actively receiving events + */ + active?: boolean; + + /** + * Event types to subscribe to. If omitted or empty, all events are sent. + */ + events?: Array<'email.sent' | 'email.delivered' | 'email.bounced' | 'email.complained'>; + + /** + * The HTTPS URL to receive webhook events + */ + url?: string; +} + +Webhooks.RotateSecret = RotateSecret; + +export declare namespace Webhooks { + export { + type WebhookCreateResponse as WebhookCreateResponse, + type WebhookRetrieveResponse as WebhookRetrieveResponse, + type WebhookUpdateResponse as WebhookUpdateResponse, + type WebhookListResponse as WebhookListResponse, + type WebhookDeleteResponse as WebhookDeleteResponse, + type WebhookCreateParams as WebhookCreateParams, + type WebhookUpdateParams as WebhookUpdateParams, + }; + + export { RotateSecret as RotateSecret, type RotateSecretCreateResponse as RotateSecretCreateResponse }; +} diff --git a/tests/api-resources/domains/domains.test.ts b/tests/api-resources/domains/domains.test.ts new file mode 100644 index 0000000..c12a1c0 --- /dev/null +++ b/tests/api-resources/domains/domains.test.ts @@ -0,0 +1,58 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource domains', () => { + test('create: only required params', async () => { + const responsePromise = client.domains.create({ domain: 'domain' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.domains.create({ domain: 'domain' }); + }); + + test('retrieve', async () => { + const responsePromise = client.domains.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list', async () => { + const responsePromise = client.domains.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('delete', async () => { + const responsePromise = client.domains.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/domains/verify.test.ts b/tests/api-resources/domains/verify.test.ts new file mode 100644 index 0000000..c42c251 --- /dev/null +++ b/tests/api-resources/domains/verify.test.ts @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource verify', () => { + test('create', async () => { + const responsePromise = client.domains.verify.create('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/emails/emails.test.ts b/tests/api-resources/emails/emails.test.ts new file mode 100644 index 0000000..cc81582 --- /dev/null +++ b/tests/api-resources/emails/emails.test.ts @@ -0,0 +1,90 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource emails', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.create({ + from: 'from', + html: 'html', + subject: 'subject', + to: ['dev@stainless.com'], + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.create({ + from: 'from', + html: 'html', + subject: 'subject', + to: ['dev@stainless.com'], + attachments: [ + { + content: 'content', + contentType: 'application/pdf', + filename: 'filename', + }, + ], + bcc: [], + cc: [], + headers: { foo: 'J!Q0Ok0bzJb7' }, + replyTo: 'dev@stainless.com', + tags: { foo: '_1' }, + text: 'text', + 'idempotency-key': 'idempotency-key', + }); + }); + + test('retrieve', async () => { + const responsePromise = client.emails.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list', async () => { + const responsePromise = client.emails.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.emails.list( + { + cursor: 'cursor', + from: '2019-12-27', + limit: 1, + projectId: 'projectId', + search: 'search', + status: 'queued', + tag: 'tag', + to: '2019-12-27', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/emails/events.test.ts b/tests/api-resources/emails/events.test.ts new file mode 100644 index 0000000..43c7b86 --- /dev/null +++ b/tests/api-resources/emails/events.test.ts @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource events', () => { + test('retrieve', async () => { + const responsePromise = client.emails.events.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/emails/render.test.ts b/tests/api-resources/emails/render.test.ts new file mode 100644 index 0000000..0cbf3fe --- /dev/null +++ b/tests/api-resources/emails/render.test.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource render', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.render.create({ templateId: '496' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.render.create({ + templateId: '496', + variables: { foo: 'string' }, + }); + }); +}); diff --git a/tests/api-resources/emails/settings.test.ts b/tests/api-resources/emails/settings.test.ts new file mode 100644 index 0000000..dade53f --- /dev/null +++ b/tests/api-resources/emails/settings.test.ts @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource settings', () => { + test('retrieve', async () => { + const responsePromise = client.emails.settings.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update', async () => { + const responsePromise = client.emails.settings.update(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.emails.settings.update( + { defaultFromName: 'defaultFromName' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/emails/stats.test.ts b/tests/api-resources/emails/stats.test.ts new file mode 100644 index 0000000..8b6d7ab --- /dev/null +++ b/tests/api-resources/emails/stats.test.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource stats', () => { + test('retrieve', async () => { + const responsePromise = client.emails.stats.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.emails.stats.retrieve( + { + groupBy: 'day', + period: '7d', + projectId: 'projectId', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/emails/suppressions-check.test.ts b/tests/api-resources/emails/suppressions-check.test.ts new file mode 100644 index 0000000..26871b3 --- /dev/null +++ b/tests/api-resources/emails/suppressions-check.test.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource suppressionsCheck', () => { + test('retrieve: only required params', async () => { + const responsePromise = client.emails.suppressionsCheck.retrieve({ email: 'email' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.emails.suppressionsCheck.retrieve({ + email: 'email', + projectId: 'projectId', + }); + }); +}); diff --git a/tests/api-resources/emails/suppressions.test.ts b/tests/api-resources/emails/suppressions.test.ts new file mode 100644 index 0000000..c3f8f9c --- /dev/null +++ b/tests/api-resources/emails/suppressions.test.ts @@ -0,0 +1,65 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource suppressions', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.suppressions.create({ email: 'dev@stainless.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.suppressions.create({ email: 'dev@stainless.com' }); + }); + + test('retrieve', async () => { + const responsePromise = client.emails.suppressions.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.emails.suppressions.retrieve( + { + cursor: 'cursor', + limit: 1, + projectId: 'projectId', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('delete: only required params', async () => { + const responsePromise = client.emails.suppressions.delete({ email: 'email' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('delete: required and optional params', async () => { + const response = await client.emails.suppressions.delete({ email: 'email', projectId: 'projectId' }); + }); +}); diff --git a/tests/api-resources/emails/template.test.ts b/tests/api-resources/emails/template.test.ts new file mode 100644 index 0000000..2558da4 --- /dev/null +++ b/tests/api-resources/emails/template.test.ts @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource template', () => { + test('create: only required params', async () => { + const responsePromise = client.emails.template.create({ + from: 'from', + templateId: '496', + to: ['dev@stainless.com'], + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.emails.template.create({ + from: 'from', + templateId: '496', + to: ['dev@stainless.com'], + attachments: [ + { + content: 'content', + contentType: 'application/pdf', + filename: 'filename', + }, + ], + bcc: [], + cc: [], + headers: { foo: 'J!Q0Ok0bzJb7' }, + replyTo: 'dev@stainless.com', + subject: 'subject', + tags: { foo: '_1' }, + text: 'text', + variables: { foo: 'string' }, + 'idempotency-key': 'idempotency-key', + }); + }); +}); diff --git a/tests/api-resources/templates/schema.test.ts b/tests/api-resources/templates/schema.test.ts new file mode 100644 index 0000000..5241672 --- /dev/null +++ b/tests/api-resources/templates/schema.test.ts @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource schema', () => { + test('retrieve', async () => { + const responsePromise = client.templates.schema.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.templates.schema.retrieve( + { displayMode: 'email', simple: true }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); diff --git a/tests/api-resources/templates/validate.test.ts b/tests/api-resources/templates/validate.test.ts new file mode 100644 index 0000000..70d9bbb --- /dev/null +++ b/tests/api-resources/templates/validate.test.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource validate', () => { + test('create: only required params', async () => { + const responsePromise = client.templates.validate.create({ design: { foo: 'bar' } }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.templates.validate.create({ + design: { foo: 'bar' }, + customTools: [ + { + options: { foo: { options: {} } }, + slug: 'slug', + label: 'label', + supportedDisplayModes: ['email'], + type: 'type', + values: { foo: 'bar' }, + }, + ], + displayMode: 'email', + migrate: true, + schema: 'full', + }); + }); +}); diff --git a/tests/api-resources/webhooks/rotate-secret.test.ts b/tests/api-resources/webhooks/rotate-secret.test.ts new file mode 100644 index 0000000..f1f7557 --- /dev/null +++ b/tests/api-resources/webhooks/rotate-secret.test.ts @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource rotateSecret', () => { + test('create', async () => { + const responsePromise = client.webhooks.rotateSecret.create('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/webhooks/webhooks.test.ts b/tests/api-resources/webhooks/webhooks.test.ts new file mode 100644 index 0000000..6505153 --- /dev/null +++ b/tests/api-resources/webhooks/webhooks.test.ts @@ -0,0 +1,88 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource webhooks', () => { + test('create: only required params', async () => { + const responsePromise = client.webhooks.create({ url: 'https://example.com' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.webhooks.create({ + url: 'https://example.com', + active: true, + events: ['email.sent'], + }); + }); + + test('retrieve', async () => { + const responsePromise = client.webhooks.retrieve('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update', async () => { + const responsePromise = client.webhooks.update('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.webhooks.update( + 'id', + { + active: true, + events: ['email.sent'], + url: 'https://example.com', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); + + test('list', async () => { + const responsePromise = client.webhooks.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('delete', async () => { + const responsePromise = client.webhooks.delete('id'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); From d92f9cf42ffa4deb9a078ab896c3320ec8e467f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:13:11 +0000 Subject: [PATCH 114/118] feat(api): api update --- .stats.yml | 8 +- api.md | 10 ++ src/client.ts | 12 +++ src/resources/blocks.ts | 143 +++++++++++++++++++++++++++++ src/resources/index.ts | 1 + tests/api-resources/blocks.test.ts | 40 ++++++++ 6 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 src/resources/blocks.ts create mode 100644 tests/api-resources/blocks.test.ts diff --git a/.stats.yml b/.stats.yml index b5c4710..022e0e6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 50 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-112356d364a4c9b7cf7f8d272937732568d750f9574ecc0c07516eca112cdddf.yml -openapi_spec_hash: 283e15c9bc02c4d7c69189873b1da9d4 -config_hash: c65b47a2f20400d392a50837c0a10945 +configured_endpoints: 51 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-92f6b863c3ee96cd2d4dd5b6a38d2820b0a56bf1006a0429a3d6fb756530d781.yml +openapi_spec_hash: 204d0db45842998a761ec507960eae9f +config_hash: 31bbe4c50af7bd9aea5582d9a2ab786d diff --git a/api.md b/api.md index 66d02c4..76404ab 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,13 @@ +# Blocks + +Types: + +- BlockRetrieveResponse + +Methods: + +- client.blocks.retrieve({ ...params }) -> BlockRetrieveResponse + # Domains Types: diff --git a/src/client.ts b/src/client.ts index be8e975..dd24fe1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -19,6 +19,7 @@ import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { BlockRetrieveParams, BlockRetrieveResponse, Blocks } from './resources/blocks'; import { EditorSessionCreateParams, EditorSessionCreateResponse, @@ -852,6 +853,10 @@ export class Unlayer { static toFile = Uploads.toFile; + /** + * Reusable design blocks — list shared project blocks and end-user saved blocks for backup, migration, and usage reporting. + */ + blocks: API.Blocks = new API.Blocks(this); domains: API.Domains = new API.Domains(this); editorSessions: API.EditorSessions = new API.EditorSessions(this); emails: API.Emails = new API.Emails(this); @@ -871,6 +876,7 @@ export class Unlayer { workspaces: API.Workspaces = new API.Workspaces(this); } +Unlayer.Blocks = Blocks; Unlayer.Domains = Domains; Unlayer.EditorSessions = EditorSessions; Unlayer.Emails = Emails; @@ -886,6 +892,12 @@ export declare namespace Unlayer { export import CursorPage = Pagination.CursorPage; export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { + Blocks as Blocks, + type BlockRetrieveResponse as BlockRetrieveResponse, + type BlockRetrieveParams as BlockRetrieveParams, + }; + export { Domains as Domains, type DomainCreateResponse as DomainCreateResponse, diff --git a/src/resources/blocks.ts b/src/resources/blocks.ts new file mode 100644 index 0000000..d007356 --- /dev/null +++ b/src/resources/blocks.ts @@ -0,0 +1,143 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +/** + * Reusable design blocks — list shared project blocks and end-user saved blocks for backup, migration, and usage reporting. + */ +export class Blocks extends APIResource { + /** + * List blocks with cursor-based pagination. Returns both shared project blocks and + * blocks saved by end-users; each user-saved block carries the userId it was saved + * under (null for shared blocks), so usage can be aggregated per end-user without + * enumerating user IDs. Returns blocks in descending order by creation. + */ + retrieve( + query: BlockRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/v3/blocks', { query, ...options }); + } +} + +export interface BlockRetrieveResponse { + data: Array; + + /** + * Whether there are more results after this page + */ + has_more: boolean; + + /** + * Cursor for the next page. Null if no more results. + */ + next_cursor?: string | null; +} + +export namespace BlockRetrieveResponse { + export interface Data { + /** + * Block ID + */ + id?: string; + + /** + * Block category + */ + category?: string; + + createdAt?: string; + + /** + * The block design JSON. Omitted when includeData=false is passed. + */ + data?: { [key: string]: unknown }; + + /** + * Display mode the block was saved for: email, web, popup, or document + */ + displayMode?: string; + + /** + * Whether the block is currently a synced block + */ + isSyncEnabled?: boolean; + + /** + * Synced-block ID referenced by designs using this block. Null when the block has + * never been synced. + */ + syncId?: string | null; + + /** + * Block tags + */ + tags?: Array; + + /** + * URL of the auto-generated block thumbnail, if available + */ + thumbnailUrl?: string | null; + + updatedAt?: string; + + /** + * End-user ID the block was saved under (the user id your app passes to the + * editor). Null for shared project blocks. + */ + userId?: string | null; + } +} + +export interface BlockRetrieveParams { + /** + * Filter by category (case-insensitive search) + */ + category?: string; + + /** + * Pagination cursor from previous response + */ + cursor?: string; + + /** + * Filter by display mode + */ + displayMode?: 'email' | 'web' | 'popup' | 'document'; + + /** + * Include the block design JSON in each item. Pass false for lightweight sweeps + * (e.g. usage reports). + */ + includeData?: boolean; + + /** + * Number of blocks to return (1-100) + */ + limit?: number; + + /** + * The project ID to list blocks for + */ + projectId?: string; + + /** + * Filter by block ownership: shared project blocks, end-user saved blocks, or both + */ + scope?: 'all' | 'shared' | 'user'; + + /** + * Only blocks saved by this end-user (exact match on the user id your app passes + * to the editor) + */ + userId?: string; +} + +export declare namespace Blocks { + export { + type BlockRetrieveResponse as BlockRetrieveResponse, + type BlockRetrieveParams as BlockRetrieveParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 6fadd48..c40edde 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { Blocks, type BlockRetrieveResponse, type BlockRetrieveParams } from './blocks'; export { Domains, type DomainCreateResponse, diff --git a/tests/api-resources/blocks.test.ts b/tests/api-resources/blocks.test.ts new file mode 100644 index 0000000..6520e67 --- /dev/null +++ b/tests/api-resources/blocks.test.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Unlayer from '@unlayer/sdk'; + +const client = new Unlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource blocks', () => { + test('retrieve', async () => { + const responsePromise = client.blocks.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.blocks.retrieve( + { + category: 'category', + cursor: 'cursor', + displayMode: 'email', + includeData: true, + limit: 1, + projectId: 'projectId', + scope: 'all', + userId: 'userId', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Unlayer.NotFoundError); + }); +}); From 68e9d2c1600e6ba3be7eaa0c005b13f6269129fe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:16:32 +0000 Subject: [PATCH 115/118] feat(api): api update --- .stats.yml | 4 ++-- src/resources/projects/ai-credits-usage.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 022e0e6..e8a0a73 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-92f6b863c3ee96cd2d4dd5b6a38d2820b0a56bf1006a0429a3d6fb756530d781.yml -openapi_spec_hash: 204d0db45842998a761ec507960eae9f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-268cac778fb55e8dafe406262f0ead04728e2bafb672ca60161f985f942cf4f8.yml +openapi_spec_hash: e5ac63432486a66a5b5e101151bd95f4 config_hash: 31bbe4c50af7bd9aea5582d9a2ab786d diff --git a/src/resources/projects/ai-credits-usage.ts b/src/resources/projects/ai-credits-usage.ts index 38bec77..77631f9 100644 --- a/src/resources/projects/ai-credits-usage.ts +++ b/src/resources/projects/ai-credits-usage.ts @@ -11,8 +11,10 @@ import { path } from '../../internal/utils/path'; export class AICreditsUsage extends APIResource { /** * Returns AI credit consumption for the project, broken down by end user and - * feature type. Filterable by date range, end user, and feature type. Defaults to - * the current billing period. Only credit counts are returned; token counts, model + * feature type. Filterable by date range, end user, and feature type. Usage is + * updated near real time and grouped by the UTC date when the AI activity + * occurred. Recent activity may take a short time to appear. Defaults to the + * current billing period. Only credit counts are returned; token counts, model * names, and costs are never exposed. Per-end-user attribution requires the * partner to pass `endUserId` on editor initialization. */ From 84d125e2ba5922cc46ff9c792f4e028bbde5bcf7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 20:32:17 +0000 Subject: [PATCH 116/118] feat(api): api update --- .stats.yml | 4 ++-- src/resources/templates/generate.ts | 27 ++++++++++++++++----------- src/resources/templates/import.ts | 6 +++--- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index e8a0a73..203960b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-268cac778fb55e8dafe406262f0ead04728e2bafb672ca60161f985f942cf4f8.yml -openapi_spec_hash: e5ac63432486a66a5b5e101151bd95f4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-d939bc17efff27c8a66b48b80e6ef9d5790105eed03bbddf57642c65a22ad16c.yml +openapi_spec_hash: f60ac2085adb51c5a437684028a065b2 config_hash: 31bbe4c50af7bd9aea5582d9a2ab786d diff --git a/src/resources/templates/generate.ts b/src/resources/templates/generate.ts index d5e60bf..8420147 100644 --- a/src/resources/templates/generate.ts +++ b/src/resources/templates/generate.ts @@ -50,8 +50,8 @@ export interface GenerateCreateResponse { output?: GenerateCreateResponse.Output; /** - * Aggregate token usage for the turn when exposed by the caller. Builder copilot - * endpoints expose it only in local/dev/QA and omit it in staging/production. + * Aggregate token usage and billed AI credits for the turn. Estimated provider + * cost is included only by builder copilot endpoints in local/dev/QA. */ usage?: GenerateCreateResponse.Usage; } @@ -63,7 +63,7 @@ export namespace GenerateCreateResponse { */ export interface Model { /** - * Resolved model id, e.g. "claude-opus-4-7". + * Resolved model id, e.g. "claude-opus-5". */ id?: string; @@ -90,10 +90,16 @@ export namespace GenerateCreateResponse { } /** - * Aggregate token usage for the turn when exposed by the caller. Builder copilot - * endpoints expose it only in local/dev/QA and omit it in staging/production. + * Aggregate token usage and billed AI credits for the turn. Estimated provider + * cost is included only by builder copilot endpoints in local/dev/QA. */ export interface Usage { + /** + * Marked-up integer AI credits used by the complete turn, including failover + * attempts. + */ + aiCreditsUsed?: number; + cachedInputTokens?: number; estimatedCostMicroUsd?: number; @@ -111,10 +117,10 @@ export namespace GenerateCreateResponse { export interface GenerateCreateParams { /** * Body param: Conversation messages in chronological order, capped at 10 messages. - * The last `user` message is the prompt for this turn; any earlier - * `user`/`assistant` text turns are forwarded to the model as prior chat context. - * A `user` message may carry a predefined prompt action via `metadata.action.id` - * (e.g. SPELLING, REPHRASE). + * The last `user` message is the prompt for this turn; the newest earlier + * `user`/`assistant` turns are forwarded within a 12,000-character aggregate + * history budget. A `user` message may carry a predefined prompt action via + * `metadata.action.id` (e.g. SPELLING, REPHRASE). */ messages: Array; @@ -153,8 +159,7 @@ export interface GenerateCreateParams { /** * Body param: Preferred AI model in "provider/id" form, e.g. - * "anthropic/claude-opus-4-7". Optional — server resolves a default per output - * kind. + * "anthropic/claude-opus-5". Optional — server resolves a default per output kind. */ model?: string; } diff --git a/src/resources/templates/import.ts b/src/resources/templates/import.ts index 4e00541..dbffd65 100644 --- a/src/resources/templates/import.ts +++ b/src/resources/templates/import.ts @@ -85,10 +85,10 @@ export interface ImportCreateParams { /** * Body param: Preferred AI model. Accepts a provider/model string (e.g. - * "anthropic/claude-opus-4-7", "openai/gpt-5.5"), a bare provider ("anthropic", + * "anthropic/claude-opus-5", "openai/gpt-5.6-luna"), a bare provider ("anthropic", * "openai") which uses that provider's default model, or a bare model id - * ("claude-opus-4-7", "gpt-5.5") with the provider inferred from the name. - * Optional — defaults to anthropic/claude-opus-4-7. + * ("claude-opus-5", "gpt-5.6-luna") with the provider inferred from the name. + * Optional — defaults to anthropic/claude-opus-5. */ model?: string; } From 44742950f85be97a2decf67a081f118dfb77665d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 20:59:35 +0000 Subject: [PATCH 117/118] feat(api): api update --- .stats.yml | 4 +-- src/resources/templates/generate.ts | 34 +++++++++++++++++++ .../api-resources/templates/generate.test.ts | 13 +++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 203960b..15f8edc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-d939bc17efff27c8a66b48b80e6ef9d5790105eed03bbddf57642c65a22ad16c.yml -openapi_spec_hash: f60ac2085adb51c5a437684028a065b2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-a96fca229b9908a56f32846b8ac997932655bc35644c267004c3bada5ed3d9fe.yml +openapi_spec_hash: e3c4bccf1cf35f4ba5ec3d8ba207c689 config_hash: 31bbe4c50af7bd9aea5582d9a2ab786d diff --git a/src/resources/templates/generate.ts b/src/resources/templates/generate.ts index 8420147..8220af9 100644 --- a/src/resources/templates/generate.ts +++ b/src/resources/templates/generate.ts @@ -223,6 +223,8 @@ export namespace GenerateCreateParams { export interface Context { availableTools?: Array; + brand?: Context.Brand; + customTools?: Array; fullDesign?: { [key: string]: unknown } | null; @@ -233,6 +235,38 @@ export namespace GenerateCreateParams { } export namespace Context { + export interface Brand { + colors?: Brand.Colors; + + companyName?: string; + + fonts?: Brand.Fonts; + + guidelines?: string; + + productDescription?: string; + + targetAudience?: string; + + voice?: string; + } + + export namespace Brand { + export interface Colors { + accent?: string; + + primary?: string; + + secondary?: string; + } + + export interface Fonts { + body?: string; + + heading?: string; + } + } + export interface CustomTool { options: { [key: string]: unknown }; diff --git a/tests/api-resources/templates/generate.test.ts b/tests/api-resources/templates/generate.test.ts index e383821..ba969ba 100644 --- a/tests/api-resources/templates/generate.test.ts +++ b/tests/api-resources/templates/generate.test.ts @@ -46,6 +46,19 @@ describe('resource generate', () => { projectId: 'projectId', context: { availableTools: ['string'], + brand: { + colors: { + accent: 'accent', + primary: 'primary', + secondary: 'secondary', + }, + companyName: 'companyName', + fonts: { body: 'body', heading: 'heading' }, + guidelines: 'guidelines', + productDescription: 'productDescription', + targetAudience: 'targetAudience', + voice: 'voice', + }, customTools: [ { options: { foo: 'bar' }, From 15ad050a08619859c5aac38327b3a46b6b430029 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:18:18 +0000 Subject: [PATCH 118/118] feat(api): api update --- .stats.yml | 4 ++-- src/resources/templates/generate.ts | 18 +++++++++++++++++- tests/api-resources/templates/generate.test.ts | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 15f8edc..5f064af 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-a96fca229b9908a56f32846b8ac997932655bc35644c267004c3bada5ed3d9fe.yml -openapi_spec_hash: e3c4bccf1cf35f4ba5ec3d8ba207c689 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/unlayer/unlayer-231dfb6902a557101992c19fd91a3cf6d4d187b06c9d6b20f2b70d7df77e664a.yml +openapi_spec_hash: 487c5e8289dd85c5d412f6635c2bc3fc config_hash: 31bbe4c50af7bd9aea5582d9a2ab786d diff --git a/src/resources/templates/generate.ts b/src/resources/templates/generate.ts index 8220af9..d835af5 100644 --- a/src/resources/templates/generate.ts +++ b/src/resources/templates/generate.ts @@ -221,9 +221,11 @@ export namespace GenerateCreateParams { } export interface Context { + availableFonts?: Array; + availableTools?: Array; - brand?: Context.Brand; + brand?: Context.Brand | null; customTools?: Array; @@ -235,6 +237,12 @@ export namespace GenerateCreateParams { } export namespace Context { + export interface AvailableFont { + label: string; + + value: string; + } + export interface Brand { colors?: Brand.Colors; @@ -244,6 +252,8 @@ export namespace GenerateCreateParams { guidelines?: string; + logos?: Brand.Logos; + productDescription?: string; targetAudience?: string; @@ -265,6 +275,12 @@ export namespace GenerateCreateParams { heading?: string; } + + export interface Logos { + primary?: string; + + secondary?: string; + } } export interface CustomTool { diff --git a/tests/api-resources/templates/generate.test.ts b/tests/api-resources/templates/generate.test.ts index ba969ba..476e271 100644 --- a/tests/api-resources/templates/generate.test.ts +++ b/tests/api-resources/templates/generate.test.ts @@ -45,6 +45,7 @@ describe('resource generate', () => { }, projectId: 'projectId', context: { + availableFonts: [{ label: 'x', value: 'x' }], availableTools: ['string'], brand: { colors: { @@ -55,6 +56,7 @@ describe('resource generate', () => { companyName: 'companyName', fonts: { body: 'body', heading: 'heading' }, guidelines: 'guidelines', + logos: { primary: 'https://example.com', secondary: 'https://example.com' }, productDescription: 'productDescription', targetAudience: 'targetAudience', voice: 'voice',