diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fafe63a..b4e179b 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/**' @@ -17,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/spreadsheet-api-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 @@ -36,7 +38,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/spreadsheet-api-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 @@ -55,14 +57,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/spreadsheet-api-typescript' + if: |- + github.repository == 'stainless-sdks/spreadsheet-api-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/spreadsheet-api-typescript' + if: |- + github.repository == 'stainless-sdks/spreadsheet-api-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index d288ed0..45dc5b6 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.GRID_NPM_TOKEN || secrets.NPM_TOKEN }} - 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 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bf6b571..0d1bebe 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.5.4" + ".": "1.6.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 92361b1..9d4d8d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## 1.6.0 (2026-04-29) + +Full Changelog: [v1.5.4...v1.6.0](https://github.com/GRID-is/api-sdk-ts/compare/v1.5.4...v1.6.0) + +### Features + +* support setting headers via env ([f13bb8b](https://github.com/GRID-is/api-sdk-ts/commit/f13bb8babbe12f265957417330b8d6470f951c97)) + + +### Bug Fixes + +* **client:** preserve URL params already embedded in path ([f774112](https://github.com/GRID-is/api-sdk-ts/commit/f774112e955928024384688ffc43ab24af317517)) + + +### Chores + +* **ci:** skip lint on metadata-only changes ([85f6a50](https://github.com/GRID-is/api-sdk-ts/commit/85f6a50e55e9ea0e50ef6b10c796eec4b638861a)) +* **ci:** skip uploading artifacts on stainless-internal branches ([ccfeebb](https://github.com/GRID-is/api-sdk-ts/commit/ccfeebb085a7c9ca5a0d24ba5ee175700981d653)) +* **format:** run eslint and prettier separately ([b38d95e](https://github.com/GRID-is/api-sdk-ts/commit/b38d95e03840b8204978ea8f29e94e0bf7a0ba12)) +* **internal:** codegen related update ([f17ba61](https://github.com/GRID-is/api-sdk-ts/commit/f17ba61fa0eecce6a8d675b45a1d02e9e0b26a01)) +* **internal:** codegen related update ([de5d2e8](https://github.com/GRID-is/api-sdk-ts/commit/de5d2e8f039630d1b172b1a84c53d7bcaa0b8e4b)) +* **internal:** codegen related update ([cdb0d9f](https://github.com/GRID-is/api-sdk-ts/commit/cdb0d9fe5e112d35bb393fd1253e5140efa79242)) +* **internal:** codegen related update ([cf1e298](https://github.com/GRID-is/api-sdk-ts/commit/cf1e2984941f530ac0f3250b1e11fef64c828037)) +* **internal:** codegen related update ([862a3cc](https://github.com/GRID-is/api-sdk-ts/commit/862a3cc96242474206647d4bca2181001b1bbd72)) +* **internal:** codegen related update ([a81a9a6](https://github.com/GRID-is/api-sdk-ts/commit/a81a9a6fdc993c81346b7743b19fbaed6680ae4d)) +* **internal:** more robust bootstrap script ([759b9c9](https://github.com/GRID-is/api-sdk-ts/commit/759b9c90714c74d804172951063d337cc6f1020b)) +* **internal:** move stringifyQuery implementation to internal function ([8808754](https://github.com/GRID-is/api-sdk-ts/commit/8808754e3e69ac2da2ce730c67b125f8dd15982b)) +* **internal:** tweak CI branches ([2a0aacc](https://github.com/GRID-is/api-sdk-ts/commit/2a0aacc8f4687f478091f5df519bea008cc6e75b)) +* **internal:** update dependencies to address dependabot vulnerabilities ([32288f2](https://github.com/GRID-is/api-sdk-ts/commit/32288f2f780637c8c26af93b43ab41886645db14)) +* **internal:** update gitignore ([13c70b2](https://github.com/GRID-is/api-sdk-ts/commit/13c70b26a33b80c5ae74b105c2d8385c83cafae5)) +* update placeholder string ([399fbc7](https://github.com/GRID-is/api-sdk-ts/commit/399fbc71da55d63d6790d41951d4913e4d9ab803)) + + +### Documentation + +* update examples ([963bd9d](https://github.com/GRID-is/api-sdk-ts/commit/963bd9dd114f47f8525638ea9492cad77916be3c)) + ## 1.5.4 (2026-02-24) Full Changelog: [v1.5.3...v1.5.4](https://github.com/GRID-is/api-sdk-ts/compare/v1.5.3...v1.5.4) diff --git a/README.md b/README.md index 7d7fefd..fe06c33 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,7 @@ const client = new Grid({ apiKey: process.env['GRID_API_TOKEN'], // This is the default and can be omitted }); -const response = await client.workbooks.query('YOUR_WORKBOOK_ID', { - read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'], -}); +const response = await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }); console.log(response.read); ``` @@ -45,7 +43,7 @@ const client = new Grid({ apiKey: process.env['GRID_API_TOKEN'], // This is the default and can be omitted }); -const params: Grid.WorkbookQueryParams = { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }; +const params: Grid.WorkbookQueryParams = { read: ['A1:A4'] }; const response: Grid.WorkbookQueryResponse = await client.workbooks.query( 'YOUR_WORKBOOK_ID', params, @@ -92,7 +90,7 @@ a subclass of `APIError` will be thrown: ```ts const response = await client.workbooks - .query('YOUR_WORKBOOK_ID', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }) + .query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }) .catch(async (err) => { if (err instanceof Grid.APIError) { console.log(err.status); // 400 @@ -133,7 +131,7 @@ const client = new Grid({ }); // Or, configure per-request: -await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }, { +await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }, { maxRetries: 5, }); ``` @@ -150,7 +148,7 @@ const client = new Grid({ }); // Override per-request: -await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }, { +await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }, { timeout: 5 * 1000, }); ``` @@ -203,7 +201,7 @@ const client = new Grid(); const response = await client.workbooks.query( 'YOUR_WORKBOOK_ID', - { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }, + { read: ['A1:A4'] }, { headers: { 'X-Client-Name': 'My-Custom-Value' } }, ); ``` @@ -222,14 +220,12 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Grid(); -const response = await client.workbooks - .query('YOUR_WORKBOOK_ID', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }) - .asResponse(); +const response = await client.workbooks.query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }).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.workbooks - .query('YOUR_WORKBOOK_ID', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }) + .query('YOUR_WORKBOOK_ID', { read: ['A1:A4'] }) .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(response.read); diff --git a/eslint.config.mjs b/eslint.config.mjs index 6c4dd68..527d6cb 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 4a41a45..bc0d9de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@grid-is/api", - "version": "1.5.4", + "version": "1.6.0", "description": "The official TypeScript library for the Grid API", "author": "Grid ", "types": "dist/index.d.ts", @@ -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", @@ -50,6 +49,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/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 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/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 5788210..234f31d 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'; @@ -191,6 +192,18 @@ export class Grid { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('GRID_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; @@ -237,21 +250,8 @@ export class Grid { /** * 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.GridError( - `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 { @@ -283,12 +283,13 @@ export class Grid { : 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)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); @@ -617,9 +618,9 @@ export class Grid { } } - // 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); } @@ -752,7 +753,7 @@ export class Grid { ) { 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 }); @@ -778,7 +779,13 @@ export class Grid { static toFile = Uploads.toFile; + /** + * Interact with workbooks and their data + */ workbooks: API.Workbooks = new API.Workbooks(this); + /** + * Interact with workbooks and their data + */ beta: API.Beta = new API.Beta(this); } 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/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/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; }; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 0000000..7aca9c6 --- /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 { GridError } 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 GridError( + `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/src/resources/beta.ts b/src/resources/beta.ts index 03efd15..93a6938 100644 --- a/src/resources/beta.ts +++ b/src/resources/beta.ts @@ -5,9 +5,17 @@ import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Interact with workbooks and their data + */ export class Beta extends APIResource { /** * Retrieve labels automatically detected for cells and ranges in the workbook. + * + * @example + * ```ts + * const response = await client.beta.getWorkbookLabels('id'); + * ``` */ getWorkbookLabels(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v1/workbooks/${id}/labels`, options); @@ -15,6 +23,13 @@ export class Beta extends APIResource { /** * Retrieve labels automatically detected for cells and ranges in the workbook. + * + * @example + * ```ts + * const response = await client.beta.getWorkbookParameters( + * 'id', + * ); + * ``` */ getWorkbookParameters(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v1/workbooks/${id}/parameters`, options); @@ -22,6 +37,13 @@ export class Beta extends APIResource { /** * Search data labels across all spreadsheets uploaded to an account + * + * @example + * ```ts + * const response = await client.beta.searchLabels({ + * query: 'profit', + * }); + * ``` */ searchLabels(body: BetaSearchLabelsParams, options?: RequestOptions): APIPromise { return this._client.post('/v1/workbooks/search/labels', { body, ...options }); diff --git a/src/resources/workbooks.ts b/src/resources/workbooks.ts index cf7b0f1..533a718 100644 --- a/src/resources/workbooks.ts +++ b/src/resources/workbooks.ts @@ -9,6 +9,9 @@ import { RequestOptions } from '../internal/request-options'; import { multipartFormRequestOptions } from '../internal/uploads'; import { path } from '../internal/utils/path'; +/** + * Interact with workbooks and their data + */ export class Workbooks extends APIResource { /** * List the workbooks linked to an account. @@ -80,7 +83,7 @@ export class Workbooks extends APIResource { * @example * ```ts * const response = await client.workbooks.query('id', { - * read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'], + * read: ['A1:A4'], * }); * ``` */ diff --git a/src/version.ts b/src/version.ts index 8defa1b..8fe4c2e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '1.5.4'; // x-release-please-version +export const VERSION = '1.6.0'; // x-release-please-version diff --git a/tests/api-resources/workbooks.test.ts b/tests/api-resources/workbooks.test.ts index a2fe2f2..5e7c6d4 100644 --- a/tests/api-resources/workbooks.test.ts +++ b/tests/api-resources/workbooks.test.ts @@ -55,7 +55,7 @@ describe('resource workbooks', () => { // Mock server tests are disabled test.skip('query: only required params', async () => { - const responsePromise = client.workbooks.query('id', { read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'] }); + const responsePromise = client.workbooks.query('id', { read: ['A1:A4'] }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -68,7 +68,7 @@ describe('resource workbooks', () => { // Mock server tests are disabled test.skip('query: required and optional params', async () => { const response = await client.workbooks.query('id', { - read: ['A1', 'Sheet2!B3', '=SUM(A1:A4)'], + read: ['A1:A4'], apply: [{ target: 'A2', value: 1234 }], goalSeek: { controlCell: 'Sheet1!A1:B2', @@ -128,7 +128,7 @@ describe('resource workbooks', () => { // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.workbooks.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), + file: await toFile(Buffer.from('Example data'), 'README.md'), }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -142,7 +142,7 @@ describe('resource workbooks', () => { // Mock server tests are disabled test.skip('upload: required and optional params', async () => { const response = await client.workbooks.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), + file: await toFile(Buffer.from('Example data'), 'README.md'), }); }); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 78019c2..655c5cd 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 { Grid } from '@grid-is/api'; - -const { stringifyQuery } = Grid.prototype as any; +import { stringifyQuery } from '@grid-is/api/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); }); diff --git a/yarn.lock b/yarn.lock index fc9f262..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" @@ -1219,18 +1214,10 @@ 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: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== +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== dependencies: balanced-match "^1.0.0" @@ -1395,11 +1382,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" @@ -1528,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" @@ -1687,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" @@ -2600,26 +2569,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" @@ -2868,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" @@ -3171,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"