Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

### Added

- The upstream codegen (`apis-code-gen`) now resolves `$ref` schemas in parameter and request-body positions natively — they emit `${X}Schema` references (and imports) instead of falling through to `z.unknown()`. Closes the root cause across the spec; each consumer no longer needs a per-config inlining patch. As a result:
- **Path-level `id` parameters**: every operation that takes a `{id}` now generates `id: TrelloIDSchema` (imported from `../models`) rather than `id: z.unknown()`. Affects 200+ parameter files.
- **Top-level `oneOf` schemas** (e.g. `posStringOrNumber: oneOf:[{string,enum:['top','bottom']}, {number}]`) are emitted as proper `z.union([...])` schemas in the models directory. The Trello-specific workaround that flattened `posStringOrNumber` to `z.number()` has been removed.
- **Path-level shared parameters** are merged into operation-level parameters via the `mergePathParameters` transform so they participate in the normal generation pipeline.
- **`fields`-style CSV query params** (entities `Action`, `Attachment`, `Board`, `Card`, `Notification`, `Organization`, `Token`): now accept `z.enum([...documented field names...])` or an array thereof in addition to the existing free-form `string | string[]`. Affected: `getAction`, `getActionBoard`, `getActionCard`, `getActionOrganization`, `getBoardLists`, `getCard`, `getCardAttachments`, `getCardBoard`, `getEnterpriseOrganizations`, `getListBoard`, `getMember`, `getMemberBoards`, `getMemberInvitedBoards`, `getMemberInvitedOrganizations`, `getMemberNotifications`, `getMemberOrganizations`, `getNotification`, `getNotificationBoard`, `getNotificationCard`, `getNotificationOrganization`, `getOrganizationBoards`, `getToken`, `deactivateEnterpriseMember`. Entities whose `<Entity>Fields` enum was missing or unusable in the swagger are seeded separately (see the next two bullets).
- **`fields` params for entities whose swagger enum was missing or truncated** — `List` (shipped as the singleton `['id']`), `Organization` (truncated to `['id', 'name']`), and `Checklist` / `Sticker` / `Label` / `CustomEmoji` (no `<Entity>Fields` schema at all). The `<Entity>Fields` enums are now seeded/created from the corresponding object models (`TrelloList`, `Organization`, `Checklist`, `Label`, `CustomEmoji`) and the documented Sticker object, so these params expose the typed enum as the 4-branch `string | string[] | enum | enum[]` union. New generated models: `ListFieldsSchema` (expanded), `OrganizationFieldsSchema` (expanded), `ChecklistFieldsSchema`, `StickerFieldsSchema`, `LabelFieldsSchema`, `CustomEmojiFieldsSchema`. Affected params include `getList.fields`, `getBoardLists.fields`, `getCardList.fields`, `getActionList.fields`, `getNotificationList.fields`, `getChecklist.fields`, `getCard.checklistFields`/`stickerFields`, `getCardSticker.fields`, `getCardStickers.fields`, `getLabel.fields`, and the organization-`fields` params across `getMember`, `getMemberBoards`, `getMemberOrganizations`, `getMemberInvitedOrganizations`, `getEnterpriseOrganizations`, `getActionOrganization`, `getNotification`, `getNotificationOrganization`, `search`. Loose `string`/`string[]` branches retained — non-breaking.
- **Member `fields` params**: Trello's swagger ships the `MemberFields` enum as a useless singleton (`['id']`), so every member-`fields` param had degraded to a bare string (or, where the swagger used an explicit `$ref`, to the over-restrictive `MemberFieldsSchema` that accepted only `'id'`). The `MemberFields` enum is now seeded from the [documented member object fields](https://developer.atlassian.com/cloud/trello/guides/rest-api/object-definitions/#member-object) (`id`, `avatarHash`, `avatarUrl`, `fullName`, `username`, `initials`, `confirmed`, `idBoards`, `idOrganizations`, …), so all member-`fields` params now expose the typed enum (CSV params as the 4-branch `string | string[] | enum | enum[]` union; the single-value `getMemberField.field` path param as `string | enum`). Affected: `getEnterpriseMembers.fields`, `getBoardMemberships.memberFields`, `getActionMember.fields`, `getActionCreator.fields`, `getCardMembers.fields`, `getCardMembersVoted.fields`, `getNotificationMember.fields`, `getNotificationCreator.fields`, `getTokenMember.fields`, `getMemberField.field`, plus the `memberFields`/`memberCreatorFields`/`memberVotedFields` params on `getAction`, `getCard`, `getMember`, `getMemberNotifications`, `getNotification`. The loose `string`/`string[]` branches are retained, so this is non-breaking and undocumented field names are still accepted.
- **Inline-backtick CSV query params** ("Comma-separated list of: `a`, `b`, …" / "all or a comma-separated list of: `a`, `b`, …" with the field names listed inline and no `[fields](…)` doc link): now accept `z.enum([…])` or an array thereof alongside the free-form `string | string[]`. Affected: `getEnterprise.fields`, `getCardCheckItemStates.fields`, `search.modelTypes`/`boardFields`/`cardFields`. Interrupting parentheticals in the description (e.g. the pagination caveat on `getEnterprise.fields`) are stripped before extraction.
- **Single-value `$ref` enums in query and path params**: `Color` (`createLabel.color`, `updateLabel.color`), `ViewFilter` (`getBoardLists.cards`/`filter`, `getBoardListsByFilter.filter`), and the path `field` params on `getActionField`, `getCardField`, `getNotificationField`, `getOrganizationField` now expose `z.union([z.string(), z.enum([...])])`.
- **Inline-listed JSDoc enums** ("One of: `a`, `b`, `c`" / "Valid values: a, b, c") on plain `string` params: `boardStars`, `getBoardStars.filter`, `getEnterprise.members`/`memberFields`/`memberSortOrder`/`organizations`, `getEnterpriseMembers.count`, `createEnterpriseToken.expiration`, `getBoardField.field`, `getMemberNotifications.readFilter`, `updateBoard.prefs/{permissionLevel,invitations,voting,comments,background,cardAging}`, `updateOrganization.prefs/{boardVisibilityRestrict/*,permissionLevel}`.
- **Positioning params** (`pos` and friends) — `top`, `bottom`, or a positive number — typed as `z.union([z.string(), z.number(), z.enum(['top', 'bottom'])])` across `createBoardList`, `createCardChecklist`, `createChecklist`, `createChecklistItem`, `createCustomField`, `createCustomFieldOption`, `createMemberSavedSearch`, `starBoard`, `updateCardCheckItem`, `updateCardChecklistItem`, `updateChecklist`, `updateCustomField`, `updateMemberBoardStar`, `updateMemberSavedSearch`. Loose `z.string()` branch kept for backward compatibility with callers that previously passed `z.string()` / `z.unknown()`.
- **`$ref`-to-enum/primitive-union request body fields** picked up the same treatment, so body-side `pos`/`color`/`idCard`/etc. flow through the same inline expansion instead of `z.unknown()`.
- `POST /checklists.name` JSDoc now documents the server-side default (`**Defaults**: `Checklist``) — verified empirically against the live API.

### Internal

- Build scripts (`scripts/build-og-image`, `scripts/copy-api-to-ru`) migrated from `.mjs` to TypeScript, executed via `tsx`. `tsx` added as a dev dependency.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,5 @@
"engines": {
"node": ">=22"
},
"packageManager": "pnpm@11.1.3"
"packageManager": "pnpm@11.2.2"
}
15 changes: 7 additions & 8 deletions src/models/action.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { LimitsSchema } from '#/models/limits';
import { MemberSchema } from '#/models/member';

export const ActionSchema = apiObject({
id: TrelloIDSchema,
idMemberCreator: TrelloIDSchema,
id: z.string(),
idMemberCreator: z.string(),
data: z.record(z.string(), z.any()),
type: z.string(),
date: z.coerce.date(),
Expand All @@ -18,12 +17,12 @@ export const ActionSchema = apiObject({
type: z.string().optional(),
translationKey: z.string().optional(),
hideIfContext: z.boolean().optional(),
idContext: TrelloIDSchema.optional(),
idContext: z.string().optional(),
}).optional(),
card: apiObject({
type: z.string().optional(),
hideIfContext: z.boolean().optional(),
id: TrelloIDSchema,
id: z.string(),
shortLink: z.string().optional(),
text: z.string().optional(),
}).optional(),
Expand All @@ -33,19 +32,19 @@ export const ActionSchema = apiObject({
}).optional(),
memberCreator: apiObject({
type: z.string().optional(),
id: TrelloIDSchema,
id: z.string(),
username: z.string().optional(),
text: z.string().optional(),
}).optional(),
}).optional(),
}).optional(),
memberCreator: apiObject({
id: TrelloIDSchema,
id: z.string(),
activityBlocked: z.boolean().optional(),
avatarHash: z.string().optional(),
avatarUrl: z.string().optional(),
fullName: z.string().optional(),
idMemberReferrer: TrelloIDSchema.nullish(),
idMemberReferrer: z.string().nullish(),
initials: z.string().optional(),
username: z.string().optional(),
nonPublic: z.record(z.string(), z.any()).optional(),
Expand Down
5 changes: 2 additions & 3 deletions src/models/attachment.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { ColorSchema } from '#/models/color';
import { LimitsSchema } from '#/models/limits';

export const AttachmentSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
bytes: z.string().nullish(),
date: z.coerce.date().optional(),
edgeColor: ColorSchema.nullish(),
idMember: TrelloIDSchema.optional(),
idMember: z.string().optional(),
isUpload: z.boolean().optional(),
mimeType: z.string().optional(),
name: z.string().optional(),
Expand Down
7 changes: 3 additions & 4 deletions src/models/board.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { PrefsSchema } from '#/models/prefs';
import { LimitsSchema } from '#/models/limits';
import { MembershipsSchema } from '#/models/memberships';
import { BoardMyPrefsSchema } from '#/models/boardMyPrefs';
import { OrganizationSchema } from '#/models/organization';

export const BoardSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
/** The name of the board. */
name: z.string().optional(),
desc: z.string().optional(),
descData: z.record(z.string(), z.any()).nullish(),
closed: z.boolean().optional(),
idMemberCreator: TrelloIDSchema.optional(),
idOrganization: TrelloIDSchema.optional(),
idMemberCreator: z.string().optional(),
idOrganization: z.string().optional(),
pinned: z.boolean().optional(),
url: z.string().optional(),
shortUrl: z.string().optional(),
Expand Down
3 changes: 1 addition & 2 deletions src/models/boardBackground.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { ImageDescriptorSchema } from '#/models/imageDescriptor';

export const BoardBackgroundSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
attribution: apiObject({
url: z.string().nullish(),
name: z.string().nullish(),
Expand Down
5 changes: 2 additions & 3 deletions src/models/boardStars.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const BoardStarsSchema = apiObject({
id: TrelloIDSchema,
idBoard: TrelloIDSchema.optional(),
id: z.string(),
idBoard: z.string().optional(),
pos: z.number().optional(),
});

Expand Down
25 changes: 13 additions & 12 deletions src/models/card.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { ChecklistSchema } from '#/models/checklist';
import { LabelSchema } from '#/models/label';
import { LimitsSchema } from '#/models/limits';
import { ColorSchema } from '#/models/color';

export const CardSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
address: z.string().nullish(),
badges: apiObject({
attachmentsByType: apiObject({
Expand Down Expand Up @@ -44,27 +45,27 @@ export const CardSchema = apiObject({
}).optional(),
due: z.coerce.date().nullish(),
dueReminder: z.string().nullish(),
idBoard: TrelloIDSchema.optional(),
idChecklists: z.array(z.union([z.unknown(), z.unknown()])).optional(),
idLabels: z.array(z.union([z.unknown(), z.unknown()])).optional(),
idList: TrelloIDSchema.optional(),
idMembers: z.array(z.unknown()).optional(),
idMembersVoted: z.array(z.unknown()).optional(),
idBoard: z.string().optional(),
idChecklists: z.array(z.union([ChecklistSchema, z.string()])).optional(),
idLabels: z.array(z.union([LabelSchema, z.string()])).optional(),
idList: z.string().optional(),
idMembers: z.array(z.string()).optional(),
idMembersVoted: z.array(z.string()).optional(),
idShort: z.number().optional(),
idAttachmentCover: TrelloIDSchema.nullish(),
labels: z.array(z.unknown()).optional(),
idAttachmentCover: z.string().nullish(),
labels: z.array(LabelSchema).optional(),
limits: LimitsSchema.optional(),
locationName: z.string().nullish(),
manualCoverAttachment: z.boolean().optional(),
mirrorSourceId: TrelloIDSchema.nullish(),
mirrorSourceId: z.string().nullish(),
name: z.string().optional(),
pos: z.number().optional(),
shortLink: z.string().optional(),
shortUrl: z.string().optional(),
subscribed: z.boolean().optional(),
url: z.string().optional(),
cover: apiObject({
idAttachment: TrelloIDSchema.nullish(),
idAttachment: z.string().nullish(),
color: ColorSchema.nullish(),
idUploadedBackground: z.boolean().nullish(),
size: z.enum(['normal']).optional(),
Expand Down
7 changes: 3 additions & 4 deletions src/models/checkItem.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { posStringOrNumberSchema } from '#/models/posStringOrNumber';
import { LimitsSchema } from '#/models/limits';

export const CheckItemSchema = apiObject({
idChecklist: TrelloIDSchema.optional(),
idChecklist: z.string().optional(),
state: z.enum(['complete', 'incomplete']).optional(),
id: TrelloIDSchema,
id: z.string(),
name: z.string().optional(),
nameData: z.record(z.string(), z.any()).optional(),
pos: posStringOrNumberSchema.optional(),
due: z.coerce.date().nullish(),
dueReminder: z.number().nullish(),
idMember: TrelloIDSchema.nullish(),
idMember: z.string().nullish(),
limits: LimitsSchema.optional(),
creationMethod: z.unknown().optional(),
});
Expand Down
7 changes: 3 additions & 4 deletions src/models/checklist.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { posStringOrNumberSchema } from '#/models/posStringOrNumber';
import { CheckItemSchema } from '#/models/checkItem';
import { LimitsSchema } from '#/models/limits';

export const ChecklistSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
name: z.string().optional(),
idBoard: TrelloIDSchema.optional(),
idCard: TrelloIDSchema.optional(),
idBoard: z.string().optional(),
idCard: z.string().optional(),
pos: posStringOrNumberSchema.optional(),
checkItems: z.array(CheckItemSchema).optional(),
limits: LimitsSchema.optional(),
Expand Down
5 changes: 5 additions & 0 deletions src/models/checklistFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { z } from 'zod';

export const ChecklistFieldsSchema = z.enum(['id', 'name', 'idBoard', 'idCard', 'pos']);

export type ChecklistFields = z.infer<typeof ChecklistFieldsSchema>;
5 changes: 2 additions & 3 deletions src/models/claimableOrganizations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const ClaimableOrganizationsSchema = apiObject({
organizations: z
Expand All @@ -9,9 +8,9 @@ export const ClaimableOrganizationsSchema = apiObject({
name: z.string().optional(),
displayName: z.string().optional(),
activeMembershipCount: z.number().optional(),
idActiveAdmins: z.array(TrelloIDSchema).optional(),
idActiveAdmins: z.array(z.string()).optional(),
products: z.array(z.number()).optional(),
id: TrelloIDSchema,
id: z.string(),
logoUrl: z.string().nullish(),
/**
* The date of the most recent activity on any of the boards in the workspace. If the workspace has no boards,
Expand Down
3 changes: 1 addition & 2 deletions src/models/customEmoji.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const CustomEmojiSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
url: z.string().optional(),
name: z.string().optional(),
});
Expand Down
5 changes: 5 additions & 0 deletions src/models/customEmojiFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { z } from 'zod';

export const CustomEmojiFieldsSchema = z.enum(['id', 'name', 'url']);

export type CustomEmojiFields = z.infer<typeof CustomEmojiFieldsSchema>;
7 changes: 3 additions & 4 deletions src/models/customField.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const CustomFieldSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
idModel: z.string().optional(),
modelType: z.enum(['card', 'board', 'member']).optional(),
fieldGroup: z.string().optional(),
Expand All @@ -14,8 +13,8 @@ export const CustomFieldSchema = apiObject({
options: z
.array(
apiObject({
id: TrelloIDSchema,
idCustomField: TrelloIDSchema.optional(),
id: z.string(),
idCustomField: z.string().optional(),
value: apiObject({
text: z.string().optional(),
}).optional(),
Expand Down
7 changes: 3 additions & 4 deletions src/models/customFieldItems.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const CustomFieldItemsSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
value: apiObject({
checked: z.string().optional(),
}).optional(),
idCustomField: TrelloIDSchema.optional(),
idModel: TrelloIDSchema.optional(),
idCustomField: z.string().optional(),
idModel: z.string().optional(),
modelType: z.enum(['card', 'board', 'member']).optional(),
});

Expand Down
3 changes: 1 addition & 2 deletions src/models/customSticker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { ImageDescriptorSchema } from '#/models/imageDescriptor';
import { LimitsSchema } from '#/models/limits';

export const CustomStickerSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
url: z.string().optional(),
scaled: z.array(ImageDescriptorSchema).optional(),
image: z.string().nullish(),
Expand Down
9 changes: 4 additions & 5 deletions src/models/enterprise.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { OrganizationPrefsSchema } from '#/models/organizationPrefs';

export const EnterpriseSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
name: z.string().optional(),
displayName: z.string().optional(),
logoHash: z.string().nullish(),
Expand All @@ -23,11 +22,11 @@ export const EnterpriseSchema = apiObject({
}).optional(),
organizationPrefs: OrganizationPrefsSchema.optional(),
ssoActivationFailed: z.boolean().optional(),
idAdmins: z.array(TrelloIDSchema).optional(),
idAdmins: z.array(z.string()).optional(),
enterpriseDomains: z.array(z.string()).optional(),
isRealEnterprise: z.boolean().optional(),
pluginWhitelistingEnabled: z.array(TrelloIDSchema).optional(),
idOrganizations: z.array(TrelloIDSchema).optional(),
pluginWhitelistingEnabled: z.array(z.string()).optional(),
idOrganizations: z.array(z.string()).optional(),
products: z.array(z.number()).optional(),
licenses: apiObject({
maxMembers: z.number().nullish(),
Expand Down
3 changes: 1 addition & 2 deletions src/models/enterpriseAdmin.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';

export const EnterpriseAdminSchema = apiObject({
id: TrelloIDSchema,
id: z.string(),
fullName: z.string().optional(),
username: z.string().optional(),
});
Expand Down
5 changes: 2 additions & 3 deletions src/models/enterpriseAuditLog.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { z } from 'zod';
import { apiObject } from '#/core';
import { TrelloIDSchema } from '#/models/trelloID';
import { OrganizationSchema } from '#/models/organization';
import { MemberSchema } from '#/models/member';

export const EnterpriseAuditLogSchema = apiObject({
idAction: TrelloIDSchema.optional(),
idAction: z.string().optional(),
type: z.string().optional(),
date: z.coerce.date().optional(),
memberCreator: apiObject({
id: TrelloIDSchema,
id: z.string(),
username: z.string().optional(),
fullName: z.string().optional(),
}).optional(),
Expand Down
Loading