diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 674fb6e2..e8108514 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,6 +9,8 @@ on: - 'typedoc.json' - 'package.json' - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - 'patches/**' - '.github/workflows/docs.yml' workflow_dispatch: diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d32fd5..385baaab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,48 +1,33 @@ # Trello.js changelog -## Unreleased +## v2.3.0 (2026-10-11) -### Fixed - -- `Organization` gained `trial`, the object Trello now returns on every workspace: `{ eligible: boolean, endDate: Date | null }`. It was silently stripped in normal mode and raised `ZodError: unrecognized_keys` in strict/audit mode (`pnpm audit:schemas`), breaking `getMemberOrganizations`. `endDate` reads as `null` on every workspace reachable from this account, so its populated shape is still unobserved. -- `Prefs.invitations` is now `string` instead of `unknown`, which it was typed on the assumption the name implied a list. Trello sends `"members"` on every board reachable from this account, so the value was there all along and unusable without a cast. - -### Deprecated - -- **`Organization.eligibleForTrial`.** Trello stopped sending it, and `trial.eligible` replaces it. The field stays optional so reading it still compiles, and goes at the next major version. - -### Added - -- **Request cancellation.** Every endpoint method takes an optional last argument, `{ signal }`, typed by the new `RequestOptions` exported from `trello.js/core`. The signal reaches `fetch` unchanged, and it also cuts short a 429 backoff still counting down instead of letting it run its full 2/4/8 seconds. The argument is optional everywhere, so existing calls are unaffected; `batch.run` is the one exception, since its requests share a single HTTP call. - - ```ts - const board = await trello.boards.getBoard({ id }, { signal: AbortSignal.timeout(5_000) }); - ``` - -- `SendRequestOptions` gained `signal`, so a custom `Client` implementation receives it too. -- **`entities` on the five actions-list endpoints.** `getBoardActions`, `getCardActions`, `getListActions`, `getMemberActions` and `getOrganizationActions` take `entities: boolean`. Trello sends `Action.entities` only when it is asked for, so the field the schema declared was unreachable through this client. +**Read this one if you touch `action.data` anywhere.** `Action` now combines twenty-nine typed action branches with an open fallback, `ActionUnknown`, whose `data` is `unknown`. Reading `action.data.text` directly stops compiling. This is a compile break in a minor release: validate an action with its exported branch schema, such as `ActionCommentCardSchema.parse(action)`, before reading its data. Checking `action.type` alone is insufficient because the fallback accepts any action type, including known ones. Casting to `ActionUnknown` keeps `data` unknown. ### Changed -- **`Action` is now a union discriminated on `type`.** Twenty-nine action types carry their own `data` shape, so `action.data.text` on a `commentCard` is a `string` rather than `any`, and reading a field that type does not have is a compile error instead of `undefined` at runtime. +- **Twenty-nine action types have dedicated `data` schemas.** Parsing a comment with `ActionCommentCardSchema` returns an `ActionCommentCard`, whose `data.text` is a `string`. Reading a field that this branch does not have is a compile error. ```ts + import { ActionCommentCardSchema } from 'trello.js/models'; + const action = await trello.actions.getAction({ id }); if (action.type === 'commentCard') { - console.log(action.data.text); + const comment = ActionCommentCardSchema.parse(action); + console.log(comment.data.text); } ``` - This breaks code that reads `action.data.` without narrowing first: `data` no longer has an index signature on the branched types. Narrowing on `type` is the fix, and it is the only one, because the field genuinely is not there on the other twenty-eight. + A branch's `data` has no index signature. Its schema checks both the action type and the data shape, and throws `ZodError` when either does not match. The open fallback has `type: string`, so an `if` on `type` cannot exclude it from the `Action` union; the branch schema provides the validated type. - Each branch is its own exported model and schema, `ActionCommentCard` with `ActionCommentCardSchema` and so on for all twenty-nine, built over the shared `ActionDataBoard`, `ActionDataCard`, `ActionDataList`, `ActionDataOrganization`, `ActionDataMember`, `ActionDataChecklist`, `ActionDataCustomField`, `ActionDataAttachment` and `ActionDataCheckItem` shapes. The branched types are `addAttachmentToCard`, `addChecklistToCard`, `addMemberToBoard`, `addMemberToCard`, `addToOrganizationBoard`, `commentCard`, `convertToCardFromCheckItem`, `copyCard`, `copyCommentCard`, `createBoard`, `createCard`, `createCustomField`, `createList`, `createOrganization`, `deleteAttachmentFromCard`, `deleteCard`, `makeAdminOfBoard`, `makeNormalMemberOfBoard`, `moveCardFromBoard`, `moveCardToBoard`, `moveListFromBoard`, `moveListToBoard`, `removeChecklistFromCard`, `removeMemberFromCard`, `updateBoard`, `updateCard`, `updateCheckItemStateOnCard`, `updateList` and `updateOrganization`. + Each branch is an exported model and schema of its own, `ActionCommentCard` with `ActionCommentCardSchema` and so on for all twenty-nine, built over the shared `ActionDataBoard`, `ActionDataCard`, `ActionDataList`, `ActionDataOrganization`, `ActionDataMember`, `ActionDataChecklist`, `ActionDataCustomField`, `ActionDataAttachment` and `ActionDataCheckItem` shapes. The branched types are `addAttachmentToCard`, `addChecklistToCard`, `addMemberToBoard`, `addMemberToCard`, `addToOrganizationBoard`, `commentCard`, `convertToCardFromCheckItem`, `copyCard`, `copyCommentCard`, `createBoard`, `createCard`, `createCustomField`, `createList`, `createOrganization`, `deleteAttachmentFromCard`, `deleteCard`, `makeAdminOfBoard`, `makeNormalMemberOfBoard`, `moveCardFromBoard`, `moveCardToBoard`, `moveListFromBoard`, `moveListToBoard`, `removeChecklistFromCard`, `removeMemberFromCard`, `updateBoard`, `updateCard`, `updateCheckItemStateOnCard`, `updateList` and `updateOrganization`. - The union ends in an open branch, `ActionUnknown`, whose `data` stays `Record`. An action type Trello adds tomorrow still parses, and an account whose history holds a type this list does not name still reads without a `ZodError`. The cost is that the schema cannot itself report drift inside a branched type, so a live test does that instead: it builds a workspace that produces most of the twenty-nine types, reads the account history as well, parses every action against its own branch, and prints the types it saw that no branch covers. + The union ends in an open branch, `ActionUnknown`, whose `data` is `unknown`. An action type Trello ships next month parses, and so does an account whose history holds one of the many types this list does not name. The fallback also accepts a known type whose data no longer matches its branch, so `ActionSchema` alone does not report that drift. Parsing with the branch schema does. A live suite builds a workspace that produces most of the twenty-nine types, reads the account history as well, parses every action against its own branch, and prints the types no branch covers without failing on them. - The shapes are observations, not readings of the spec, which documents `data` as a free-form object. A key present in every sample of its type is required and everything else is optional, on 249 actions from a purpose-built fixture and from this account's history. Adding or removing a label is not its own type, for one: it arrives as `updateCard` carrying `old.idLabels`. + The shapes are observations, not readings of the spec, which documents `data` as a free-form object. A key present in every sample of its type is required and everything else optional, across 249 actions from a purpose-built fixture and from account history. Adding or removing a label is not its own action type, for one: it arrives as `updateCard` carrying `old.idLabels`. -- **Fifteen fields that were typed `unknown`, `unknown[]` or `Record` now carry the shape the live API sends.** The shapes are observations rather than readings of the spec: only fields the live suites could populate were typed. Everything still unobservable from this account (`Organization.powerUps`, `Card.customFieldItems`, `Token.webhooks`, the enterprise and licence fields) is left exactly as it was. +- **Fifteen fields that were typed `unknown`, `unknown[]` or `Record` now carry the shape the live API sends.** These are observations rather than readings of the spec: only fields the live suites could populate were typed. Everything still unobservable from this account (`Organization.powerUps`, `Card.customFieldItems`, `Token.webhooks`, the enterprise and licence fields) is left exactly as it was. | Model | Field | Was | Now | | --- | --- | --- | --- | @@ -62,6 +47,33 @@ Nothing at the top level became required, because Trello's `fields` parameter prunes it and nothing but `id` survives `?fields=name`. Nested properties are not pruned, so ones present in every sample are typed as required, `Action.entities[].type` and `Organization.credits[].applied` among them. That is the one risk here: should Trello stop sending one, the response raises `ZodError` instead of parsing without it. +### Added + +- **Request cancellation.** Every endpoint method takes an optional last argument, `{ signal }`, typed by the new `RequestOptions` exported from `trello.js/core`. The signal reaches `fetch` unchanged, and it also cuts short a 429 backoff still counting down instead of letting it run its full 2/4/8 seconds. The argument is optional everywhere, so existing calls are unaffected; `batch.run` is the one exception, since its requests share a single HTTP call. + + ```ts + const board = await trello.boards.getBoard({ id }, { signal: AbortSignal.timeout(5_000) }); + ``` + +- `SendRequestOptions` gained `signal`, so a custom `Client` implementation receives it too. +- **`entities` on the five actions-list endpoints.** `getBoardActions`, `getCardActions`, `getListActions`, `getMemberActions` and `getOrganizationActions` take `entities: boolean`. Trello sends `Action.entities` only when it is asked for, so the field the schema declared was unreachable through this client. + +### Fixed + +- **All field selectors accept a string or an array of strings.** `getCardAttachment.fields` previously accepted only an array, while twenty-eight other `fields` / `*Fields` parameters accepted only a string. All 104 selectors now accept both a comma-separated string and an array, retaining documented field-name suggestions. Boolean flags such as `customFields` are unchanged. +- `Attachment` gained optional `aiSummary`, typed as `unknown` because only null has been observed. `BoardMyPrefs` gained optional boolean fields `aiGoogleGmailEnabled` and `showListGuide`, matching live responses. These new fields previously caused strict/audit mode to reject attachment and board preference responses. +- `Card` gained optional `lastSummaryChangeEventAt`, parsed as `Date | null`. Trello now sends the field, which was stripped in normal mode and rejected in strict/audit mode. Null is preserved and date strings are coerced to `Date`. Only null has been observed on this account; a raw-response live check guards the expected null-or-ISO-string shape before coercion can hide a different runtime type. +- **`TokenPermission.idModel` is a string.** Trello returns either `"*"` or a concrete resource ID. The spec describes a union of a Trello ID and `"*"`, but the generated open enum became a closed `"*"` enum in strict schema mode and rejected real token permissions. The schema now accepts both forms and checks that the value is a string. +- **`fields` on six endpoints asked for a whole object instead of a list of field names.** `getBoardActions`, `getCardActions`, `getListActions`, `getMemberActions` and `getOrganizationActions` typed it as `Action`; `getBoardLabels` typed it as `Label`. Trello's spec is the source: it points those parameters at the object schema rather than at the matching `ActionFields` and `LabelFields` enums. All six now take the shape the other thirty-five `fields` parameters in this client already had, `string | string[]` widened with the documented names for autocomplete, so `fields: 'id,name'` and `fields: ['id', 'name']` both work. Code that passed an `Action` or a `Label` object stops compiling, which is the point: the request it produced was never one the API could answer. +- **The documented values were missing from the suggestions on every parameter that lists them.** Eighty schemas paired an `openEnum` with a plain `z.string()` branch in the same union, and one model did the same. The branch accepted nothing the open enum did not already accept, and in the type a bare `string` swallowed the literal names next to it, so an editor offered nothing for `fields: '…'`, `filter: '…'` or `pos: '…'` — only the array form still suggested anything. The branch is gone. Any string is still accepted, which is the whole point of an open enum, and nothing that compiled before stops compiling. +- `Organization` gained `trial`, the object Trello now returns on every workspace: `{ eligible: boolean, endDate: Date | null }`. It was silently stripped in normal mode and raised `ZodError: unrecognized_keys` in strict/audit mode (`pnpm audit:schemas`), breaking `getMemberOrganizations`. `endDate` reads as `null` on every workspace reachable from this account, so its populated shape is still unobserved. +- `Prefs.invitations` is now `string` rather than `unknown`, which it was typed on the assumption the name implied a list. Trello sends `"members"` on every board reachable from this account, so the value was there all along and unusable without a cast. +- **The published API reference did not build.** Every parameter and model type was expanded inline on the endpoint pages instead of linked, which put `docs/api` at 22 MB and pushed VitePress past an 8 GB heap. Types are references now, and `typedoc-plugin-zod` fills the pages they point at with the fields and descriptions the schemas already carried. The reference is 9.0 MB and builds with the same 8 GB heap setting as the Docs workflow. The fix behind it is a local patch to typedoc, which drops the written name of a type alias whenever that alias resolves through a conditional type. + +### Deprecated + +- **`Organization.eligibleForTrial`.** Trello stopped sending it, and `trial.eligible` replaces it. The field stays optional so reading it still compiles, and goes at the next major version. + ## v2.2.0 (2026-08-20) **Read this one if you `switch` exhaustively over a value this client returns.** The enum-shaped types are now open, `Color` and `CardAging` among them, so a `switch` with no `default` branch stops type-checking. That ships in a minor release on purpose: the values belong to Trello, not to this client. The `_light` / `_dark` label shades reached the live API long before the spec named them and broke `getBoardCards` for every consumer until v2.1.6 added the 30 values by hand, so a closed set was never a promise a wrapper could keep. diff --git a/docs/recipes/actions.md b/docs/recipes/actions.md index 714479e9..b31c003f 100644 --- a/docs/recipes/actions.md +++ b/docs/recipes/actions.md @@ -14,6 +14,23 @@ const action = await trello.actions.getAction({ id: actionId }); console.log(action.type, action.date, action.memberCreator?.fullName); ``` +## Read typed action data + +`Action` includes an open fallback whose `data` is `unknown`. Checking `action.type` alone does not exclude that fallback. Validate a known action with its branch schema before reading its data: + +```ts +import { ActionCommentCardSchema } from 'trello.js/models'; + +const action = await trello.actions.getAction({ id: actionId }); + +if (action.type === 'commentCard') { + const comment = ActionCommentCardSchema.parse(action); + console.log(comment.data.text); +} +``` + +`parse` checks the action type and data shape, returns an `ActionCommentCard`, and throws `ZodError` if the payload does not match. Each of the twenty-nine typed branches exports its own model and schema. `ActionUnknown.data` remains `unknown` and requires validation before use. + ## List actions on a board / card / list / member ```ts diff --git a/docs/ru/recipes/actions.md b/docs/ru/recipes/actions.md index 0afa3240..e859eced 100644 --- a/docs/ru/recipes/actions.md +++ b/docs/ru/recipes/actions.md @@ -14,6 +14,23 @@ const action = await trello.actions.getAction({ id: actionId }); console.log(action.type, action.date, action.memberCreator?.fullName); ``` +## Чтение типизированных данных действия + +`Action` включает открытую ветку, у которой `data` имеет тип `unknown`. Проверка `action.type` сама по себе не исключает эту ветку. Перед чтением данных известного действия проверьте его соответствующей схемой: + +```ts +import { ActionCommentCardSchema } from 'trello.js/models'; + +const action = await trello.actions.getAction({ id: actionId }); + +if (action.type === 'commentCard') { + const comment = ActionCommentCardSchema.parse(action); + console.log(comment.data.text); +} +``` + +`parse` проверяет тип действия и форму данных, возвращает `ActionCommentCard` и выбрасывает `ZodError`, если ответ не соответствует схеме. Каждая из двадцати девяти типизированных веток экспортирует свою модель и схему. `ActionUnknown.data` остаётся `unknown` и требует проверки перед использованием. + ## Список действий на доске / карточке / списке / участнике ```ts diff --git a/package.json b/package.json index 1995fc41..9e947404 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "imports": { "#/*": "./src/*" }, - "version": "2.2.0", + "version": "2.3.0", "description": "Type-safe Trello REST API client for TypeScript and JavaScript. ESM-only, tree-shakable, runtime-validated by Zod 4. Full coverage of boards, cards, lists, checklists, members, webhooks, organizations. Atlassian Trello SDK for Node.js 22+ and modern browsers.", "author": "Vladislav Tupikin ", "license": "MIT", @@ -187,8 +187,9 @@ "sitemap": "^9.0.1", "tsc-alias": "^1.9.2", "tsx": "^4.23.12", - "typedoc": "^0.28.20", + "typedoc": "0.28.20", "typedoc-plugin-markdown": "^4.12.0", + "typedoc-plugin-zod": "^1.4.3", "typedoc-vitepress-theme": "^1.1.3", "typescript": "^6.0.3", "typescript-eslint": "^8.67.0", diff --git a/patches/typedoc@0.28.20.patch b/patches/typedoc@0.28.20.patch new file mode 100644 index 00000000..8d4e14ed --- /dev/null +++ b/patches/typedoc@0.28.20.patch @@ -0,0 +1,24 @@ +diff --git a/dist/index.js b/dist/index.js +index daa82424664dcf1236746613e27a3e79abf96bdd..ff2c2e8cdc21f1c31a8299c315d700077e78f9fb 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -5371,6 +5371,19 @@ function convertType(context, typeOrNode, maybeNode) { + } + return requestBugReport(context, typeOrNode); + } ++ if (maybeNode && ts13.isTypeReferenceNode(maybeNode) && ts13.isIdentifier(maybeNode.typeName)) { ++ try { ++ const writtenSymbol = context.expectSymbolAtLocation(maybeNode.typeName); ++ const writtenName = maybeNode.typeName.text; ++ if (writtenSymbol && !context.shouldInline(writtenSymbol, writtenName)) { ++ ++typeConversionDepth; ++ const written = referenceConverter.convert(context, maybeNode); ++ --typeConversionDepth; ++ return written; ++ } ++ } catch { ++ } ++ } + if (typeOrNode.isUnion() && typeOrNode.origin && !typeOrNode.aliasSymbol) { + return convertType(context, typeOrNode.origin); + } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c167a48e..dfbf9bee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + typedoc@0.28.20: cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed + importers: .: @@ -67,14 +70,17 @@ importers: specifier: ^4.23.12 version: 4.23.12 typedoc: - specifier: ^0.28.20 - version: 0.28.20(typescript@6.0.3) + specifier: 0.28.20 + version: 0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3) typedoc-plugin-markdown: specifier: ^4.12.0 - version: 4.12.0(typedoc@0.28.20(typescript@6.0.3)) + version: 4.12.0(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3)) + typedoc-plugin-zod: + specifier: ^1.4.3 + version: 1.4.3(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3)) typedoc-vitepress-theme: specifier: ^1.1.3 - version: 1.1.3(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3))) + version: 1.1.3(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3))) typescript: specifier: ^6.0.3 version: 6.0.3 @@ -2577,6 +2583,11 @@ packages: peerDependencies: typedoc: 0.28.x + typedoc-plugin-zod@1.4.3: + resolution: {integrity: sha512-j3kb4dGGK5OegtiIOH4F4etYdqq2lh+sTx6sABTmptPJJm8qx9XHyNlzfLYqW86ZVfL0hFR3+B/Ij9YXQw9TsA==} + peerDependencies: + typedoc: 0.23.x || 0.24.x || 0.25.x || 0.26.x || 0.27.x || 0.28.x + typedoc-vitepress-theme@1.1.3: resolution: {integrity: sha512-EK9iV7e3+R8lFNigdc0rIPWMxqfmDku0uGac3qYUu9tS4Qf1rhWZnyZJ4zu4G3iXrP5mqNPkv2wpODzRlA7jLw==} peerDependencies: @@ -5309,15 +5320,19 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3)): + typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3)): + dependencies: + typedoc: 0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3) + + typedoc-plugin-zod@1.4.3(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3)): dependencies: - typedoc: 0.28.20(typescript@6.0.3) + typedoc: 0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3) - typedoc-vitepress-theme@1.1.3(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(typescript@6.0.3))): + typedoc-vitepress-theme@1.1.3(typedoc-plugin-markdown@4.12.0(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3))): dependencies: - typedoc-plugin-markdown: 4.12.0(typedoc@0.28.20(typescript@6.0.3)) + typedoc-plugin-markdown: 4.12.0(typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3)) - typedoc@0.28.20(typescript@6.0.3): + typedoc@0.28.20(patch_hash=cfd112fe03b6081c8a9fb7de8d2c6dff89101e8367c0d7560981cb749ffcc2ed)(typescript@6.0.3): dependencies: '@gerrit0/mini-shiki': 3.23.0 lunr: 2.3.9 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5ed0b5af..93eb7551 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,4 @@ allowBuilds: esbuild: true +patchedDependencies: + typedoc@0.28.20: patches/typedoc@0.28.20.patch diff --git a/src/api/actions.ts b/src/api/actions.ts index 208f94a1..157dc5f3 100644 --- a/src/api/actions.ts +++ b/src/api/actions.ts @@ -26,7 +26,12 @@ import type { GetActionReactionSummary } from '#/parameters/getActionReactionSum import type { Client, RequestOptions, SendRequestOptions } from '#/core'; import { z } from 'zod'; -/** Get an Action */ +/** + * Get an Action + * + * _Note: An action can live on a board or a workspace, so accessing it needs `read:board:trello` or + * `read:organization:trello`._ + */ export async function getAction(client: Client, parameters: GetAction, options?: RequestOptions): Promise { const config: SendRequestOptions = { url: `/actions/${parameters.id}`, @@ -77,7 +82,12 @@ export async function deleteAction(client: Client, parameters: DeleteAction, opt return await client.sendRequest(config); } -/** Get a specific property of an action */ +/** + * Get a specific property of an action + * + * _Note: An action can live on a board or a workspace, so accessing it needs `read:board:trello` or + * `read:organization:trello`._ + */ export async function getActionField( client: Client, parameters: GetActionField, @@ -150,7 +160,12 @@ export async function getActionList( return await client.sendRequest(config); } -/** Gets the member of an action (not the creator) */ +/** + * Gets the member of an action (not the creator) + * + * _Note: An action can live on a board or a workspace, so accessing it needs `read:board:trello` or + * `read:organization:trello`._ + */ export async function getActionMember( client: Client, parameters: GetActionMember, @@ -169,7 +184,12 @@ export async function getActionMember( return await client.sendRequest(config); } -/** Get the Member who created the Action */ +/** + * Get the Member who created the Action + * + * _Note: An action can live on a board or a workspace, so accessing it needs `read:board:trello` or + * `read:organization:trello`._ + */ export async function getActionCreator( client: Client, parameters: GetActionCreator, diff --git a/src/api/boards.ts b/src/api/boards.ts index b397bf57..e997ed85 100644 --- a/src/api/boards.ts +++ b/src/api/boards.ts @@ -72,7 +72,9 @@ export async function getBoardMemberships( activity: parameters.activity, orgMemberType: parameters.orgMemberType, member: parameters.member, - member_fields: parameters.memberFields, + member_fields: Array.isArray(parameters.memberFields) + ? parameters.memberFields.join(',') + : parameters.memberFields, }, schema: z.array(MembershipsSchema), signal: options?.signal, @@ -471,7 +473,9 @@ export async function updateBoardMembership( method: 'PUT', searchParams: { type: parameters.type, - member_fields: parameters.memberFields, + member_fields: Array.isArray(parameters.memberFields) + ? parameters.memberFields.join(',') + : parameters.memberFields, }, schema: MembershipsSchema, signal: options?.signal, @@ -671,7 +675,7 @@ export async function markBoardAsViewed( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/boards/${parameters.id}/markedAsViewed`, + url: `/boards/${parameters.id}/markAsViewed`, method: 'POST', schema: BoardSchema, signal: options?.signal, diff --git a/src/api/cards.ts b/src/api/cards.ts index 1594ffd7..bf07b090 100644 --- a/src/api/cards.ts +++ b/src/api/cards.ts @@ -270,7 +270,7 @@ export async function getCardAttachment( url: `/cards/${parameters.id}/attachments/${parameters.idAttachment}`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: AttachmentSchema, signal: options?.signal, @@ -339,9 +339,11 @@ export async function getCardChecklists( method: 'GET', searchParams: { checkItems: parameters.checkItems, - checkItem_fields: parameters.checkItemFields, + checkItem_fields: Array.isArray(parameters.checkItemFields) + ? parameters.checkItemFields.join(',') + : parameters.checkItemFields, filter: parameters.filter, - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: z.array(ChecklistSchema), signal: options?.signal, diff --git a/src/api/checklists.ts b/src/api/checklists.ts index ed27973b..d5656e97 100644 --- a/src/api/checklists.ts +++ b/src/api/checklists.ts @@ -171,7 +171,7 @@ export async function getChecklistItems( method: 'GET', searchParams: { filter: parameters.filter, - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: z.array(CheckItemSchema), signal: options?.signal, @@ -212,7 +212,7 @@ export async function getChecklistItem( url: `/checklists/${parameters.id}/checkItems/${parameters.idCheckItem}`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: CheckItemSchema, signal: options?.signal, diff --git a/src/api/enterprises.ts b/src/api/enterprises.ts index 2a38895a..30ecb341 100644 --- a/src/api/enterprises.ts +++ b/src/api/enterprises.ts @@ -403,8 +403,10 @@ export async function deactivateEnterpriseMember( method: 'PUT', searchParams: { value: parameters.value, - fields: parameters.fields, - organization_fields: parameters.organizationFields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, + organization_fields: Array.isArray(parameters.organizationFields) + ? parameters.organizationFields.join(',') + : parameters.organizationFields, board_fields: parameters.boardFields, }, schema: MemberSchema, diff --git a/src/api/lists.ts b/src/api/lists.ts index 1f94a7b3..78c696c6 100644 --- a/src/api/lists.ts +++ b/src/api/lists.ts @@ -22,7 +22,7 @@ export async function getList(client: Client, parameters: GetList, options?: Req url: `/lists/${parameters.id}`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: TrelloListSchema, signal: options?.signal, diff --git a/src/api/members.ts b/src/api/members.ts index 996c8424..273edb24 100644 --- a/src/api/members.ts +++ b/src/api/members.ts @@ -73,7 +73,9 @@ export async function getMember(client: Client, parameters: GetMember, options?: boards: parameters.boards, boardBackgrounds: parameters.boardBackgrounds, boardsInvited: parameters.boardsInvited, - boardsInvited_fields: parameters.boardsInvitedFields, + boardsInvited_fields: Array.isArray(parameters.boardsInvitedFields) + ? parameters.boardsInvitedFields.join(',') + : parameters.boardsInvitedFields, boardStars: parameters.boardStars, cards: parameters.cards, customBoardBackgrounds: parameters.customBoardBackgrounds, @@ -355,7 +357,9 @@ export async function getMemberBoards( fields: parameters.fields, lists: parameters.lists, organization: parameters.organization, - organization_fields: parameters.organizationFields, + organization_fields: Array.isArray(parameters.organizationFields) + ? parameters.organizationFields.join(',') + : parameters.organizationFields, }, schema: z.array(BoardSchema), signal: options?.signal, @@ -534,7 +538,7 @@ export async function getMemberCustomEmoji( url: `/members/${parameters.id}/customEmoji/${parameters.idEmoji}`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: CustomEmojiSchema, signal: options?.signal, @@ -588,7 +592,7 @@ export async function getMemberCustomSticker( url: `/members/${parameters.id}/customStickers/${parameters.idSticker}`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: CustomStickerSchema, signal: options?.signal, @@ -652,7 +656,7 @@ export async function getMemberOrganizations( method: 'GET', searchParams: { filter: parameters.filter, - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, paid_account: parameters.paidAccount, }, schema: z.array(OrganizationSchema), @@ -832,7 +836,7 @@ export async function getMemberNotificationChannelSettings( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/members/${parameters.id}/notificationsChannelSettings`, + url: `/members/${parameters.id}/notificationChannelSettings`, method: 'GET', schema: z.array(NotificationChannelSettingsSchema), signal: options?.signal, @@ -848,7 +852,7 @@ export async function updateMemberNotificationChannelSettings( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/members/${parameters.id}/notificationsChannelSettings`, + url: `/members/${parameters.id}/notificationChannelSettings`, method: 'PUT', body: { channel: parameters.channel, @@ -868,7 +872,7 @@ export async function getMemberNotificationChannelSetting( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/members/${parameters.id}/notificationsChannelSettings/${parameters.channel}`, + url: `/members/${parameters.id}/notificationChannelSettings/${parameters.channel}`, method: 'GET', schema: NotificationChannelSettingsSchema, signal: options?.signal, @@ -884,7 +888,7 @@ export async function updateMemberNotificationChannelSetting( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/members/${parameters.id}/notificationsChannelSettings/${parameters.channel}`, + url: `/members/${parameters.id}/notificationChannelSettings/${parameters.channel}`, method: 'PUT', body: { blockedKeys: parameters.blockedKeys, @@ -903,7 +907,7 @@ export async function updateMemberNotificationChannelBlockedKey( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/members/${parameters.id}/notificationsChannelSettings/${parameters.channel}/${parameters.blockedKeys}`, + url: `/members/${parameters.id}/notificationChannelSettings/${parameters.channel}/${parameters.blockedKeys}`, method: 'PUT', schema: NotificationChannelSettingsSchema, signal: options?.signal, diff --git a/src/api/notifications.ts b/src/api/notifications.ts index ec1ea253..fbf8b4ee 100644 --- a/src/api/notifications.ts +++ b/src/api/notifications.ts @@ -29,15 +29,17 @@ export async function getNotification( method: 'GET', searchParams: { board: parameters.board, - board_fields: parameters.boardFields, + board_fields: Array.isArray(parameters.boardFields) ? parameters.boardFields.join(',') : parameters.boardFields, card: parameters.card, - card_fields: parameters.cardFields, + card_fields: Array.isArray(parameters.cardFields) ? parameters.cardFields.join(',') : parameters.cardFields, display: parameters.display, entities: parameters.entities, - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, list: parameters.list, member: parameters.member, - member_fields: parameters.memberFields, + member_fields: Array.isArray(parameters.memberFields) + ? parameters.memberFields.join(',') + : parameters.memberFields, memberCreator: parameters.memberCreator, memberCreator_fields: parameters.memberCreatorFields, organization: parameters.organization, @@ -96,7 +98,7 @@ export async function markAllNotificationsRead( method: 'POST', searchParams: { read: parameters.read, - ids: parameters.ids, + ids: Array.isArray(parameters.ids) ? parameters.ids.join(',') : parameters.ids, }, signal: options?.signal, }; @@ -133,7 +135,7 @@ export async function getNotificationBoard( url: `/notifications/${parameters.id}/board`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: BoardSchema, signal: options?.signal, @@ -152,7 +154,7 @@ export async function getNotificationCard( url: `/notifications/${parameters.id}/card`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: CardSchema, signal: options?.signal, @@ -209,7 +211,7 @@ export async function getNotificationCreator( url: `/notifications/${parameters.id}/memberCreator`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: MemberSchema, signal: options?.signal, @@ -228,7 +230,7 @@ export async function getNotificationOrganization( url: `/notifications/${parameters.id}/organization`, method: 'GET', searchParams: { - fields: parameters.fields, + fields: Array.isArray(parameters.fields) ? parameters.fields.join(',') : parameters.fields, }, schema: OrganizationSchema, signal: options?.signal, diff --git a/src/api/plugins.ts b/src/api/plugins.ts index 1dca1b10..4a7b16de 100644 --- a/src/api/plugins.ts +++ b/src/api/plugins.ts @@ -42,7 +42,7 @@ export async function createPluginListing( options?: RequestOptions, ): Promise { const config: SendRequestOptions = { - url: `/plugins/${parameters.idPlugin}/listing`, + url: `/plugins/${parameters.idPlugin}/listings`, method: 'POST', body: { description: parameters.description, diff --git a/src/api/search.ts b/src/api/search.ts index 68b91e61..8295245b 100644 --- a/src/api/search.ts +++ b/src/api/search.ts @@ -13,13 +13,15 @@ export async function search(client: Client, parameters: Search, options?: Reque searchParams: { query: parameters.query, idBoards: parameters.idBoards, - idOrganizations: parameters.idOrganizations, - idCards: parameters.idCards, + idOrganizations: Array.isArray(parameters.idOrganizations) + ? parameters.idOrganizations.join(',') + : parameters.idOrganizations, + idCards: Array.isArray(parameters.idCards) ? parameters.idCards.join(',') : parameters.idCards, modelTypes: parameters.modelTypes, - board_fields: parameters.boardFields, + board_fields: Array.isArray(parameters.boardFields) ? parameters.boardFields.join(',') : parameters.boardFields, boards_limit: parameters.boardsLimit, board_organization: parameters.boardOrganization, - card_fields: parameters.cardFields, + card_fields: Array.isArray(parameters.cardFields) ? parameters.cardFields.join(',') : parameters.cardFields, cards_limit: parameters.cardsLimit, cards_page: parameters.cardsPage, card_board: parameters.cardBoard, diff --git a/src/models/actionUnknown.ts b/src/models/actionUnknown.ts index d2b4114f..1c3c7689 100644 --- a/src/models/actionUnknown.ts +++ b/src/models/actionUnknown.ts @@ -6,7 +6,7 @@ import { MemberSchema } from '#/models/member'; export const ActionUnknownSchema = apiObject({ id: z.string(), idMemberCreator: z.string(), - data: z.record(z.string(), z.any()), + data: z.unknown(), type: z.string(), date: z.coerce.date(), limits: LimitsSchema.nullish(), diff --git a/src/models/attachment.ts b/src/models/attachment.ts index 2bc8c736..6d5571c9 100644 --- a/src/models/attachment.ts +++ b/src/models/attachment.ts @@ -15,6 +15,7 @@ export const AttachmentSchema = apiObject({ previews: z.array(z.string()).optional(), url: z.string().optional(), pos: z.number().optional(), + aiSummary: z.unknown().optional(), fileName: z.string().nullish(), isMalicious: z.boolean().optional(), limits: LimitsSchema.optional(), diff --git a/src/models/boardMyPrefs.ts b/src/models/boardMyPrefs.ts index ab2efd0d..55f41a33 100644 --- a/src/models/boardMyPrefs.ts +++ b/src/models/boardMyPrefs.ts @@ -15,6 +15,8 @@ export const BoardMyPrefsSchema = apiObject({ aiMSTeamsEnabled: z.boolean().optional(), aiConfluenceEnabled: z.boolean().optional(), aiGoogleChatEnabled: z.boolean().optional(), + aiGoogleGmailEnabled: z.boolean().optional(), + showListGuide: z.boolean().optional(), }); export type BoardMyPrefs = z.infer; diff --git a/src/models/card.ts b/src/models/card.ts index 8632faaa..6cc08638 100644 --- a/src/models/card.ts +++ b/src/models/card.ts @@ -101,6 +101,7 @@ export const CardSchema = apiObject({ faviconUrl: z.unknown().optional(), idMemberCreator: z.string().nullish(), idOrganization: z.string().nullish(), + lastSummaryChangeEventAt: z.coerce.date().nullish(), manifest: z.unknown().optional(), members: z.array(MemberSchema).optional(), membersVoted: z.array(MemberSchema).optional(), diff --git a/src/models/cardFields.ts b/src/models/cardFields.ts index d44221cc..f3ebcbc4 100644 --- a/src/models/cardFields.ts +++ b/src/models/cardFields.ts @@ -1,7 +1,7 @@ import type { z } from 'zod'; import { openEnum } from '#/core'; -/** The fields on a Card. */ +/** The fields on a Card. */ export const CardFieldsSchema = openEnum([ 'id', 'address', diff --git a/src/models/tokenPermission.ts b/src/models/tokenPermission.ts index 4227b750..6a633bd8 100644 --- a/src/models/tokenPermission.ts +++ b/src/models/tokenPermission.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { apiObject, openEnum } from '#/core'; export const TokenPermissionSchema = apiObject({ - idModel: z.union([z.string(), openEnum(['*'])]).optional(), + idModel: z.string().optional(), modelType: openEnum(['Board', 'Member', 'Organization', 'Enterprise']).optional(), read: z.boolean().optional(), write: z.boolean().optional(), diff --git a/src/parameters/createBoardList.ts b/src/parameters/createBoardList.ts index 586eead9..996d105d 100644 --- a/src/parameters/createBoardList.ts +++ b/src/parameters/createBoardList.ts @@ -5,7 +5,7 @@ export const CreateBoardListSchema = z.object({ /** The name of the list to be created. 1 to 16384 characters long. */ name: z.string(), /** Determines the position of the list. Valid values: `top`, `bottom`, or a positive number. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** The ID of the board */ id: z.string(), }); diff --git a/src/parameters/createCard.ts b/src/parameters/createCard.ts index 488cc538..60151696 100644 --- a/src/parameters/createCard.ts +++ b/src/parameters/createCard.ts @@ -11,7 +11,7 @@ export const CreateCardSchema = z.object({ /** A due date for the card */ due: z.string().optional(), /** The start date of a card, or `null` */ - start: z.string().optional(), + start: z.string().nullish(), /** Whether the status of the card is complete */ dueComplete: z.boolean().optional(), /** The ID of the list the card should be created in */ @@ -54,7 +54,7 @@ export const CreateCardSchema = z.object({ * For displaying cards in different ways based on the card name. Board cards must have a name that is a link to a * Trello board. Mirror cards must have a name that is a link to a Trello card. */ - cardRole: openEnum(['separator', 'board', 'mirror', 'link']).optional(), + cardRole: openEnum(['separator', 'board', 'mirror', 'link']).nullish(), }); export type CreateCard = z.input; diff --git a/src/parameters/createCardChecklist.ts b/src/parameters/createCardChecklist.ts index 49b446dd..529ec6c1 100644 --- a/src/parameters/createCardChecklist.ts +++ b/src/parameters/createCardChecklist.ts @@ -9,7 +9,7 @@ export const CreateCardChecklistSchema = z.object({ /** The ID of a source checklist to copy into the new one */ idChecklistSource: z.string().optional(), /** The position of the checklist on the card. One of: `top`, `bottom`, or a positive number. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), }); export type CreateCardChecklist = z.input; diff --git a/src/parameters/createChecklist.ts b/src/parameters/createChecklist.ts index 708e41b4..17523dc9 100644 --- a/src/parameters/createChecklist.ts +++ b/src/parameters/createChecklist.ts @@ -7,7 +7,7 @@ export const CreateChecklistSchema = z.object({ /** The name of the checklist. Should be a string of length 1 to 16384. **Defaults**: `Checklist` */ name: z.string().max(16384, 'name must be at most 16384 characters').optional(), /** The position of the checklist on the card. One of: `top`, `bottom`, or a positive number. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** The ID of a checklist to copy into the new checklist. */ idChecklistSource: z.string().optional(), }); diff --git a/src/parameters/createChecklistItem.ts b/src/parameters/createChecklistItem.ts index a8b380ee..94ba09c3 100644 --- a/src/parameters/createChecklistItem.ts +++ b/src/parameters/createChecklistItem.ts @@ -5,13 +5,13 @@ export const CreateChecklistItemSchema = z.object({ /** The name of the new check item on the checklist. Should be a string of length 1 to 16384. */ name: z.string().max(16384, 'name must be at most 16384 characters'), /** The position of the check item in the checklist. One of: `top`, `bottom`, or a positive number. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** Determines whether the check item is already checked when created. */ checked: z.boolean().optional(), /** A due date for the checkitem */ due: z.string().optional(), /** A dueReminder for the due date on the checkitem */ - dueReminder: z.number().optional(), + dueReminder: z.number().nullish(), /** An ID of a member resource. */ idMember: z.string().optional(), /** ID of a checklist. */ diff --git a/src/parameters/createCustomField.ts b/src/parameters/createCustomField.ts index f75c20ea..4ccc5e44 100644 --- a/src/parameters/createCustomField.ts +++ b/src/parameters/createCustomField.ts @@ -12,7 +12,7 @@ export const CreateCustomFieldSchema = z.object({ type: openEnum(['checkbox', 'list', 'number', 'text', 'date']), /** If the type is `checkbox` */ options: z.string().optional(), - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]), /** Whether this Custom Field should be shown on the front of Cards */ display_cardFront: z.boolean().optional(), }); diff --git a/src/parameters/createCustomFieldOption.ts b/src/parameters/createCustomFieldOption.ts index 1d8d74e3..9a67a35e 100644 --- a/src/parameters/createCustomFieldOption.ts +++ b/src/parameters/createCustomFieldOption.ts @@ -10,7 +10,7 @@ export const CreateCustomFieldOptionSchema = z.object({ }) .optional(), color: z.string().optional(), - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), }); export type CreateCustomFieldOption = z.input; diff --git a/src/parameters/createEnterpriseToken.ts b/src/parameters/createEnterpriseToken.ts index c9e3b606..e5bb9285 100644 --- a/src/parameters/createEnterpriseToken.ts +++ b/src/parameters/createEnterpriseToken.ts @@ -5,7 +5,7 @@ export const CreateEnterpriseTokenSchema = z.object({ /** ID of the enterprise to retrieve. */ id: z.string(), /** One of: `1hour`, `1day`, `30days`, `never` */ - expiration: z.union([z.string(), openEnum(['1hour', '1day', '30days', 'never'])]).optional(), + expiration: openEnum(['1hour', '1day', '30days', 'never']).optional(), }); export type CreateEnterpriseToken = z.input; diff --git a/src/parameters/createLabel.ts b/src/parameters/createLabel.ts index c5a1aa1d..fd293691 100644 --- a/src/parameters/createLabel.ts +++ b/src/parameters/createLabel.ts @@ -5,10 +5,7 @@ export const CreateLabelSchema = z.object({ /** Name for the label */ name: z.string(), /** The color for the label. */ - color: z.union([ - z.string(), - openEnum(['yellow', 'purple', 'blue', 'red', 'green', 'orange', 'black', 'sky', 'pink', 'lime']), - ]), + color: openEnum(['yellow', 'purple', 'blue', 'red', 'green', 'orange', 'black', 'sky', 'pink', 'lime']), /** The ID of the Board to create the Label on. */ idBoard: z.string(), }); diff --git a/src/parameters/createMemberSavedSearch.ts b/src/parameters/createMemberSavedSearch.ts index 0854b35f..feae0caf 100644 --- a/src/parameters/createMemberSavedSearch.ts +++ b/src/parameters/createMemberSavedSearch.ts @@ -7,7 +7,7 @@ export const CreateMemberSavedSearchSchema = z.object({ /** The search query */ query: z.string(), /** The position of the saved search. `top`, `bottom`, or a positive float. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]), /** The ID or username of the member */ id: z.string(), }); diff --git a/src/parameters/deactivateEnterpriseMember.ts b/src/parameters/deactivateEnterpriseMember.ts index 368ac09f..b14ac141 100644 --- a/src/parameters/deactivateEnterpriseMember.ts +++ b/src/parameters/deactivateEnterpriseMember.ts @@ -11,8 +11,6 @@ export const DeactivateEnterpriseMemberSchema = z.object({ /** A comma separated list of any valid values that the [nested member field resource]() accepts. */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -69,8 +67,6 @@ export const DeactivateEnterpriseMemberSchema = z.object({ */ organizationFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', @@ -119,8 +115,6 @@ export const DeactivateEnterpriseMemberSchema = z.object({ */ boardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getAction.ts b/src/parameters/getAction.ts index 2379f4ee..7dace7ac 100644 --- a/src/parameters/getAction.ts +++ b/src/parameters/getAction.ts @@ -10,8 +10,6 @@ export const GetActionSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), ]) @@ -23,8 +21,6 @@ export const GetActionSchema = z.object({ */ memberFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -83,8 +79,6 @@ export const GetActionSchema = z.object({ */ memberCreatorFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getActionBoard.ts b/src/parameters/getActionBoard.ts index 1ddae7af..92bc63f0 100644 --- a/src/parameters/getActionBoard.ts +++ b/src/parameters/getActionBoard.ts @@ -7,8 +7,6 @@ export const GetActionBoardSchema = z.object({ /** `all` or a comma-separated list of board fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getActionCard.ts b/src/parameters/getActionCard.ts index 7c7a45bd..728b5c75 100644 --- a/src/parameters/getActionCard.ts +++ b/src/parameters/getActionCard.ts @@ -7,8 +7,6 @@ export const GetActionCardSchema = z.object({ /** `all` or a comma-separated list of card fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'address', diff --git a/src/parameters/getActionCreator.ts b/src/parameters/getActionCreator.ts index e24149a2..8c6c07e3 100644 --- a/src/parameters/getActionCreator.ts +++ b/src/parameters/getActionCreator.ts @@ -7,8 +7,6 @@ export const GetActionCreatorSchema = z.object({ /** `all` or a comma-separated list of member fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getActionField.ts b/src/parameters/getActionField.ts index c1e3eec5..2250405a 100644 --- a/src/parameters/getActionField.ts +++ b/src/parameters/getActionField.ts @@ -5,10 +5,7 @@ export const GetActionFieldSchema = z.object({ /** The ID of the Action */ id: z.string(), /** An action field */ - field: z.union([ - z.string(), - openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), - ]), + field: openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), }); export type GetActionField = z.input; diff --git a/src/parameters/getActionList.ts b/src/parameters/getActionList.ts index 45069161..ab5f5512 100644 --- a/src/parameters/getActionList.ts +++ b/src/parameters/getActionList.ts @@ -7,8 +7,6 @@ export const GetActionListSchema = z.object({ /** `all` or a comma-separated list of list fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getActionMember.ts b/src/parameters/getActionMember.ts index 3313426a..a3b2aa21 100644 --- a/src/parameters/getActionMember.ts +++ b/src/parameters/getActionMember.ts @@ -7,8 +7,6 @@ export const GetActionMemberSchema = z.object({ /** `all` or a comma-separated list of member fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getActionOrganization.ts b/src/parameters/getActionOrganization.ts index a59be399..620eea86 100644 --- a/src/parameters/getActionOrganization.ts +++ b/src/parameters/getActionOrganization.ts @@ -7,8 +7,6 @@ export const GetActionOrganizationSchema = z.object({ /** `all` or a comma-separated list of organization fields */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getBoard.ts b/src/parameters/getBoard.ts index cd780c9d..f50e8dde 100644 --- a/src/parameters/getBoard.ts +++ b/src/parameters/getBoard.ts @@ -8,7 +8,7 @@ export const GetBoardSchema = z.object({ */ actions: z.string().optional(), /** Valid values are one of: `mine` or `none`. */ - boardStars: z.union([z.string(), openEnum(['mine', 'none'])]).optional(), + boardStars: openEnum(['mine', 'none']).optional(), /** * This is a nested resource. Read more about cards as nested resources * [here](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/). @@ -34,8 +34,6 @@ export const GetBoardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'closed', 'dateLastActivity', diff --git a/src/parameters/getBoardActions.ts b/src/parameters/getBoardActions.ts index 07f743a6..efebe4c6 100644 --- a/src/parameters/getBoardActions.ts +++ b/src/parameters/getBoardActions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { ActionSchema } from '../models'; +import { openEnum } from '#/core'; export const GetBoardActionsSchema = z.object({ boardId: z.string(), @@ -7,7 +7,12 @@ export const GetBoardActionsSchema = z.object({ * The fields to be returned for the Actions. [See Action fields * here](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#action-object). */ - fields: ActionSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), + z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), + ]) + .optional(), /** * A comma-separated list of [action * types](https://developer.atlassian.com/cloud/trello/guides/rest-api/action-types/). @@ -26,7 +31,7 @@ export const GetBoardActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) to * return. */ - memberFields: z.string().optional(), + memberFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to return the memberCreator object for each action. */ memberCreator: z.boolean().optional(), /** @@ -34,7 +39,7 @@ export const GetBoardActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) creator to * return */ - memberCreatorFields: z.string().optional(), + memberCreatorFields: z.union([z.string(), z.array(z.string())]).optional(), /** The page of results for actions. */ page: z.number().optional(), /** Whether to show reactions on comments or not. */ diff --git a/src/parameters/getBoardField.ts b/src/parameters/getBoardField.ts index 92164eb8..a29a05b0 100644 --- a/src/parameters/getBoardField.ts +++ b/src/parameters/getBoardField.ts @@ -9,30 +9,27 @@ export const GetBoardFieldSchema = z.object({ * idMemberCreator, idOrganization, invitations, invited, labelNames, memberships, name, pinned, powerUps, prefs, * shortLink, shortUrl, starred, subscribed, url. */ - field: z.union([ - z.string(), - openEnum([ - 'closed', - 'dateLastActivity', - 'dateLastView', - 'desc', - 'descData', - 'idMemberCreator', - 'idOrganization', - 'invitations', - 'invited', - 'labelNames', - 'memberships', - 'name', - 'pinned', - 'powerUps', - 'prefs', - 'shortLink', - 'shortUrl', - 'starred', - 'subscribed', - 'url', - ]), + field: openEnum([ + 'closed', + 'dateLastActivity', + 'dateLastView', + 'desc', + 'descData', + 'idMemberCreator', + 'idOrganization', + 'invitations', + 'invited', + 'labelNames', + 'memberships', + 'name', + 'pinned', + 'powerUps', + 'prefs', + 'shortLink', + 'shortUrl', + 'starred', + 'subscribed', + 'url', ]), }); diff --git a/src/parameters/getBoardLabels.ts b/src/parameters/getBoardLabels.ts index 5b02de2e..624c56e3 100644 --- a/src/parameters/getBoardLabels.ts +++ b/src/parameters/getBoardLabels.ts @@ -1,11 +1,16 @@ import { z } from 'zod'; -import { LabelSchema } from '../models'; +import { openEnum } from '#/core'; export const GetBoardLabelsSchema = z.object({ /** The ID of the Board. */ id: z.string(), /** The fields to be returned for the Labels. */ - fields: LabelSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idBoard', 'name', 'color', 'uses']), + z.array(openEnum(['id', 'idBoard', 'name', 'color', 'uses'])), + ]) + .optional(), /** The number of Labels to be returned. */ limit: z.number().optional(), }); diff --git a/src/parameters/getBoardLists.ts b/src/parameters/getBoardLists.ts index 3792f08d..f855fa71 100644 --- a/src/parameters/getBoardLists.ts +++ b/src/parameters/getBoardLists.ts @@ -3,15 +3,13 @@ import { openEnum } from '#/core'; export const GetBoardListsSchema = z.object({ /** Filter to apply to Cards. */ - cards: z.union([z.string(), openEnum(['all', 'closed', 'none', 'open'])]).optional(), + cards: openEnum(['all', 'closed', 'none', 'open']).optional(), /** * `all` or a comma-separated list of card * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#card-object) */ cardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'address', @@ -87,15 +85,13 @@ export const GetBoardListsSchema = z.object({ ]) .optional(), /** Filter to apply to Lists */ - filter: z.union([z.string(), openEnum(['all', 'closed', 'none', 'open'])]).optional(), + filter: openEnum(['all', 'closed', 'none', 'open']).optional(), /** * `all` or a comma-separated list of list * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getBoardListsByFilter.ts b/src/parameters/getBoardListsByFilter.ts index 4e303eb2..b93013df 100644 --- a/src/parameters/getBoardListsByFilter.ts +++ b/src/parameters/getBoardListsByFilter.ts @@ -5,7 +5,7 @@ export const GetBoardListsByFilterSchema = z.object({ /** The ID of the board */ id: z.string(), /** One of `all`, `closed`, `none`, `open` */ - filter: z.union([z.string(), openEnum(['all', 'closed', 'none', 'open'])]), + filter: openEnum(['all', 'closed', 'none', 'open']), }); export type GetBoardListsByFilter = z.input; diff --git a/src/parameters/getBoardMemberships.ts b/src/parameters/getBoardMemberships.ts index 01f8f15f..79a667cd 100644 --- a/src/parameters/getBoardMemberships.ts +++ b/src/parameters/getBoardMemberships.ts @@ -21,8 +21,6 @@ export const GetBoardMembershipsSchema = z.object({ */ memberFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getBoardStars.ts b/src/parameters/getBoardStars.ts index ffdf5874..80398658 100644 --- a/src/parameters/getBoardStars.ts +++ b/src/parameters/getBoardStars.ts @@ -4,7 +4,7 @@ import { openEnum } from '#/core'; export const GetBoardStarsSchema = z.object({ boardId: z.string(), /** Valid values: mine, none */ - filter: z.union([z.string(), openEnum(['mine', 'none'])]).optional(), + filter: openEnum(['mine', 'none']).optional(), }); export type GetBoardStars = z.input; diff --git a/src/parameters/getCard.ts b/src/parameters/getCard.ts index 77767214..b84a4f2b 100644 --- a/src/parameters/getCard.ts +++ b/src/parameters/getCard.ts @@ -10,8 +10,6 @@ export const GetCardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'address', @@ -99,8 +97,6 @@ export const GetCardSchema = z.object({ */ attachmentFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'bytes', @@ -140,8 +136,6 @@ export const GetCardSchema = z.object({ */ memberFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -201,8 +195,6 @@ export const GetCardSchema = z.object({ */ memberVotedFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -258,12 +250,7 @@ export const GetCardSchema = z.object({ checklists: z.string().optional(), /** `all` or a comma-separated list of `idBoard,idCard,name,pos` */ checklistFields: z - .union([ - z.string(), - z.array(z.string()), - openEnum(['idBoard', 'idCard', 'name', 'pos']), - z.array(openEnum(['idBoard', 'idCard', 'name', 'pos'])), - ]) + .union([openEnum(['idBoard', 'idCard', 'name', 'pos']), z.array(openEnum(['idBoard', 'idCard', 'name', 'pos']))]) .optional(), /** Whether to return the board object the card is on */ board: z.boolean().optional(), @@ -274,8 +261,6 @@ export const GetCardSchema = z.object({ */ boardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', @@ -328,8 +313,6 @@ export const GetCardSchema = z.object({ */ stickerFields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled']), z.array(openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled'])), ]) diff --git a/src/parameters/getCardActions.ts b/src/parameters/getCardActions.ts index a557a1f1..2e5f4118 100644 --- a/src/parameters/getCardActions.ts +++ b/src/parameters/getCardActions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { ActionSchema } from '../models'; +import { openEnum } from '#/core'; export const GetCardActionsSchema = z.object({ /** The ID of the Card */ @@ -15,7 +15,12 @@ export const GetCardActionsSchema = z.object({ * The fields to be returned for the Actions. [See Action fields * here](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#action-object). */ - fields: ActionSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), + z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), + ]) + .optional(), /** The format of the returned Actions. Either list or count. */ format: z.string().optional(), /** A comma-separated list of idModels. Only actions related to these models will be returned. */ @@ -29,7 +34,7 @@ export const GetCardActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) to * return. */ - memberFields: z.string().optional(), + memberFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to return the memberCreator object for each action. */ memberCreator: z.boolean().optional(), /** @@ -37,7 +42,7 @@ export const GetCardActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) creator to * return */ - memberCreatorFields: z.string().optional(), + memberCreatorFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to show reactions on comments or not. */ reactions: z.boolean().optional(), /** diff --git a/src/parameters/getCardAttachment.ts b/src/parameters/getCardAttachment.ts index 64ab6a1b..c6eb6971 100644 --- a/src/parameters/getCardAttachment.ts +++ b/src/parameters/getCardAttachment.ts @@ -3,7 +3,7 @@ import { AttachmentFieldsSchema } from '../models'; export const GetCardAttachmentSchema = z.object({ /** The Attachment fields to be included in the response. */ - fields: z.array(AttachmentFieldsSchema).optional(), + fields: z.union([AttachmentFieldsSchema, z.array(AttachmentFieldsSchema)]).optional(), /** The ID of the Card */ id: z.string(), /** The ID of the Attachment */ diff --git a/src/parameters/getCardAttachments.ts b/src/parameters/getCardAttachments.ts index 3201baed..4d33f545 100644 --- a/src/parameters/getCardAttachments.ts +++ b/src/parameters/getCardAttachments.ts @@ -8,8 +8,6 @@ export const GetCardAttachmentsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'bytes', diff --git a/src/parameters/getCardBoard.ts b/src/parameters/getCardBoard.ts index 17cca893..c12d814b 100644 --- a/src/parameters/getCardBoard.ts +++ b/src/parameters/getCardBoard.ts @@ -10,8 +10,6 @@ export const GetCardBoardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getCardCheckItem.ts b/src/parameters/getCardCheckItem.ts index 0b17b50f..b868841e 100644 --- a/src/parameters/getCardCheckItem.ts +++ b/src/parameters/getCardCheckItem.ts @@ -5,8 +5,6 @@ export const GetCardCheckItemSchema = z.object({ /** `all` or a comma-separated list of `name,nameData,pos,state,type,due,dueReminder,idMember` */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']), z.array(openEnum(['name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember'])), ]) diff --git a/src/parameters/getCardCheckItemStates.ts b/src/parameters/getCardCheckItemStates.ts index e45a42d9..f6b3bac2 100644 --- a/src/parameters/getCardCheckItemStates.ts +++ b/src/parameters/getCardCheckItemStates.ts @@ -5,14 +5,7 @@ export const GetCardCheckItemStatesSchema = z.object({ /** The ID of the Card */ id: z.string(), /** `all` or a comma-separated list of: `idCheckItem`, `state` */ - fields: z - .union([ - z.string(), - z.array(z.string()), - openEnum(['idCheckItem', 'state']), - z.array(openEnum(['idCheckItem', 'state'])), - ]) - .optional(), + fields: z.union([openEnum(['idCheckItem', 'state']), z.array(openEnum(['idCheckItem', 'state']))]).optional(), }); export type GetCardCheckItemStates = z.input; diff --git a/src/parameters/getCardChecklists.ts b/src/parameters/getCardChecklists.ts index a0c4e3b5..a437defb 100644 --- a/src/parameters/getCardChecklists.ts +++ b/src/parameters/getCardChecklists.ts @@ -7,11 +7,21 @@ export const GetCardChecklistsSchema = z.object({ /** `all` or `none` */ checkItems: openEnum(['all', 'none']).optional(), /** `all` or a comma-separated list of: `name,nameData,pos,state,type,due,dueReminder,idMember` */ - checkItemFields: openEnum(['name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']).optional(), + checkItemFields: z + .union([ + openEnum(['name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']), + z.array(openEnum(['name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember'])), + ]) + .optional(), /** `all` or `none` */ filter: openEnum(['all', 'none']).optional(), /** `all` or a comma-separated list of: `idBoard,idCard,name,pos` */ - fields: openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type']).optional(), + fields: z + .union([ + openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type']), + z.array(openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type'])), + ]) + .optional(), }); export type GetCardChecklists = z.input; diff --git a/src/parameters/getCardField.ts b/src/parameters/getCardField.ts index be93760e..e708bc97 100644 --- a/src/parameters/getCardField.ts +++ b/src/parameters/getCardField.ts @@ -5,43 +5,40 @@ export const GetCardFieldSchema = z.object({ /** The ID of the Card */ id: z.string(), /** The desired field. */ - field: z.union([ - z.string(), - openEnum([ - 'id', - 'address', - 'badges', - 'checkItemStates', - 'closed', - 'coordinates', - 'creationMethod', - 'dueComplete', - 'dateLastActivity', - 'desc', - 'descData', - 'due', - 'dueReminder', - 'idBoard', - 'idChecklists', - 'idLabels', - 'idList', - 'idMembers', - 'idMembersVoted', - 'idShort', - 'idAttachmentCover', - 'labels', - 'limits', - 'locationName', - 'manualCoverAttachment', - 'name', - 'pos', - 'shortLink', - 'shortUrl', - 'subscribed', - 'url', - 'cover', - 'isTemplate', - ]), + field: openEnum([ + 'id', + 'address', + 'badges', + 'checkItemStates', + 'closed', + 'coordinates', + 'creationMethod', + 'dueComplete', + 'dateLastActivity', + 'desc', + 'descData', + 'due', + 'dueReminder', + 'idBoard', + 'idChecklists', + 'idLabels', + 'idList', + 'idMembers', + 'idMembersVoted', + 'idShort', + 'idAttachmentCover', + 'labels', + 'limits', + 'locationName', + 'manualCoverAttachment', + 'name', + 'pos', + 'shortLink', + 'shortUrl', + 'subscribed', + 'url', + 'cover', + 'isTemplate', ]), }); diff --git a/src/parameters/getCardList.ts b/src/parameters/getCardList.ts index e2e93b3a..a8b97673 100644 --- a/src/parameters/getCardList.ts +++ b/src/parameters/getCardList.ts @@ -10,8 +10,6 @@ export const GetCardListSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getCardMembers.ts b/src/parameters/getCardMembers.ts index 366c5213..97565ebe 100644 --- a/src/parameters/getCardMembers.ts +++ b/src/parameters/getCardMembers.ts @@ -10,8 +10,6 @@ export const GetCardMembersSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getCardMembersVoted.ts b/src/parameters/getCardMembersVoted.ts index fd07c491..6cc27f95 100644 --- a/src/parameters/getCardMembersVoted.ts +++ b/src/parameters/getCardMembersVoted.ts @@ -8,8 +8,6 @@ export const GetCardMembersVotedSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getCardSticker.ts b/src/parameters/getCardSticker.ts index 9e7583b9..b54ee984 100644 --- a/src/parameters/getCardSticker.ts +++ b/src/parameters/getCardSticker.ts @@ -8,8 +8,6 @@ export const GetCardStickerSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled']), z.array(openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled'])), ]) diff --git a/src/parameters/getCardStickers.ts b/src/parameters/getCardStickers.ts index 4c772585..8767286e 100644 --- a/src/parameters/getCardStickers.ts +++ b/src/parameters/getCardStickers.ts @@ -10,8 +10,6 @@ export const GetCardStickersSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled']), z.array(openEnum(['id', 'top', 'left', 'zIndex', 'rotate', 'image', 'imageUrl', 'imageScaled'])), ]) diff --git a/src/parameters/getChecklist.ts b/src/parameters/getChecklist.ts index fd8c32bf..b675ee77 100644 --- a/src/parameters/getChecklist.ts +++ b/src/parameters/getChecklist.ts @@ -14,25 +14,18 @@ export const GetChecklistSchema = z.object({ * The fields on the checkItem to return if checkItems are being returned. `all` or a comma-separated list of: `name`, * `nameData`, `pos`, `state`, `type`, `due`, `dueReminder`, `idMember` */ - checkItemFields: openEnum([ - 'all', - 'name', - 'nameData', - 'pos', - 'state', - 'type', - 'due', - 'dueReminder', - 'idMember', - ]).optional(), + checkItemFields: z + .union([ + openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']), + z.array(openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember'])), + ]) + .optional(), /** * `all` or a comma-separated list of checklist * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'name', 'idBoard', 'idCard', 'pos']), z.array(openEnum(['id', 'name', 'idBoard', 'idCard', 'pos'])), ]) diff --git a/src/parameters/getChecklistBoard.ts b/src/parameters/getChecklistBoard.ts index 51e65b7c..967b6c21 100644 --- a/src/parameters/getChecklistBoard.ts +++ b/src/parameters/getChecklistBoard.ts @@ -8,7 +8,7 @@ export const GetChecklistBoardSchema = z.object({ * `all` or a comma-separated list of board * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ - fields: openEnum(['all', 'name']).optional(), + fields: z.union([openEnum(['all', 'name']), z.array(openEnum(['all', 'name']))]).optional(), }); export type GetChecklistBoard = z.input; diff --git a/src/parameters/getChecklistItem.ts b/src/parameters/getChecklistItem.ts index 5cd74465..f670f220 100644 --- a/src/parameters/getChecklistItem.ts +++ b/src/parameters/getChecklistItem.ts @@ -3,7 +3,12 @@ import { openEnum } from '#/core'; export const GetChecklistItemSchema = z.object({ /** One of: `all`, `name`, `nameData`, `pos`, `state`, `type`, `due`, `dueReminder`, `idMember`,. */ - fields: openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']).optional(), + fields: z + .union([ + openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']), + z.array(openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember'])), + ]) + .optional(), /** ID of a checklist. */ id: z.string(), /** ID of the check item to retrieve. */ diff --git a/src/parameters/getChecklistItems.ts b/src/parameters/getChecklistItems.ts index 576c668d..04e67632 100644 --- a/src/parameters/getChecklistItems.ts +++ b/src/parameters/getChecklistItems.ts @@ -5,7 +5,12 @@ export const GetChecklistItemsSchema = z.object({ /** One of: `all`, `none`. */ filter: openEnum(['all', 'none']).optional(), /** One of: `all`, `name`, `nameData`, `pos`, `state`,`type`, `due`, `dueReminder`, `idMember`. */ - fields: openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']).optional(), + fields: z + .union([ + openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember']), + z.array(openEnum(['all', 'name', 'nameData', 'pos', 'state', 'type', 'due', 'dueReminder', 'idMember'])), + ]) + .optional(), /** ID of a checklist. */ id: z.string(), }); diff --git a/src/parameters/getEnterprise.ts b/src/parameters/getEnterprise.ts index bebcd631..dabe8e1d 100644 --- a/src/parameters/getEnterprise.ts +++ b/src/parameters/getEnterprise.ts @@ -12,8 +12,6 @@ export const GetEnterpriseSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', @@ -43,9 +41,14 @@ export const GetEnterpriseSchema = z.object({ ]) .optional(), /** One of: `none`, `normal`, `admins`, `owners`, `all` */ - members: z.union([z.string(), openEnum(['none', 'normal', 'admins', 'owners', 'all'])]).optional(), + members: openEnum(['none', 'normal', 'admins', 'owners', 'all']).optional(), /** One of: `avatarHash`, `fullName`, `initials`, `username` */ - memberFields: z.union([z.string(), openEnum(['avatarHash', 'fullName', 'initials', 'username'])]).optional(), + memberFields: z + .union([ + openEnum(['avatarHash', 'fullName', 'initials', 'username']), + z.array(openEnum(['avatarHash', 'fullName', 'initials', 'username'])), + ]) + .optional(), /** * Pass a SCIM-style query to filter members. This takes precedence over the all/normal/admins value of members. If * any of the member_* args are set, the member array will be paginated. @@ -65,15 +68,15 @@ export const GetEnterpriseSchema = z.object({ */ memberSortBy: z.string().optional(), /** Deprecated: Please use member_sort. One of: `ascending`, `descending`, `asc`, `desc` */ - memberSortOrder: z.union([z.string(), openEnum(['ascending', 'descending', 'asc', 'desc'])]).optional(), + memberSortOrder: openEnum(['ascending', 'descending', 'asc', 'desc']).optional(), /** Any integer between 0 and 100. */ memberStartIndex: z.number().optional(), /** 0 to 100 */ memberCount: z.number().optional(), /** One of: `none`, `members`, `public`, `all` */ - organizations: z.union([z.string(), openEnum(['none', 'members', 'public', 'all'])]).optional(), + organizations: openEnum(['none', 'members', 'public', 'all']).optional(), /** Any valid value that the [nested organization field resource]() accepts. */ - organizationFields: z.string().optional(), + organizationFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether or not to include paid account information in the returned workspace objects */ organizationPaidAccounts: z.boolean().optional(), /** Comma-seperated list of: `me`, `normal`, `admin`, `active`, `deactivated` */ diff --git a/src/parameters/getEnterpriseAdmins.ts b/src/parameters/getEnterpriseAdmins.ts index 4ca99f16..e9be0175 100644 --- a/src/parameters/getEnterpriseAdmins.ts +++ b/src/parameters/getEnterpriseAdmins.ts @@ -4,7 +4,7 @@ export const GetEnterpriseAdminsSchema = z.object({ /** ID of the enterprise to retrieve. */ id: z.string(), /** Any valid value that the [nested member field resource]() accepts. */ - fields: z.string().optional(), + fields: z.union([z.string(), z.array(z.string())]).optional(), }); export type GetEnterpriseAdmins = z.input; diff --git a/src/parameters/getEnterpriseMember.ts b/src/parameters/getEnterpriseMember.ts index 449e8682..1946f5bb 100644 --- a/src/parameters/getEnterpriseMember.ts +++ b/src/parameters/getEnterpriseMember.ts @@ -6,17 +6,17 @@ export const GetEnterpriseMemberSchema = z.object({ /** An ID of a member resource. */ idMember: z.string(), /** A comma separated list of any valid values that the [nested member field resource]() accepts. */ - fields: z.string().optional(), + fields: z.union([z.string(), z.array(z.string())]).optional(), /** * Any valid value that the [nested organization field * resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/) accepts. */ - organizationFields: z.string().optional(), + organizationFields: z.union([z.string(), z.array(z.string())]).optional(), /** * Any valid value that the [nested board * resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/) accepts. */ - boardFields: z.string().optional(), + boardFields: z.union([z.string(), z.array(z.string())]).optional(), }); export type GetEnterpriseMember = z.input; diff --git a/src/parameters/getEnterpriseMembers.ts b/src/parameters/getEnterpriseMembers.ts index 4588bd92..3d9960b6 100644 --- a/src/parameters/getEnterpriseMembers.ts +++ b/src/parameters/getEnterpriseMembers.ts @@ -10,8 +10,6 @@ export const GetEnterpriseMembersSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -66,7 +64,7 @@ export const GetEnterpriseMembersSchema = z.object({ * Pass a SCIM-style query to filter members. This takes precedence over the all/normal/admins value of members. If * any of the below member_* args are set, the member array will be paginated. */ - filter: z.string().optional(), + filter: z.string().nullish(), /** * This parameter expects a SCIM-style sorting value prefixed by a `-` to sort descending. If no `-` is prefixed, it * will be sorted ascending. Note that the members array returned will be paginated if `members` is 'normal' or @@ -82,7 +80,7 @@ export const GetEnterpriseMembersSchema = z.object({ */ sortBy: z.string().optional(), /** Deprecated: Please use `sort` instead. One of: `ascending`, `descending`, `asc`, `desc`. */ - sortOrder: openEnum(['ascending', 'descending', 'asc', 'desc', 'null']).optional(), + sortOrder: openEnum(['ascending', 'descending', 'asc', 'desc', 'null']).nullish(), /** Any integer between 0 and 9999. */ startIndex: z.number().optional(), /** SCIM-style filter. */ @@ -91,12 +89,12 @@ export const GetEnterpriseMembersSchema = z.object({ * Any valid value that the [nested organization field * resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/) accepts. */ - organizationFields: z.string().optional(), + organizationFields: z.union([z.string(), z.array(z.string())]).optional(), /** * Any valid value that the [nested board * resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/) accepts. */ - boardFields: z.string().optional(), + boardFields: z.union([z.string(), z.array(z.string())]).optional(), }); export type GetEnterpriseMembers = z.input; diff --git a/src/parameters/getEnterpriseOrganizations.ts b/src/parameters/getEnterpriseOrganizations.ts index 4ceaacd1..beec70db 100644 --- a/src/parameters/getEnterpriseOrganizations.ts +++ b/src/parameters/getEnterpriseOrganizations.ts @@ -10,8 +10,6 @@ export const GetEnterpriseOrganizationsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getEnterpriseSignUpUrl.ts b/src/parameters/getEnterpriseSignUpUrl.ts index 55e12e3e..c17e34dc 100644 --- a/src/parameters/getEnterpriseSignUpUrl.ts +++ b/src/parameters/getEnterpriseSignUpUrl.ts @@ -6,7 +6,7 @@ export const GetEnterpriseSignUpUrlSchema = z.object({ authenticate: z.boolean().optional(), confirmationAccepted: z.boolean().optional(), /** Any valid URL. */ - returnUrl: z.string().optional(), + returnUrl: z.string().nullish(), /** * Designates whether the user has seen/consented to the Trello ToS prior to being redirected to the enterprise signup * page/their IdP. diff --git a/src/parameters/getLabel.ts b/src/parameters/getLabel.ts index af2041b0..bfc76927 100644 --- a/src/parameters/getLabel.ts +++ b/src/parameters/getLabel.ts @@ -8,8 +8,6 @@ export const GetLabelSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['id', 'idBoard', 'name', 'color', 'uses']), z.array(openEnum(['id', 'idBoard', 'name', 'color', 'uses'])), ]) diff --git a/src/parameters/getList.ts b/src/parameters/getList.ts index b2b51af7..4e5b810e 100644 --- a/src/parameters/getList.ts +++ b/src/parameters/getList.ts @@ -5,8 +5,6 @@ export const GetListSchema = z.object({ /** `all` or a comma separated list of List field names. */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getListActions.ts b/src/parameters/getListActions.ts index 94ee146c..c3d92760 100644 --- a/src/parameters/getListActions.ts +++ b/src/parameters/getListActions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { ActionSchema } from '../models'; +import { openEnum } from '#/core'; export const GetListActionsSchema = z.object({ /** The ID of the list */ @@ -13,7 +13,12 @@ export const GetListActionsSchema = z.object({ * The fields to be returned for the Actions. [See Action fields * here](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#action-object). */ - fields: ActionSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), + z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), + ]) + .optional(), /** The format of the returned Actions. Either list or count. */ format: z.string().optional(), /** A comma-separated list of idModels. Only actions related to these models will be returned. */ @@ -27,7 +32,7 @@ export const GetListActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) to * return. */ - memberFields: z.string().optional(), + memberFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to return the memberCreator object for each action. */ memberCreator: z.boolean().optional(), /** @@ -35,7 +40,7 @@ export const GetListActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) creator to * return */ - memberCreatorFields: z.string().optional(), + memberCreatorFields: z.union([z.string(), z.array(z.string())]).optional(), /** The page of results for actions. */ page: z.number().optional(), /** Whether to show reactions on comments or not. */ diff --git a/src/parameters/getListBoard.ts b/src/parameters/getListBoard.ts index 374bd1cb..c93e5487 100644 --- a/src/parameters/getListBoard.ts +++ b/src/parameters/getListBoard.ts @@ -10,8 +10,6 @@ export const GetListBoardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getMember.ts b/src/parameters/getMember.ts index 70c2504c..36efd5d8 100644 --- a/src/parameters/getMember.ts +++ b/src/parameters/getMember.ts @@ -33,8 +33,6 @@ export const GetMemberSchema = z.object({ */ boardsInvitedFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', @@ -95,8 +93,6 @@ export const GetMemberSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -160,8 +156,6 @@ export const GetMemberSchema = z.object({ */ organizationFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', @@ -214,8 +208,6 @@ export const GetMemberSchema = z.object({ */ organizationsInvitedFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getMemberActions.ts b/src/parameters/getMemberActions.ts index 211d051a..ff115138 100644 --- a/src/parameters/getMemberActions.ts +++ b/src/parameters/getMemberActions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { ActionSchema } from '../models'; +import { openEnum } from '#/core'; export const GetMemberActionsSchema = z.object({ /** The ID or username of the member */ @@ -13,7 +13,12 @@ export const GetMemberActionsSchema = z.object({ * The fields to be returned for the Actions. [See Action fields * here](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#action-object). */ - fields: ActionSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), + z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), + ]) + .optional(), /** The format of the returned Actions. Either list or count. */ format: z.string().optional(), /** A comma-separated list of idModels. Only actions related to these models will be returned. */ @@ -27,7 +32,7 @@ export const GetMemberActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) to * return. */ - memberFields: z.string().optional(), + memberFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to return the memberCreator object for each action. */ memberCreator: z.boolean().optional(), /** @@ -35,7 +40,7 @@ export const GetMemberActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) creator to * return */ - memberCreatorFields: z.string().optional(), + memberCreatorFields: z.union([z.string(), z.array(z.string())]).optional(), /** The page of results for actions. */ page: z.number().optional(), /** Whether to show reactions on comments or not. */ diff --git a/src/parameters/getMemberBoardBackground.ts b/src/parameters/getMemberBoardBackground.ts index 6520c1b1..28ea3ad3 100644 --- a/src/parameters/getMemberBoardBackground.ts +++ b/src/parameters/getMemberBoardBackground.ts @@ -3,7 +3,12 @@ import { openEnum } from '#/core'; export const GetMemberBoardBackgroundSchema = z.object({ /** `all` or a comma-separated list of: `brightness`, `fullSizeUrl`, `scaled`, `tile` */ - fields: openEnum(['all', 'brightness', 'fullSizeUrl', 'scaled', 'tile']).optional(), + fields: z + .union([ + openEnum(['all', 'brightness', 'fullSizeUrl', 'scaled', 'tile']), + z.array(openEnum(['all', 'brightness', 'fullSizeUrl', 'scaled', 'tile'])), + ]) + .optional(), /** The ID or username of the member */ id: z.string(), /** The ID of the board background */ diff --git a/src/parameters/getMemberBoards.ts b/src/parameters/getMemberBoards.ts index 500e507d..7c88c07f 100644 --- a/src/parameters/getMemberBoards.ts +++ b/src/parameters/getMemberBoards.ts @@ -12,8 +12,6 @@ export const GetMemberBoardsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', @@ -64,8 +62,6 @@ export const GetMemberBoardsSchema = z.object({ */ organizationFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getMemberCustomEmoji.ts b/src/parameters/getMemberCustomEmoji.ts index 422ff20b..3d73fc05 100644 --- a/src/parameters/getMemberCustomEmoji.ts +++ b/src/parameters/getMemberCustomEmoji.ts @@ -7,7 +7,7 @@ export const GetMemberCustomEmojiSchema = z.object({ /** The ID of the custom emoji */ idEmoji: z.string(), /** `all` or a comma-separated list of `name`, `url` */ - fields: openEnum(['name', 'url', 'all']).optional(), + fields: z.union([openEnum(['name', 'url', 'all']), z.array(openEnum(['name', 'url', 'all']))]).optional(), }); export type GetMemberCustomEmoji = z.input; diff --git a/src/parameters/getMemberCustomSticker.ts b/src/parameters/getMemberCustomSticker.ts index dcbf6446..0b3b8c2f 100644 --- a/src/parameters/getMemberCustomSticker.ts +++ b/src/parameters/getMemberCustomSticker.ts @@ -3,7 +3,7 @@ import { openEnum } from '#/core'; export const GetMemberCustomStickerSchema = z.object({ /** `all` or a comma-separated list of `scaled`, `url` */ - fields: openEnum(['scaled', 'url', 'all']).optional(), + fields: z.union([openEnum(['scaled', 'url', 'all']), z.array(openEnum(['scaled', 'url', 'all']))]).optional(), /** The ID or username of the member */ id: z.string(), /** The ID of the uploaded sticker */ diff --git a/src/parameters/getMemberField.ts b/src/parameters/getMemberField.ts index 8c39d411..9511d80b 100644 --- a/src/parameters/getMemberField.ts +++ b/src/parameters/getMemberField.ts @@ -5,31 +5,28 @@ export const GetMemberFieldSchema = z.object({ /** The ID or username of the member */ id: z.string(), /** One of the member [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ - field: z.union([ - z.string(), - openEnum([ - 'id', - 'activityBlocked', - 'avatarHash', - 'avatarUrl', - 'bio', - 'bioData', - 'confirmed', - 'fullName', - 'idEnterprise', - 'idMemberReferrer', - 'idPremOrgsAdmin', - 'initials', - 'memberType', - 'nonPublic', - 'nonPublicAvailable', - 'products', - 'status', - 'url', - 'username', - 'idBoards', - 'idOrganizations', - ]), + field: openEnum([ + 'id', + 'activityBlocked', + 'avatarHash', + 'avatarUrl', + 'bio', + 'bioData', + 'confirmed', + 'fullName', + 'idEnterprise', + 'idMemberReferrer', + 'idPremOrgsAdmin', + 'initials', + 'memberType', + 'nonPublic', + 'nonPublicAvailable', + 'products', + 'status', + 'url', + 'username', + 'idBoards', + 'idOrganizations', ]), }); diff --git a/src/parameters/getMemberInvitedBoards.ts b/src/parameters/getMemberInvitedBoards.ts index c7c1f047..7e516721 100644 --- a/src/parameters/getMemberInvitedBoards.ts +++ b/src/parameters/getMemberInvitedBoards.ts @@ -10,8 +10,6 @@ export const GetMemberInvitedBoardsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getMemberInvitedOrganizations.ts b/src/parameters/getMemberInvitedOrganizations.ts index 884fa658..7d605e6b 100644 --- a/src/parameters/getMemberInvitedOrganizations.ts +++ b/src/parameters/getMemberInvitedOrganizations.ts @@ -10,8 +10,6 @@ export const GetMemberInvitedOrganizationsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getMemberNotifications.ts b/src/parameters/getMemberNotifications.ts index 866f65a2..2bfa7102 100644 --- a/src/parameters/getMemberNotifications.ts +++ b/src/parameters/getMemberNotifications.ts @@ -8,15 +8,13 @@ export const GetMemberNotificationsSchema = z.object({ display: z.boolean().optional(), filter: z.string().optional(), /** One of: `all`, `read`, `unread` */ - readFilter: z.union([z.string(), openEnum(['all', 'read', 'unread'])]).optional(), + readFilter: openEnum(['all', 'read', 'unread']).optional(), /** * `all` or a comma-separated list of notification * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'unread', @@ -62,8 +60,6 @@ export const GetMemberNotificationsSchema = z.object({ */ memberCreatorFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getMemberOrganizations.ts b/src/parameters/getMemberOrganizations.ts index 58fdb266..fee51801 100644 --- a/src/parameters/getMemberOrganizations.ts +++ b/src/parameters/getMemberOrganizations.ts @@ -12,8 +12,6 @@ export const GetMemberOrganizationsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getNotification.ts b/src/parameters/getNotification.ts index 31c10069..0532faca 100644 --- a/src/parameters/getNotification.ts +++ b/src/parameters/getNotification.ts @@ -12,8 +12,6 @@ export const GetNotificationSchema = z.object({ */ boardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', @@ -62,8 +60,6 @@ export const GetNotificationSchema = z.object({ */ cardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'address', @@ -148,8 +144,6 @@ export const GetNotificationSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'unread', @@ -190,8 +184,6 @@ export const GetNotificationSchema = z.object({ */ memberFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -250,8 +242,6 @@ export const GetNotificationSchema = z.object({ */ memberCreatorFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', @@ -310,8 +300,6 @@ export const GetNotificationSchema = z.object({ */ organizationFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getNotificationBoard.ts b/src/parameters/getNotificationBoard.ts index d0e96e90..3d7ebd17 100644 --- a/src/parameters/getNotificationBoard.ts +++ b/src/parameters/getNotificationBoard.ts @@ -10,8 +10,6 @@ export const GetNotificationBoardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getNotificationCard.ts b/src/parameters/getNotificationCard.ts index 1da425a9..8c105016 100644 --- a/src/parameters/getNotificationCard.ts +++ b/src/parameters/getNotificationCard.ts @@ -10,8 +10,6 @@ export const GetNotificationCardSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'address', diff --git a/src/parameters/getNotificationCreator.ts b/src/parameters/getNotificationCreator.ts index 36368a15..ee37b48b 100644 --- a/src/parameters/getNotificationCreator.ts +++ b/src/parameters/getNotificationCreator.ts @@ -10,8 +10,6 @@ export const GetNotificationCreatorSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getNotificationField.ts b/src/parameters/getNotificationField.ts index 6f6a500d..1509ff9a 100644 --- a/src/parameters/getNotificationField.ts +++ b/src/parameters/getNotificationField.ts @@ -5,21 +5,18 @@ export const GetNotificationFieldSchema = z.object({ /** The ID of the notification */ id: z.string(), /** A notification [field](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ - field: z.union([ - z.string(), - openEnum([ - 'id', - 'unread', - 'type', - 'date', - 'dateRead', - 'data', - 'card', - 'board', - 'idMemberCreator', - 'idAction', - 'reactions', - ]), + field: openEnum([ + 'id', + 'unread', + 'type', + 'date', + 'dateRead', + 'data', + 'card', + 'board', + 'idMemberCreator', + 'idAction', + 'reactions', ]), }); diff --git a/src/parameters/getNotificationList.ts b/src/parameters/getNotificationList.ts index a496313f..9db881ca 100644 --- a/src/parameters/getNotificationList.ts +++ b/src/parameters/getNotificationList.ts @@ -10,8 +10,6 @@ export const GetNotificationListSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getNotificationMember.ts b/src/parameters/getNotificationMember.ts index a87fc51b..d508181e 100644 --- a/src/parameters/getNotificationMember.ts +++ b/src/parameters/getNotificationMember.ts @@ -10,8 +10,6 @@ export const GetNotificationMemberSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/getNotificationOrganization.ts b/src/parameters/getNotificationOrganization.ts index 71d37155..44ce8b49 100644 --- a/src/parameters/getNotificationOrganization.ts +++ b/src/parameters/getNotificationOrganization.ts @@ -10,8 +10,6 @@ export const GetNotificationOrganizationSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'billableMemberCount', diff --git a/src/parameters/getOrganizationActions.ts b/src/parameters/getOrganizationActions.ts index 9330b150..c46c05fb 100644 --- a/src/parameters/getOrganizationActions.ts +++ b/src/parameters/getOrganizationActions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { ActionSchema } from '../models'; +import { openEnum } from '#/core'; export const GetOrganizationActionsSchema = z.object({ /** The ID or name of the organization */ @@ -8,7 +8,12 @@ export const GetOrganizationActionsSchema = z.object({ * The fields to be returned for the Actions. [See Action fields * here](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#action-object). */ - fields: ActionSchema.optional(), + fields: z + .union([ + openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator']), + z.array(openEnum(['id', 'idMemberCreator', 'data', 'type', 'date', 'limits', 'display', 'memberCreator'])), + ]) + .optional(), /** * A comma-separated list of [action * types](https://developer.atlassian.com/cloud/trello/guides/rest-api/action-types/). @@ -27,7 +32,7 @@ export const GetOrganizationActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) to * return. */ - memberFields: z.string().optional(), + memberFields: z.union([z.string(), z.array(z.string())]).optional(), /** Whether to return the memberCreator object for each action. */ memberCreator: z.boolean().optional(), /** @@ -35,7 +40,7 @@ export const GetOrganizationActionsSchema = z.object({ * [member](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) creator to * return */ - memberCreatorFields: z.string().optional(), + memberCreatorFields: z.union([z.string(), z.array(z.string())]).optional(), /** The page of results for actions. */ page: z.number().optional(), /** Whether to show reactions on comments or not. */ diff --git a/src/parameters/getOrganizationBoards.ts b/src/parameters/getOrganizationBoards.ts index 86febcc9..7016e08c 100644 --- a/src/parameters/getOrganizationBoards.ts +++ b/src/parameters/getOrganizationBoards.ts @@ -12,8 +12,6 @@ export const GetOrganizationBoardsSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'name', diff --git a/src/parameters/getOrganizationField.ts b/src/parameters/getOrganizationField.ts index 1f467029..b30a73c0 100644 --- a/src/parameters/getOrganizationField.ts +++ b/src/parameters/getOrganizationField.ts @@ -5,27 +5,24 @@ export const GetOrganizationFieldSchema = z.object({ /** The ID or name of the organization */ id: z.string(), /** An organization [field](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) */ - field: z.union([ - z.string(), - openEnum([ - 'id', - 'billableMemberCount', - 'desc', - 'descData', - 'displayName', - 'idBoards', - 'invitations', - 'invited', - 'logoHash', - 'memberships', - 'name', - 'powerUps', - 'prefs', - 'premiumFeatures', - 'products', - 'url', - 'website', - ]), + field: openEnum([ + 'id', + 'billableMemberCount', + 'desc', + 'descData', + 'displayName', + 'idBoards', + 'invitations', + 'invited', + 'logoHash', + 'memberships', + 'name', + 'powerUps', + 'prefs', + 'premiumFeatures', + 'products', + 'url', + 'website', ]), }); diff --git a/src/parameters/getToken.ts b/src/parameters/getToken.ts index ab66da3d..a5384c37 100644 --- a/src/parameters/getToken.ts +++ b/src/parameters/getToken.ts @@ -6,8 +6,6 @@ export const GetTokenSchema = z.object({ /** `all` or a comma-separated list of `dateCreated`, `dateExpires`, `idMember`, `identifier`, `permissions` */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum(['identifier', 'idMember', 'dateCreated', 'dateExpires', 'permissions']), z.array(openEnum(['identifier', 'idMember', 'dateCreated', 'dateExpires', 'permissions'])), ]) diff --git a/src/parameters/getTokenMember.ts b/src/parameters/getTokenMember.ts index 41a17a07..d9d65817 100644 --- a/src/parameters/getTokenMember.ts +++ b/src/parameters/getTokenMember.ts @@ -9,8 +9,6 @@ export const GetTokenMemberSchema = z.object({ */ fields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'id', 'activityBlocked', diff --git a/src/parameters/search.ts b/src/parameters/search.ts index bcdf1bcc..fa10e77c 100644 --- a/src/parameters/search.ts +++ b/src/parameters/search.ts @@ -5,7 +5,7 @@ export const SearchSchema = z.object({ /** The search query with a length of 1 to 16384 characters */ query: z.string().max(16834, 'query must be at most 16834 characters'), /** `mine` or a comma-separated list of Board IDs */ - idBoards: z.union([openEnum(['mine']), z.string()]).optional(), + idBoards: openEnum(['mine']).optional(), /** A comma-separated list of Organization IDs */ idOrganizations: z.union([z.string(), z.array(z.string())]).optional(), /** A comma-separated list of Card IDs */ @@ -16,8 +16,6 @@ export const SearchSchema = z.object({ */ modelTypes: z .union([ - z.string(), - z.array(z.string()), openEnum(['actions', 'boards', 'cards', 'members', 'organizations']), z.array(openEnum(['actions', 'boards', 'cards', 'members', 'organizations'])), ]) @@ -29,8 +27,6 @@ export const SearchSchema = z.object({ */ boardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'closed', 'dateLastActivity', @@ -88,8 +84,6 @@ export const SearchSchema = z.object({ */ cardFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'badges', 'checkItemStates', @@ -168,8 +162,6 @@ export const SearchSchema = z.object({ */ organizationFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'billableMemberCount', 'desc', @@ -218,8 +210,6 @@ export const SearchSchema = z.object({ */ memberFields: z .union([ - z.string(), - z.array(z.string()), openEnum([ 'avatarHash', 'bio', diff --git a/src/parameters/starBoard.ts b/src/parameters/starBoard.ts index 85210dfc..2e7857bb 100644 --- a/src/parameters/starBoard.ts +++ b/src/parameters/starBoard.ts @@ -7,7 +7,7 @@ export const StarBoardSchema = z.object({ /** The ID of the board to star */ idBoard: z.string(), /** The position of the newly starred board. `top`, `bottom`, or a positive float. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]), }); export type StarBoard = z.input; diff --git a/src/parameters/updateBoard.ts b/src/parameters/updateBoard.ts index d51ad14e..0736026a 100644 --- a/src/parameters/updateBoard.ts +++ b/src/parameters/updateBoard.ts @@ -13,7 +13,7 @@ export const UpdateBoardSchema = z.object({ /** The id of the Workspace the board should be moved to */ idOrganization: z.string().optional(), /** One of: org, private, public */ - 'prefs/permissionLevel': z.union([z.string(), openEnum(['org', 'private', 'public'])]).optional(), + 'prefs/permissionLevel': openEnum(['org', 'private', 'public']).optional(), /** Whether Workspace members can join the board themselves */ 'prefs/selfJoin': z.boolean().optional(), /** Whether card covers should be displayed on this board */ @@ -21,17 +21,15 @@ export const UpdateBoardSchema = z.object({ /** Determines whether the Voting Power-Up should hide who voted on cards or not. */ 'prefs/hideVotes': z.boolean().optional(), /** Who can invite people to this board. One of: admins, members */ - 'prefs/invitations': z.union([z.string(), openEnum(['admins', 'members'])]).optional(), + 'prefs/invitations': openEnum(['admins', 'members']).optional(), /** Who can vote on this board. One of disabled, members, observers, org, public */ - 'prefs/voting': z.union([z.string(), openEnum(['disabled', 'members', 'observers', 'org', 'public'])]).optional(), + 'prefs/voting': openEnum(['disabled', 'members', 'observers', 'org', 'public']).optional(), /** Who can comment on cards on this board. One of: disabled, members, observers, org, public */ - 'prefs/comments': z.union([z.string(), openEnum(['disabled', 'members', 'observers', 'org', 'public'])]).optional(), + 'prefs/comments': openEnum(['disabled', 'members', 'observers', 'org', 'public']).optional(), /** The id of a custom background or one of: blue, orange, green, red, purple, pink, lime, sky, grey */ - 'prefs/background': z - .union([z.string(), openEnum(['blue', 'orange', 'green', 'red', 'purple', 'pink', 'lime', 'sky', 'grey'])]) - .optional(), + 'prefs/background': openEnum(['blue', 'orange', 'green', 'red', 'purple', 'pink', 'lime', 'sky', 'grey']).optional(), /** One of: pirate, regular */ - 'prefs/cardAging': z.union([z.string(), openEnum(['pirate', 'regular'])]).optional(), + 'prefs/cardAging': openEnum(['pirate', 'regular']).optional(), /** Determines whether the calendar feed is enabled or not. */ 'prefs/calendarFeedEnabled': z.boolean().optional(), id: z.string(), diff --git a/src/parameters/updateBoardMembership.ts b/src/parameters/updateBoardMembership.ts index 894d6cd2..807ef3a1 100644 --- a/src/parameters/updateBoardMembership.ts +++ b/src/parameters/updateBoardMembership.ts @@ -12,21 +12,42 @@ export const UpdateBoardMembershipSchema = z.object({ * Valid values: all, avatarHash, bio, bioData, confirmed, fullName, idPremOrgsAdmin, initials, memberType, products, * status, url, username */ - memberFields: openEnum([ - 'all', - 'avatarHash', - 'bio', - 'bioData', - 'confirmed', - 'fullName', - 'idPremOrgsAdmin', - 'initials', - 'memberType', - 'products', - 'status', - 'url', - 'username', - ]).optional(), + memberFields: z + .union([ + openEnum([ + 'all', + 'avatarHash', + 'bio', + 'bioData', + 'confirmed', + 'fullName', + 'idPremOrgsAdmin', + 'initials', + 'memberType', + 'products', + 'status', + 'url', + 'username', + ]), + z.array( + openEnum([ + 'all', + 'avatarHash', + 'bio', + 'bioData', + 'confirmed', + 'fullName', + 'idPremOrgsAdmin', + 'initials', + 'memberType', + 'products', + 'status', + 'url', + 'username', + ]), + ), + ]) + .optional(), }); export type UpdateBoardMembership = z.input; diff --git a/src/parameters/updateCard.ts b/src/parameters/updateCard.ts index d6e76e85..a98c0378 100644 --- a/src/parameters/updateCard.ts +++ b/src/parameters/updateCard.ts @@ -21,9 +21,9 @@ export const UpdateCardSchema = z.object({ /** The position of the card in its list. `top`, `bottom`, or a positive float */ pos: z.union([openEnum(['top', 'bottom']), z.number()]).optional(), /** When the card is due, or `null` */ - due: z.string().optional(), + due: z.string().nullish(), /** The start date of a card, or `null` */ - start: z.string().optional(), + start: z.string().nullish(), /** Whether the status of the card is complete */ dueComplete: z.boolean().optional(), /** Whether the member is should be subscribed to the card */ diff --git a/src/parameters/updateCardCheckItem.ts b/src/parameters/updateCardCheckItem.ts index ed9d33ad..6285f587 100644 --- a/src/parameters/updateCardCheckItem.ts +++ b/src/parameters/updateCardCheckItem.ts @@ -9,11 +9,11 @@ export const UpdateCardCheckItemSchema = z.object({ /** The ID of the checklist this item is in */ idChecklist: z.string().optional(), /** `top`, `bottom`, or a positive float */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** A due date for the checkitem */ due: z.string().optional(), /** A dueReminder for the due date on the checkitem */ - dueReminder: z.number().optional(), + dueReminder: z.number().nullish(), /** The ID of the member to remove from the card */ idMember: z.string().optional(), /** The ID of the Card */ diff --git a/src/parameters/updateCardChecklistItem.ts b/src/parameters/updateCardChecklistItem.ts index f6b09ab4..c8a27135 100644 --- a/src/parameters/updateCardChecklistItem.ts +++ b/src/parameters/updateCardChecklistItem.ts @@ -7,7 +7,7 @@ export const UpdateCardChecklistItemSchema = z.object({ /** The ID of the checklist item to update */ idCheckItem: z.string(), /** `top`, `bottom`, or a positive float */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** The ID of the item to update. */ idChecklist: z.string(), }); diff --git a/src/parameters/updateChecklist.ts b/src/parameters/updateChecklist.ts index de659242..5c6592ea 100644 --- a/src/parameters/updateChecklist.ts +++ b/src/parameters/updateChecklist.ts @@ -5,7 +5,7 @@ export const UpdateChecklistSchema = z.object({ /** Name of the new checklist being created. Should be length of 1 to 16384. */ name: z.string().optional(), /** Determines the position of the checklist on the card. One of: `top`, `bottom`, or a positive number. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** ID of a checklist. */ id: z.string(), }); diff --git a/src/parameters/updateCustomField.ts b/src/parameters/updateCustomField.ts index fb040791..91bbd4c5 100644 --- a/src/parameters/updateCustomField.ts +++ b/src/parameters/updateCustomField.ts @@ -6,7 +6,7 @@ export const UpdateCustomFieldSchema = z.object({ id: z.string(), /** The name of the Custom Field */ name: z.string().optional(), - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** Whether to display this custom field on the front of cards */ 'display/cardFront': z.boolean().optional(), }); diff --git a/src/parameters/updateLabel.ts b/src/parameters/updateLabel.ts index 8c22db62..713c9917 100644 --- a/src/parameters/updateLabel.ts +++ b/src/parameters/updateLabel.ts @@ -8,12 +8,7 @@ export const UpdateLabelSchema = z.object({ * The new color for the label. See: * [fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/) for color options */ - color: z - .union([ - z.string(), - openEnum(['yellow', 'purple', 'blue', 'red', 'green', 'orange', 'black', 'sky', 'pink', 'lime']), - ]) - .optional(), + color: openEnum(['yellow', 'purple', 'blue', 'red', 'green', 'orange', 'black', 'sky', 'pink', 'lime']).optional(), /** The ID of the Label */ id: z.string(), }); diff --git a/src/parameters/updateListField.ts b/src/parameters/updateListField.ts index 0f510f13..134bd1f4 100644 --- a/src/parameters/updateListField.ts +++ b/src/parameters/updateListField.ts @@ -7,7 +7,7 @@ export const UpdateListFieldSchema = z.object({ /** The field on the List to be updated */ field: openEnum(['name', 'pos', 'subscribed']), /** The new value for the field */ - value: z.union([z.string(), z.number(), openEnum(['top', 'bottom']), z.boolean()]).optional(), + value: z.union([z.number(), openEnum(['top', 'bottom']), z.boolean()]).optional(), }); export type UpdateListField = z.input; diff --git a/src/parameters/updateMemberBoardStar.ts b/src/parameters/updateMemberBoardStar.ts index 60c8ac0e..5a1eb614 100644 --- a/src/parameters/updateMemberBoardStar.ts +++ b/src/parameters/updateMemberBoardStar.ts @@ -3,7 +3,7 @@ import { openEnum } from '#/core'; export const UpdateMemberBoardStarSchema = z.object({ /** New position for the starred board. `top`, `bottom`, or a positive float. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** The ID or username of the member */ id: z.string(), /** The ID of the board star */ diff --git a/src/parameters/updateMemberNotificationChannelBlockedKey.ts b/src/parameters/updateMemberNotificationChannelBlockedKey.ts index 3997695c..7035f3fd 100644 --- a/src/parameters/updateMemberNotificationChannelBlockedKey.ts +++ b/src/parameters/updateMemberNotificationChannelBlockedKey.ts @@ -8,20 +8,17 @@ export const UpdateMemberNotificationChannelBlockedKeySchema = z.object({ /** Channel to block notifications on */ channel: ChannelSchema, /** Singular key or comma-separated list of notification keys */ - blockedKeys: z.union([ - z.string(), - openEnum([ - 'notification_comment_card', - 'notification_added_a_due_date', - 'notification_changed_due_date', - 'notification_card_due_soon', - 'notification_removed_from_card', - 'notification_added_attachment_to_card', - 'notification_created_card', - 'notification_moved_card', - 'notification_archived_card', - 'notification_unarchived_card', - ]), + blockedKeys: openEnum([ + 'notification_comment_card', + 'notification_added_a_due_date', + 'notification_changed_due_date', + 'notification_card_due_soon', + 'notification_removed_from_card', + 'notification_added_attachment_to_card', + 'notification_created_card', + 'notification_moved_card', + 'notification_archived_card', + 'notification_unarchived_card', ]), }); diff --git a/src/parameters/updateMemberSavedSearch.ts b/src/parameters/updateMemberSavedSearch.ts index d74fab81..b9d25773 100644 --- a/src/parameters/updateMemberSavedSearch.ts +++ b/src/parameters/updateMemberSavedSearch.ts @@ -7,7 +7,7 @@ export const UpdateMemberSavedSearchSchema = z.object({ /** The new search query */ query: z.string().optional(), /** New position for saves search. `top`, `bottom`, or a positive float. */ - pos: z.union([z.string(), z.number(), openEnum(['top', 'bottom'])]).optional(), + pos: z.union([z.number(), openEnum(['top', 'bottom'])]).optional(), /** The ID or username of the member */ id: z.string(), /** The ID of the saved search to delete */ diff --git a/src/parameters/updateOrganization.ts b/src/parameters/updateOrganization.ts index 2375a070..68a0af77 100644 --- a/src/parameters/updateOrganization.ts +++ b/src/parameters/updateOrganization.ts @@ -17,15 +17,15 @@ export const UpdateOrganizationSchema = z.object({ /** `1` or `2` */ 'prefs/googleAppsVersion': z.number().optional(), /** Who on the Workspace can make Workspace visible boards. One of `admin`, `none`, `org` */ - 'prefs/boardVisibilityRestrict/org': z.union([z.string(), openEnum(['admin', 'none', 'org'])]).optional(), + 'prefs/boardVisibilityRestrict/org': openEnum(['admin', 'none', 'org']).optional(), /** Who can make private boards. One of: `admin`, `none`, `org` */ - 'prefs/boardVisibilityRestrict/private': z.union([z.string(), openEnum(['admin', 'none', 'org'])]).optional(), + 'prefs/boardVisibilityRestrict/private': openEnum(['admin', 'none', 'org']).optional(), /** Who on the Workspace can make public boards. One of: `admin`, `none`, `org` */ - 'prefs/boardVisibilityRestrict/public': z.union([z.string(), openEnum(['admin', 'none', 'org'])]).optional(), + 'prefs/boardVisibilityRestrict/public': openEnum(['admin', 'none', 'org']).optional(), /** An email address with optional wildcard characters. (E.g. `subdomain.*.trello.com`) */ 'prefs/orgInviteRestrict': z.string().optional(), /** Whether the Workspace page is publicly visible. One of: `private`, `public` */ - 'prefs/permissionLevel': z.union([z.string(), openEnum(['private', 'public'])]).optional(), + 'prefs/permissionLevel': openEnum(['private', 'public']).optional(), /** The ID or name of the Organization */ id: z.string(), }); diff --git a/tests/live/actions.live.test.ts b/tests/live/actions.live.test.ts index 2c1c9d94..90b3ee3e 100644 --- a/tests/live/actions.live.test.ts +++ b/tests/live/actions.live.test.ts @@ -1,5 +1,6 @@ -import { describe, it, expect, beforeAll, afterAll, assert } from 'vitest'; +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import type { TrelloClient } from '../../src/createTrelloClient'; +import { ActionCommentCardSchema } from '../../src/models/actionCommentCard'; import { getLiveClient, getRawLiveClient } from './setup/client'; import { ResourceTracker } from './setup/resources'; import { testName } from './helpers/naming'; @@ -111,15 +112,15 @@ describe('Actions', () => { const newText = testName('updated-comment'); const updated = await trello.actions.updateAction({ id: commentActionId, text: newText }); expect(updated.id).toBe(commentActionId); - assert(updated.type === 'commentCard'); - expect(updated.data.text).toBe(newText); + const comment = ActionCommentCardSchema.parse(updated); + expect(comment.data.text).toBe(newText); }); it('updateActionText also updates the comment text', async () => { const newText = testName('text-updated-comment'); const updated = await trello.actions.updateActionText({ id: commentActionId, value: newText }); - assert(updated.type === 'commentCard'); - expect(updated.data.text).toBe(newText); + const comment = ActionCommentCardSchema.parse(updated); + expect(comment.data.text).toBe(newText); }); }); diff --git a/tests/live/boards.live.test.ts b/tests/live/boards.live.test.ts index 48923558..459a9b65 100644 --- a/tests/live/boards.live.test.ts +++ b/tests/live/boards.live.test.ts @@ -278,6 +278,17 @@ describe('Boards', () => { // ─── preferences ─────────────────────────────────────────────────────────── describe('preferences', () => { + it('raw board preferences include boolean Gmail and list guide flags', async () => { + const board = (await getRawLiveClient().boards.getBoard({ + id: boardId, + myPrefs: true, + fields: 'all', + })) as unknown as { myPrefs?: { aiGoogleGmailEnabled?: unknown; showListGuide?: unknown } }; + + expect(typeof board.myPrefs?.aiGoogleGmailEnabled).toBe('boolean'); + expect(typeof board.myPrefs?.showListGuide).toBe('boolean'); + }); + it('updateBoardShowSidebar returns BoardMyPrefs', async () => { const prefs = await trello.boards.updateBoardShowSidebar({ id: boardId, value: true }); expect(typeof prefs.showSidebar).toBe('boolean'); diff --git a/tests/live/cards.live.test.ts b/tests/live/cards.live.test.ts index b8d73763..b7f4a696 100644 --- a/tests/live/cards.live.test.ts +++ b/tests/live/cards.live.test.ts @@ -1,4 +1,5 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { z } from 'zod'; import type { TrelloClient } from '../../src/createTrelloClient'; import { getLiveClient, getRawLiveClient, getMember2Id } from './setup/client'; import { ResourceTracker } from './setup/resources'; @@ -140,6 +141,17 @@ describe('Cards', () => { expect(card.name).toContain('retrieval-target'); }); + it('raw summary timestamp is null or an ISO date string', async () => { + const raw = (await getRawLiveClient().cards.getCard({ + id: cardId, + fields: 'all', + })) as unknown as { lastSummaryChangeEventAt?: unknown }; + + expect(raw).toHaveProperty('lastSummaryChangeEventAt'); + const timestamp = raw.lastSummaryChangeEventAt; + expect(timestamp === null || z.iso.datetime({ offset: true }).safeParse(timestamp).success).toBe(true); + }); + it('getCardField returns _value for name field', async () => { const result = await trello.cards.getCardField({ id: cardId, field: 'name' }); expect(typeof result._value).toBe('string'); @@ -507,6 +519,7 @@ describe('Cards', () => { expect(typeof attachment.id).toBe('string'); expect(typeof attachment.url).toBe('string'); + expect(attachment).toHaveProperty('aiSummary'); attachmentId = attachment.id; }); @@ -524,6 +537,21 @@ describe('Cards', () => { expect(attachment.id).toBe(attachmentId); }); + it.each([ + { fields: 'id,name' }, + { fields: ['id', 'name'] }, + ])('getCardAttachment selects fields with $fields', async ({ fields }) => { + const attachment = await trello.cards.getCardAttachment({ + id: cardId, + idAttachment: attachmentId, + fields, + }); + + expect(attachment.id).toBe(attachmentId); + expect(attachment.name).toContain('attach'); + expect(attachment.url).toBeUndefined(); + }); + it('deleteCardAttachment removes the attachment', async () => { await expect( trello.cards.deleteCardAttachment({ id: cardId, idAttachment: attachmentId }), diff --git a/tests/unit/api/fieldLists.test.ts b/tests/unit/api/fieldLists.test.ts new file mode 100644 index 00000000..014a3b35 --- /dev/null +++ b/tests/unit/api/fieldLists.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it, vi } from 'vitest'; +import { z } from 'zod'; +import * as parameters from '../../../src/parameters'; +import { getCardAttachment } from '../../../src/api/cards'; +import type { Client } from '../../../src/core'; + +const fieldLists = Object.entries(parameters).flatMap(([name, schema]) => { + if (!(schema instanceof z.ZodObject)) return []; + + return Object.entries(schema.shape) + .filter(([field, value]) => /fields$/i.test(field) && !(value as z.ZodType).safeParse(true).success) + .map(([field, value]) => [name, field, value as z.ZodType] as const); +}); + +describe('field selection parameters', () => { + it.each(fieldLists)('%s.%s accepts strings and arrays', (_name, _field, schema) => { + for (const fields of ['all', 'id,name', ['id', 'name']]) { + expect(schema.safeParse(fields).success).toBe(true); + } + + expect(schema.safeParse(42).success).toBe(false); + expect(schema.safeParse(['id', 42]).success).toBe(false); + }); + + it('keeps customFields as a boolean flag', () => { + expect(parameters.GetBoardSchema.shape.customFields.parse(true)).toBe(true); + expect(parameters.GetBoardSchema.shape.customFields.safeParse('id,name').success).toBe(false); + }); + + it.each([ + { fields: 'id,name', expected: 'id,name' }, + { fields: ['id', 'name'], expected: 'id,name' }, + { fields: 'all', expected: 'all' }, + { fields: undefined, expected: undefined }, + ])('sends attachment fields $fields as one query value', async ({ fields, expected }) => { + const sendRequest = vi.fn().mockResolvedValue({ id: 'attachment' }); + const client = { sendRequest } as unknown as Client; + + await getCardAttachment(client, { id: 'card', idAttachment: 'attachment', fields }); + + expect(sendRequest).toHaveBeenCalledWith(expect.objectContaining({ + url: '/cards/card/attachments/attachment', + searchParams: { fields: expected }, + })); + }); +}); diff --git a/tests/unit/api/plugins.test.ts b/tests/unit/api/plugins.test.ts index 3cb76c33..a7141a43 100644 --- a/tests/unit/api/plugins.test.ts +++ b/tests/unit/api/plugins.test.ts @@ -54,7 +54,7 @@ describe('plugins API (wire shape)', () => { name: 'name', }); const opts = sendRequest.mock.calls[0][0] as { url: string; method: string; body: Record }; - expect(opts.url).toBe('/plugins/p1/listing'); + expect(opts.url).toBe('/plugins/p1/listings'); expect(opts.method).toBe('POST'); expect(opts.body).toEqual({ description: 'desc', diff --git a/tests/unit/core/buildUrl.test.ts b/tests/unit/core/buildUrl.test.ts index 83e7a897..bacd0a0c 100644 --- a/tests/unit/core/buildUrl.test.ts +++ b/tests/unit/core/buildUrl.test.ts @@ -42,6 +42,16 @@ describe('buildUrl', () => { }); }); + describe('array values', () => { + it('joins an array into one comma-separated value', () => { + expect(buildUrl('/boards/123/labels', { fields: ['id', 'name'] })).toBe('/boards/123/labels?fields=id%2Cname'); + }); + + it('sends a single-element array without a trailing comma', () => { + expect(buildUrl('/boards/123/labels', { fields: ['id'] })).toBe('/boards/123/labels?fields=id'); + }); + }); + describe('multiple params', () => { it('appends all non-null params', () => { const url = buildUrl('/cards', { limit: 10, filter: 'open' }); diff --git a/tests/unit/models/cardSummaryDate.test.ts b/tests/unit/models/cardSummaryDate.test.ts new file mode 100644 index 00000000..7d63a9f7 --- /dev/null +++ b/tests/unit/models/cardSummaryDate.test.ts @@ -0,0 +1,31 @@ +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; + +describe('Card summary timestamp in strict schema mode', () => { + let schema: typeof import('../../../src/models/card').CardSchema; + + beforeAll(async () => { + vi.stubEnv('TRELLO_STRICT_SCHEMAS', 'true'); + vi.resetModules(); + schema = (await import('../../../src/models/card')).CardSchema; + }); + + afterAll(() => vi.unstubAllEnvs()); + + it('accepts an omitted timestamp', () => { + expect(schema.parse({ id: 'card' }).lastSummaryChangeEventAt).toBeUndefined(); + }); + + it('preserves null instead of coercing it to the epoch', () => { + expect(schema.parse({ id: 'card', lastSummaryChangeEventAt: null }).lastSummaryChangeEventAt).toBeNull(); + }); + + it('coerces an ISO timestamp to a Date', () => { + const timestamp = '2026-10-11T09:30:00.000Z'; + expect(schema.parse({ id: 'card', lastSummaryChangeEventAt: timestamp }).lastSummaryChangeEventAt) + .toEqual(new Date(timestamp)); + }); + + it('rejects an invalid date', () => { + expect(schema.safeParse({ id: 'card', lastSummaryChangeEventAt: 'invalid-date' }).success).toBe(false); + }); +}); diff --git a/tests/unit/models/tokenPermission.test.ts b/tests/unit/models/tokenPermission.test.ts new file mode 100644 index 00000000..277a6003 --- /dev/null +++ b/tests/unit/models/tokenPermission.test.ts @@ -0,0 +1,25 @@ +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; + +describe('TokenPermission in strict schema mode', () => { + let schema: typeof import('../../../src/models/tokenPermission').TokenPermissionSchema; + + beforeAll(async () => { + vi.stubEnv('TRELLO_STRICT_SCHEMAS', 'true'); + vi.resetModules(); + schema = (await import('../../../src/models/tokenPermission')).TokenPermissionSchema; + }); + + afterAll(() => vi.unstubAllEnvs()); + + it.each(['*', '507f1f77bcf86cd799439011'])('accepts idModel %s', (idModel) => { + expect(schema.parse({ idModel, modelType: 'Board' }).idModel).toBe(idModel); + }); + + it('rejects a non-string model ID', () => { + expect(schema.safeParse({ idModel: 42 }).success).toBe(false); + }); + + it('still validates the model type in strict mode', () => { + expect(schema.safeParse({ modelType: 'Unexpected' }).success).toBe(false); + }); +}); diff --git a/typedoc.json b/typedoc.json index 8e001cb5..de43af13 100644 --- a/typedoc.json +++ b/typedoc.json @@ -11,7 +11,7 @@ "exclude": ["**/*.test.ts", "**/index.ts"], "tsconfig": "tsconfig.json", "out": "docs/api", - "plugin": ["typedoc-plugin-markdown", "typedoc-vitepress-theme"], + "plugin": ["typedoc-plugin-zod", "typedoc-plugin-markdown", "typedoc-vitepress-theme"], "hidePageHeader": true, "hideBreadcrumbs": true, "readme": "none",