@air/api-rest 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Typed REST client for the [Air API SDK](https://github.com/AirLabsTeam/air-api-sdk).
4
4
 
5
- This package provides the resource classes (boards, showcases, assets, tags, custom fields, uploads, imports, roles) and their TypeScript types. It builds on `@air/api-core` for HTTP transport.
5
+ This package provides the resource classes (boards, showcases, assets, tags, custom fields, discussions, members, uploads, imports, roles) and their TypeScript types. It builds on `@air/api-core` for HTTP transport.
6
6
 
7
7
  ## Installation
8
8
 
@@ -20,7 +20,9 @@ npm install @air/api-rest
20
20
 
21
21
  ## What's included
22
22
 
23
- - Resource classes: `Boards`, `Showcases`, `Assets`, `Tags`, `CustomFields`, `Uploads`, `Imports`, `Roles`
23
+ - Resource classes: `Boards`, `Showcases`, `Assets`, `Tags`, `CustomFields`, `Discussions`, `Members`, `Uploads`, `Imports`, `Roles`
24
+ - Discussions: `list`, `get`, `listComments`, `create`, `createComment`, `update`, `updateComment`, `deleteComment`
25
+ - Members: `list`
24
26
  - Showcases: `list`, `get`, `create`, `update`, `updateShareLink`, `addAssets`, `removeAsset`, `addBoards`, `removeBoard`, plus a `showcaseId` filter on `assets.list` and `boards.list`
25
27
  - Asset CDN link helpers: `listCdnLinks`, `createCdnLink`, and `updateCdnLink`
26
28
  - Share links: `listShareLinks`, `createShareLink`, and `updateShareLink` on assets and boards
package/dist/index.cjs CHANGED
@@ -40,9 +40,11 @@ __export(index_exports, {
40
40
  ConnectionError: () => import_api_core2.ConnectionError,
41
41
  CursorPage: () => import_api_core2.CursorPage,
42
42
  CustomFields: () => CustomFields,
43
+ Discussions: () => Discussions,
43
44
  Imports: () => Imports,
44
45
  InternalServerError: () => import_api_core2.InternalServerError,
45
46
  Libraries: () => Libraries,
47
+ Members: () => Members,
46
48
  NotFoundError: () => import_api_core2.NotFoundError,
47
49
  PagePromise: () => import_api_core2.PagePromise,
48
50
  PermissionError: () => import_api_core2.PermissionError,
@@ -418,6 +420,118 @@ var CustomFields = class {
418
420
  }
419
421
  };
420
422
 
423
+ // src/resources/discussions.ts
424
+ var Discussions = class {
425
+ constructor(client) {
426
+ this.client = client;
427
+ }
428
+ /**
429
+ * List discussions on an asset or on the assets currently in a board.
430
+ * Exactly one of `assetId` or `boardId` is required.
431
+ *
432
+ * Pages don't overlap. With the default `lastCommentedAt` sort, a reply
433
+ * between pages can move a discussion, so it may repeat or be skipped. For
434
+ * a stable walk, use `sortBy: "createdAt"` and `sortDirection: "asc"`.
435
+ */
436
+ list(params) {
437
+ const query = {
438
+ assetId: params.assetId,
439
+ assetVersionId: params.assetVersionId,
440
+ boardId: params.boardId,
441
+ resolved: params.resolved,
442
+ sortBy: params.sortBy,
443
+ sortDirection: params.sortDirection,
444
+ limit: params.limit,
445
+ cursor: params.cursor
446
+ };
447
+ return this.client.requestCursorPage(
448
+ { method: "GET", path: "/discussions", query },
449
+ query
450
+ );
451
+ }
452
+ /** Get one discussion, including its first 10 comments. A discussion you cannot view is 404. */
453
+ async get(discussionId) {
454
+ return this.client.request({
455
+ method: "GET",
456
+ path: `/discussions/${discussionId}`
457
+ });
458
+ }
459
+ /**
460
+ * List every comment on a discussion, oldest first.
461
+ * `discussion.comments.pagination.cursor` is accepted as `cursor`.
462
+ */
463
+ listComments(discussionId, params = {}) {
464
+ const query = {
465
+ limit: params.limit,
466
+ cursor: params.cursor
467
+ };
468
+ return this.client.requestCursorPage(
469
+ { method: "GET", path: `/discussions/${discussionId}/comments`, query },
470
+ query
471
+ );
472
+ }
473
+ /**
474
+ * Start a discussion on an asset version. `assetVersionId` is required.
475
+ * Mention someone with `{{mention:N}}` and a `mentions` entry at that index.
476
+ * On a document or PDF, every annotation needs a `pageNumber`.
477
+ *
478
+ * The body has no board. In a workspace that scopes comments to boards, a
479
+ * discussion with no board needs `asset.canManageDiscussions` at the
480
+ * workspace level, so a board guest gets 403 even when they can comment in
481
+ * their board. A timeout can create a duplicate: list before retrying.
482
+ */
483
+ async create(params) {
484
+ return this.client.request({
485
+ method: "POST",
486
+ path: "/discussions",
487
+ body: params
488
+ });
489
+ }
490
+ /** Add a comment. The body and mention rules match `create`. */
491
+ async createComment(discussionId, params) {
492
+ return this.client.request({
493
+ method: "POST",
494
+ path: `/discussions/${discussionId}/comments`,
495
+ body: params
496
+ });
497
+ }
498
+ /**
499
+ * Resolve or reopen a discussion. The response is empty, including when the
500
+ * discussion was already in the requested state.
501
+ */
502
+ async update(discussionId, params) {
503
+ return this.client.request({
504
+ method: "PATCH",
505
+ path: `/discussions/${discussionId}`,
506
+ body: params
507
+ });
508
+ }
509
+ /**
510
+ * Replace a comment's text and mentions. Only the author can edit.
511
+ * The response is empty, and the edit notifies no one. An edit that leaves
512
+ * the text and mentions as they are changes nothing and keeps `updatedAt`.
513
+ * Omitting `mentions`, or sending `null`, when the comment has them is 409.
514
+ * `[]` removes them.
515
+ */
516
+ async updateComment(discussionId, commentId, params) {
517
+ return this.client.request({
518
+ method: "PATCH",
519
+ path: `/discussions/${discussionId}/comments/${commentId}`,
520
+ body: params
521
+ });
522
+ }
523
+ /**
524
+ * Delete a comment. Only the author can delete. The response is empty.
525
+ * Deleting the last comment deletes the discussion.
526
+ */
527
+ async deleteComment(discussionId, commentId) {
528
+ return this.client.request({
529
+ method: "DELETE",
530
+ path: `/discussions/${discussionId}/comments/${commentId}`
531
+ });
532
+ }
533
+ };
534
+
421
535
  // src/resources/imports.ts
422
536
  var Imports = class {
423
537
  constructor(client) {
@@ -482,6 +596,30 @@ var Libraries = class {
482
596
  }
483
597
  };
484
598
 
599
+ // src/resources/members.ts
600
+ var Members = class {
601
+ constructor(client) {
602
+ this.client = client;
603
+ }
604
+ /**
605
+ * List people in the workspace. Requires `members.read`.
606
+ * `workspace.read` does not grant it.
607
+ *
608
+ * Sort is fixed: `firstJoinedAt` ascending, then `id`.
609
+ * `email` without `type` searches every type. An unknown email is an empty list.
610
+ */
611
+ list(params = {}) {
612
+ const query = {
613
+ type: params.type,
614
+ email: params.email,
615
+ search: params.search,
616
+ limit: params.limit,
617
+ cursor: params.cursor
618
+ };
619
+ return this.client.requestCursorPage({ method: "GET", path: "/members", query }, query);
620
+ }
621
+ };
622
+
485
623
  // src/resources/roles.ts
486
624
  var Roles = class {
487
625
  constructor(client) {
@@ -921,6 +1059,8 @@ var AirApi = class extends import_api_core.AirBase {
921
1059
  libraries;
922
1060
  tags;
923
1061
  customFields;
1062
+ discussions;
1063
+ members;
924
1064
  roles;
925
1065
  imports;
926
1066
  uploads;
@@ -933,6 +1073,8 @@ var AirApi = class extends import_api_core.AirBase {
933
1073
  this.libraries = new Libraries(this);
934
1074
  this.tags = new Tags(this);
935
1075
  this.customFields = new CustomFields(this);
1076
+ this.discussions = new Discussions(this);
1077
+ this.members = new Members(this);
936
1078
  this.roles = new Roles(this);
937
1079
  this.imports = new Imports(this);
938
1080
  this.uploads = new Uploads(this);
@@ -954,9 +1096,11 @@ var import_api_core2 = require("@air/api-core");
954
1096
  ConnectionError,
955
1097
  CursorPage,
956
1098
  CustomFields,
1099
+ Discussions,
957
1100
  Imports,
958
1101
  InternalServerError,
959
1102
  Libraries,
1103
+ Members,
960
1104
  NotFoundError,
961
1105
  PagePromise,
962
1106
  PermissionError,
package/dist/index.d.cts CHANGED
@@ -457,6 +457,226 @@ declare class CustomFields {
457
457
  deleteValue(customFieldId: string, valueId: string): Promise<void>;
458
458
  }
459
459
 
460
+ /**
461
+ * Exactly one of `assetId` or `boardId`. `assetVersionId` requires `assetId`.
462
+ * The server rejects any other combination, so the type does too.
463
+ */
464
+ type DiscussionListParams = DiscussionListOptions & ({
465
+ /** Discussions on this asset. */
466
+ assetId: string;
467
+ /** Limit the asset list to this version. */
468
+ assetVersionId?: string;
469
+ boardId?: never;
470
+ } | {
471
+ /** Discussions on assets currently on this board. */
472
+ boardId: string;
473
+ assetId?: never;
474
+ assetVersionId?: never;
475
+ });
476
+ interface DiscussionListOptions extends CursorPageParams {
477
+ /** When set, only discussions in that resolved state. */
478
+ resolved?: boolean;
479
+ /**
480
+ * `lastCommentedAt` is the default and moves when someone replies.
481
+ * `createdAt` is the first comment and stays put.
482
+ */
483
+ sortBy?: "lastCommentedAt" | "createdAt";
484
+ /** `desc` is the default. */
485
+ sortDirection?: "asc" | "desc";
486
+ }
487
+ interface DiscussionCommentListParams extends CursorPageParams {
488
+ }
489
+ interface Discussion {
490
+ id: string;
491
+ resolved: boolean;
492
+ /** When the first comment was created. */
493
+ createdAt: string | null;
494
+ /** When the latest comment was created. A reply moves this. */
495
+ lastCommentedAt: string | null;
496
+ asset: {
497
+ id: string;
498
+ };
499
+ assetVersion: {
500
+ /** Asset version id. This is `assetVersionId` on create. */
501
+ id: string;
502
+ version: number;
503
+ };
504
+ /**
505
+ * Present only when the stored board is active and the caller can view it.
506
+ * Otherwise the field is omitted.
507
+ */
508
+ boardId?: string;
509
+ annotations: DiscussionAnnotation[];
510
+ /** The first 10 comments, oldest first. */
511
+ comments: DiscussionCommentPage;
512
+ }
513
+ interface DiscussionCommentPage {
514
+ data: DiscussionComment[];
515
+ pagination: {
516
+ hasMore: boolean;
517
+ cursor: string | null;
518
+ };
519
+ total: number;
520
+ }
521
+ interface DiscussionComment {
522
+ id: string;
523
+ discussionId: string;
524
+ /** Plain text with mentions rendered as `@Display Name`. */
525
+ body: string;
526
+ createdAt: string;
527
+ /**
528
+ * Equal to `createdAt` until the first edit that changes the stored text.
529
+ * An edit is `updatedAt !== createdAt`.
530
+ */
531
+ updatedAt: string;
532
+ author: DiscussionAuthor;
533
+ mentions: DiscussionMention[];
534
+ }
535
+ type DiscussionAuthor = {
536
+ type: "workspace_account";
537
+ /** Account id. The same id as `members.list` `id`. */
538
+ id: string;
539
+ displayName: string | null;
540
+ } | {
541
+ type: "anonymous";
542
+ displayName: string | null;
543
+ };
544
+ /** A mention on a comment. `id` is the account id. */
545
+ interface DiscussionMention {
546
+ id: string;
547
+ displayName: string | null;
548
+ }
549
+ /** A mention sent on create or edit. `accountId` is `DiscussionMention.id`. */
550
+ interface DiscussionMentionInput {
551
+ accountId: string;
552
+ }
553
+ type DiscussionAnnotation = BoxAnnotation | PencilAnnotation;
554
+ interface BoxAnnotation {
555
+ type: "box";
556
+ /** Seconds into a video. Omit for a still image. */
557
+ timestamp?: number;
558
+ /** Requires `timestamp`, and must be greater than or equal to it. */
559
+ endTimestamp?: number;
560
+ /** Top-left corner as fractions of the frame, from 0 to 1. */
561
+ coordinates: {
562
+ x: number;
563
+ y: number;
564
+ };
565
+ /** Width and height as fractions of the frame. The box must fit in the frame. */
566
+ dimensions: {
567
+ width: number;
568
+ height: number;
569
+ };
570
+ /** `#RRGGBB`, either case, on write. A stored annotation read back may use another color format. */
571
+ color: string;
572
+ /** Document page, from 1. Required on a document or PDF. Omit for an image or video. */
573
+ pageNumber?: number;
574
+ }
575
+ interface PencilAnnotation {
576
+ type: "pencil";
577
+ /** Seconds into a video. Omit for a still image. */
578
+ timestamp?: number;
579
+ /** Requires `timestamp`, and must be greater than or equal to it. */
580
+ endTimestamp?: number;
581
+ /** 1 to 10 lines. */
582
+ lines: PencilLine[];
583
+ }
584
+ interface PencilLine {
585
+ /** 2 to 1000 points, each a fraction of the frame from 0 to 1. */
586
+ coordinates: {
587
+ x: number;
588
+ y: number;
589
+ }[];
590
+ /** Greater than 0 and at most 1000. */
591
+ lineWidth: number;
592
+ /** `#RRGGBB`, either case, on write. A stored annotation read back may use another color format. */
593
+ color: string;
594
+ /** Document page, from 1. Required on a document or PDF. Omit for an image or video. */
595
+ pageNumber?: number;
596
+ }
597
+ interface DiscussionCreateParams {
598
+ assetId: string;
599
+ /** Required. There is no default to the current version. */
600
+ assetVersionId: string;
601
+ /** Plain text, 1 to 500 characters. Mention someone with `{{mention:N}}`. */
602
+ body: string;
603
+ /** At most 10. `null` is the same as omitting it. */
604
+ mentions?: DiscussionMentionInput[] | null;
605
+ /** At most 10. */
606
+ annotations?: DiscussionAnnotation[];
607
+ }
608
+ interface DiscussionCommentCreateParams {
609
+ /** Plain text, 1 to 500 characters. Mention someone with `{{mention:N}}`. */
610
+ body: string;
611
+ /** At most 10. `null` is the same as omitting it. */
612
+ mentions?: DiscussionMentionInput[] | null;
613
+ }
614
+ interface DiscussionCommentUpdateParams {
615
+ body: string;
616
+ /**
617
+ * Required when the stored comment has mentions. Send the mentions again to
618
+ * keep them, or `[]` to remove them. Omitting this field, or sending `null`,
619
+ * on a comment that has mentions is 409.
620
+ */
621
+ mentions?: DiscussionMentionInput[] | null;
622
+ }
623
+ interface DiscussionUpdateParams {
624
+ /** `true` resolves the discussion. `false` reopens it. */
625
+ resolved: boolean;
626
+ }
627
+
628
+ declare class Discussions {
629
+ private client;
630
+ constructor(client: AirBase);
631
+ /**
632
+ * List discussions on an asset or on the assets currently in a board.
633
+ * Exactly one of `assetId` or `boardId` is required.
634
+ *
635
+ * Pages don't overlap. With the default `lastCommentedAt` sort, a reply
636
+ * between pages can move a discussion, so it may repeat or be skipped. For
637
+ * a stable walk, use `sortBy: "createdAt"` and `sortDirection: "asc"`.
638
+ */
639
+ list(params: DiscussionListParams): PagePromise<Discussion>;
640
+ /** Get one discussion, including its first 10 comments. A discussion you cannot view is 404. */
641
+ get(discussionId: string): Promise<Discussion>;
642
+ /**
643
+ * List every comment on a discussion, oldest first.
644
+ * `discussion.comments.pagination.cursor` is accepted as `cursor`.
645
+ */
646
+ listComments(discussionId: string, params?: DiscussionCommentListParams): PagePromise<DiscussionComment>;
647
+ /**
648
+ * Start a discussion on an asset version. `assetVersionId` is required.
649
+ * Mention someone with `{{mention:N}}` and a `mentions` entry at that index.
650
+ * On a document or PDF, every annotation needs a `pageNumber`.
651
+ *
652
+ * The body has no board. In a workspace that scopes comments to boards, a
653
+ * discussion with no board needs `asset.canManageDiscussions` at the
654
+ * workspace level, so a board guest gets 403 even when they can comment in
655
+ * their board. A timeout can create a duplicate: list before retrying.
656
+ */
657
+ create(params: DiscussionCreateParams): Promise<Discussion>;
658
+ /** Add a comment. The body and mention rules match `create`. */
659
+ createComment(discussionId: string, params: DiscussionCommentCreateParams): Promise<DiscussionComment>;
660
+ /**
661
+ * Resolve or reopen a discussion. The response is empty, including when the
662
+ * discussion was already in the requested state.
663
+ */
664
+ update(discussionId: string, params: DiscussionUpdateParams): Promise<void>;
665
+ /**
666
+ * Replace a comment's text and mentions. Only the author can edit.
667
+ * The response is empty, and the edit notifies no one. An edit that leaves
668
+ * the text and mentions as they are changes nothing and keeps `updatedAt`.
669
+ * Omitting `mentions`, or sending `null`, when the comment has them is 409.
670
+ * `[]` removes them.
671
+ */
672
+ updateComment(discussionId: string, commentId: string, params: DiscussionCommentUpdateParams): Promise<void>;
673
+ /**
674
+ * Delete a comment. Only the author can delete. The response is empty.
675
+ * Deleting the last comment deletes the discussion.
676
+ */
677
+ deleteComment(discussionId: string, commentId: string): Promise<void>;
678
+ }
679
+
460
680
  interface ImportCreateParams {
461
681
  sourceUrl: string;
462
682
  fileName?: string;
@@ -533,6 +753,53 @@ declare class Libraries {
533
753
  delete(libraryId: string): Promise<void>;
534
754
  }
535
755
 
756
+ type MemberType = "member" | "guest" | "libraryMember";
757
+ interface MemberListParams extends CursorPageParams {
758
+ /**
759
+ * Defaults to `member`. With `email` and no `type`, every type is searched,
760
+ * so omit it to look up an email across member, guest, and libraryMember.
761
+ */
762
+ type?: MemberType;
763
+ /** Exact email. Cannot be combined with `search`. An unknown email is an empty list. */
764
+ email?: string;
765
+ /** Name or email search, 1 to 100 characters. Cannot be combined with `email`. */
766
+ search?: string;
767
+ }
768
+ interface Member {
769
+ /** Account id. The same id as a comment mention `id` and `accountId`. */
770
+ id: string;
771
+ type: MemberType;
772
+ displayName: string | null;
773
+ firstName: string | null;
774
+ lastName: string | null;
775
+ email: string;
776
+ /**
777
+ * The first time this person joined. A rejoin does not change it.
778
+ *
779
+ * The stored Postgres timestamp text, not ISO 8601 like the other
780
+ * timestamps: for example `2024-03-01 12:00:00.123456+00`. It has up to 6
781
+ * fraction digits with trailing zeros dropped (`12:00:00.12+00`,
782
+ * `12:00:00+00`), and a UTC offset (currently `+00`). Don't parse a fixed
783
+ * width.
784
+ */
785
+ firstJoinedAt: string;
786
+ /** Present when the person has an avatar URL. */
787
+ avatar?: string;
788
+ }
789
+
790
+ declare class Members {
791
+ private client;
792
+ constructor(client: AirBase);
793
+ /**
794
+ * List people in the workspace. Requires `members.read`.
795
+ * `workspace.read` does not grant it.
796
+ *
797
+ * Sort is fixed: `firstJoinedAt` ascending, then `id`.
798
+ * `email` without `type` searches every type. An unknown email is an empty list.
799
+ */
800
+ list(params?: MemberListParams): PagePromise<Member>;
801
+ }
802
+
536
803
  interface Role {
537
804
  id: string;
538
805
  name: string;
@@ -866,6 +1133,8 @@ declare class AirApi extends AirBase {
866
1133
  readonly libraries: Libraries;
867
1134
  readonly tags: Tags;
868
1135
  readonly customFields: CustomFields;
1136
+ readonly discussions: Discussions;
1137
+ readonly members: Members;
869
1138
  readonly roles: Roles;
870
1139
  readonly imports: Imports;
871
1140
  readonly uploads: Uploads;
@@ -873,4 +1142,4 @@ declare class AirApi extends AirBase {
873
1142
  constructor(options?: AirApiOptions);
874
1143
  }
875
1144
 
876
- export { type AddBoardAssetsParams, type AddGuestParams, type AddShowcaseAssetsParams, type AddShowcaseBoardsParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCdnLinkCreateParams, type AssetCdnLinkListResponse, type AssetCdnLinkUpdateParams, type AssetCustomFieldDateFilter, type AssetCustomFieldDateOperator, type AssetCustomFieldFilter, type AssetCustomFieldSelectFilter, type AssetCustomFieldTextFilter, type AssetCustomFieldTextOperator, type AssetCustomFieldValue, type AssetListParams, type AssetShareLink, type AssetShareLinkCreateParams, type AssetShareLinkListParams, type AssetShareLinkUpdateParams, type AssetShareLinkWriteSettings, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardShareLink, type BoardShareLinkCreateParams, type BoardShareLinkListResponse, type BoardShareLinkUpdateParams, type BoardUpdateParams, Boards, type CdnLink, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, Libraries, type Library, type LibraryCreateParams, type LibraryListParams, type LibraryUpdateParams, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type ShareLink, type ShareLinkCommentsAccess, type ShareLinkCustomFieldsAccess, type ShareLinkWriteSettings, type Showcase, type ShowcaseCreateParams, type ShowcaseListParams, type ShowcaseShareLink, type ShowcaseShareLinkStatus, type ShowcaseShareLinkUpdateParams, type ShowcaseStats, type ShowcaseUpdateParams, Showcases, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads, type Workspace, type WorkspaceListResponse, Workspaces };
1145
+ export { type AddBoardAssetsParams, type AddGuestParams, type AddShowcaseAssetsParams, type AddShowcaseBoardsParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCdnLinkCreateParams, type AssetCdnLinkListResponse, type AssetCdnLinkUpdateParams, type AssetCustomFieldDateFilter, type AssetCustomFieldDateOperator, type AssetCustomFieldFilter, type AssetCustomFieldSelectFilter, type AssetCustomFieldTextFilter, type AssetCustomFieldTextOperator, type AssetCustomFieldValue, type AssetListParams, type AssetShareLink, type AssetShareLinkCreateParams, type AssetShareLinkListParams, type AssetShareLinkUpdateParams, type AssetShareLinkWriteSettings, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardShareLink, type BoardShareLinkCreateParams, type BoardShareLinkListResponse, type BoardShareLinkUpdateParams, type BoardUpdateParams, Boards, type BoxAnnotation, type CdnLink, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type Discussion, type DiscussionAnnotation, type DiscussionAuthor, type DiscussionComment, type DiscussionCommentCreateParams, type DiscussionCommentListParams, type DiscussionCommentPage, type DiscussionCommentUpdateParams, type DiscussionCreateParams, type DiscussionListOptions, type DiscussionListParams, type DiscussionMention, type DiscussionMentionInput, type DiscussionUpdateParams, Discussions, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, Libraries, type Library, type LibraryCreateParams, type LibraryListParams, type LibraryUpdateParams, type Member, type MemberListParams, type MemberType, Members, type PencilAnnotation, type PencilLine, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type ShareLink, type ShareLinkCommentsAccess, type ShareLinkCustomFieldsAccess, type ShareLinkWriteSettings, type Showcase, type ShowcaseCreateParams, type ShowcaseListParams, type ShowcaseShareLink, type ShowcaseShareLinkStatus, type ShowcaseShareLinkUpdateParams, type ShowcaseStats, type ShowcaseUpdateParams, Showcases, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads, type Workspace, type WorkspaceListResponse, Workspaces };
package/dist/index.d.ts CHANGED
@@ -457,6 +457,226 @@ declare class CustomFields {
457
457
  deleteValue(customFieldId: string, valueId: string): Promise<void>;
458
458
  }
459
459
 
460
+ /**
461
+ * Exactly one of `assetId` or `boardId`. `assetVersionId` requires `assetId`.
462
+ * The server rejects any other combination, so the type does too.
463
+ */
464
+ type DiscussionListParams = DiscussionListOptions & ({
465
+ /** Discussions on this asset. */
466
+ assetId: string;
467
+ /** Limit the asset list to this version. */
468
+ assetVersionId?: string;
469
+ boardId?: never;
470
+ } | {
471
+ /** Discussions on assets currently on this board. */
472
+ boardId: string;
473
+ assetId?: never;
474
+ assetVersionId?: never;
475
+ });
476
+ interface DiscussionListOptions extends CursorPageParams {
477
+ /** When set, only discussions in that resolved state. */
478
+ resolved?: boolean;
479
+ /**
480
+ * `lastCommentedAt` is the default and moves when someone replies.
481
+ * `createdAt` is the first comment and stays put.
482
+ */
483
+ sortBy?: "lastCommentedAt" | "createdAt";
484
+ /** `desc` is the default. */
485
+ sortDirection?: "asc" | "desc";
486
+ }
487
+ interface DiscussionCommentListParams extends CursorPageParams {
488
+ }
489
+ interface Discussion {
490
+ id: string;
491
+ resolved: boolean;
492
+ /** When the first comment was created. */
493
+ createdAt: string | null;
494
+ /** When the latest comment was created. A reply moves this. */
495
+ lastCommentedAt: string | null;
496
+ asset: {
497
+ id: string;
498
+ };
499
+ assetVersion: {
500
+ /** Asset version id. This is `assetVersionId` on create. */
501
+ id: string;
502
+ version: number;
503
+ };
504
+ /**
505
+ * Present only when the stored board is active and the caller can view it.
506
+ * Otherwise the field is omitted.
507
+ */
508
+ boardId?: string;
509
+ annotations: DiscussionAnnotation[];
510
+ /** The first 10 comments, oldest first. */
511
+ comments: DiscussionCommentPage;
512
+ }
513
+ interface DiscussionCommentPage {
514
+ data: DiscussionComment[];
515
+ pagination: {
516
+ hasMore: boolean;
517
+ cursor: string | null;
518
+ };
519
+ total: number;
520
+ }
521
+ interface DiscussionComment {
522
+ id: string;
523
+ discussionId: string;
524
+ /** Plain text with mentions rendered as `@Display Name`. */
525
+ body: string;
526
+ createdAt: string;
527
+ /**
528
+ * Equal to `createdAt` until the first edit that changes the stored text.
529
+ * An edit is `updatedAt !== createdAt`.
530
+ */
531
+ updatedAt: string;
532
+ author: DiscussionAuthor;
533
+ mentions: DiscussionMention[];
534
+ }
535
+ type DiscussionAuthor = {
536
+ type: "workspace_account";
537
+ /** Account id. The same id as `members.list` `id`. */
538
+ id: string;
539
+ displayName: string | null;
540
+ } | {
541
+ type: "anonymous";
542
+ displayName: string | null;
543
+ };
544
+ /** A mention on a comment. `id` is the account id. */
545
+ interface DiscussionMention {
546
+ id: string;
547
+ displayName: string | null;
548
+ }
549
+ /** A mention sent on create or edit. `accountId` is `DiscussionMention.id`. */
550
+ interface DiscussionMentionInput {
551
+ accountId: string;
552
+ }
553
+ type DiscussionAnnotation = BoxAnnotation | PencilAnnotation;
554
+ interface BoxAnnotation {
555
+ type: "box";
556
+ /** Seconds into a video. Omit for a still image. */
557
+ timestamp?: number;
558
+ /** Requires `timestamp`, and must be greater than or equal to it. */
559
+ endTimestamp?: number;
560
+ /** Top-left corner as fractions of the frame, from 0 to 1. */
561
+ coordinates: {
562
+ x: number;
563
+ y: number;
564
+ };
565
+ /** Width and height as fractions of the frame. The box must fit in the frame. */
566
+ dimensions: {
567
+ width: number;
568
+ height: number;
569
+ };
570
+ /** `#RRGGBB`, either case, on write. A stored annotation read back may use another color format. */
571
+ color: string;
572
+ /** Document page, from 1. Required on a document or PDF. Omit for an image or video. */
573
+ pageNumber?: number;
574
+ }
575
+ interface PencilAnnotation {
576
+ type: "pencil";
577
+ /** Seconds into a video. Omit for a still image. */
578
+ timestamp?: number;
579
+ /** Requires `timestamp`, and must be greater than or equal to it. */
580
+ endTimestamp?: number;
581
+ /** 1 to 10 lines. */
582
+ lines: PencilLine[];
583
+ }
584
+ interface PencilLine {
585
+ /** 2 to 1000 points, each a fraction of the frame from 0 to 1. */
586
+ coordinates: {
587
+ x: number;
588
+ y: number;
589
+ }[];
590
+ /** Greater than 0 and at most 1000. */
591
+ lineWidth: number;
592
+ /** `#RRGGBB`, either case, on write. A stored annotation read back may use another color format. */
593
+ color: string;
594
+ /** Document page, from 1. Required on a document or PDF. Omit for an image or video. */
595
+ pageNumber?: number;
596
+ }
597
+ interface DiscussionCreateParams {
598
+ assetId: string;
599
+ /** Required. There is no default to the current version. */
600
+ assetVersionId: string;
601
+ /** Plain text, 1 to 500 characters. Mention someone with `{{mention:N}}`. */
602
+ body: string;
603
+ /** At most 10. `null` is the same as omitting it. */
604
+ mentions?: DiscussionMentionInput[] | null;
605
+ /** At most 10. */
606
+ annotations?: DiscussionAnnotation[];
607
+ }
608
+ interface DiscussionCommentCreateParams {
609
+ /** Plain text, 1 to 500 characters. Mention someone with `{{mention:N}}`. */
610
+ body: string;
611
+ /** At most 10. `null` is the same as omitting it. */
612
+ mentions?: DiscussionMentionInput[] | null;
613
+ }
614
+ interface DiscussionCommentUpdateParams {
615
+ body: string;
616
+ /**
617
+ * Required when the stored comment has mentions. Send the mentions again to
618
+ * keep them, or `[]` to remove them. Omitting this field, or sending `null`,
619
+ * on a comment that has mentions is 409.
620
+ */
621
+ mentions?: DiscussionMentionInput[] | null;
622
+ }
623
+ interface DiscussionUpdateParams {
624
+ /** `true` resolves the discussion. `false` reopens it. */
625
+ resolved: boolean;
626
+ }
627
+
628
+ declare class Discussions {
629
+ private client;
630
+ constructor(client: AirBase);
631
+ /**
632
+ * List discussions on an asset or on the assets currently in a board.
633
+ * Exactly one of `assetId` or `boardId` is required.
634
+ *
635
+ * Pages don't overlap. With the default `lastCommentedAt` sort, a reply
636
+ * between pages can move a discussion, so it may repeat or be skipped. For
637
+ * a stable walk, use `sortBy: "createdAt"` and `sortDirection: "asc"`.
638
+ */
639
+ list(params: DiscussionListParams): PagePromise<Discussion>;
640
+ /** Get one discussion, including its first 10 comments. A discussion you cannot view is 404. */
641
+ get(discussionId: string): Promise<Discussion>;
642
+ /**
643
+ * List every comment on a discussion, oldest first.
644
+ * `discussion.comments.pagination.cursor` is accepted as `cursor`.
645
+ */
646
+ listComments(discussionId: string, params?: DiscussionCommentListParams): PagePromise<DiscussionComment>;
647
+ /**
648
+ * Start a discussion on an asset version. `assetVersionId` is required.
649
+ * Mention someone with `{{mention:N}}` and a `mentions` entry at that index.
650
+ * On a document or PDF, every annotation needs a `pageNumber`.
651
+ *
652
+ * The body has no board. In a workspace that scopes comments to boards, a
653
+ * discussion with no board needs `asset.canManageDiscussions` at the
654
+ * workspace level, so a board guest gets 403 even when they can comment in
655
+ * their board. A timeout can create a duplicate: list before retrying.
656
+ */
657
+ create(params: DiscussionCreateParams): Promise<Discussion>;
658
+ /** Add a comment. The body and mention rules match `create`. */
659
+ createComment(discussionId: string, params: DiscussionCommentCreateParams): Promise<DiscussionComment>;
660
+ /**
661
+ * Resolve or reopen a discussion. The response is empty, including when the
662
+ * discussion was already in the requested state.
663
+ */
664
+ update(discussionId: string, params: DiscussionUpdateParams): Promise<void>;
665
+ /**
666
+ * Replace a comment's text and mentions. Only the author can edit.
667
+ * The response is empty, and the edit notifies no one. An edit that leaves
668
+ * the text and mentions as they are changes nothing and keeps `updatedAt`.
669
+ * Omitting `mentions`, or sending `null`, when the comment has them is 409.
670
+ * `[]` removes them.
671
+ */
672
+ updateComment(discussionId: string, commentId: string, params: DiscussionCommentUpdateParams): Promise<void>;
673
+ /**
674
+ * Delete a comment. Only the author can delete. The response is empty.
675
+ * Deleting the last comment deletes the discussion.
676
+ */
677
+ deleteComment(discussionId: string, commentId: string): Promise<void>;
678
+ }
679
+
460
680
  interface ImportCreateParams {
461
681
  sourceUrl: string;
462
682
  fileName?: string;
@@ -533,6 +753,53 @@ declare class Libraries {
533
753
  delete(libraryId: string): Promise<void>;
534
754
  }
535
755
 
756
+ type MemberType = "member" | "guest" | "libraryMember";
757
+ interface MemberListParams extends CursorPageParams {
758
+ /**
759
+ * Defaults to `member`. With `email` and no `type`, every type is searched,
760
+ * so omit it to look up an email across member, guest, and libraryMember.
761
+ */
762
+ type?: MemberType;
763
+ /** Exact email. Cannot be combined with `search`. An unknown email is an empty list. */
764
+ email?: string;
765
+ /** Name or email search, 1 to 100 characters. Cannot be combined with `email`. */
766
+ search?: string;
767
+ }
768
+ interface Member {
769
+ /** Account id. The same id as a comment mention `id` and `accountId`. */
770
+ id: string;
771
+ type: MemberType;
772
+ displayName: string | null;
773
+ firstName: string | null;
774
+ lastName: string | null;
775
+ email: string;
776
+ /**
777
+ * The first time this person joined. A rejoin does not change it.
778
+ *
779
+ * The stored Postgres timestamp text, not ISO 8601 like the other
780
+ * timestamps: for example `2024-03-01 12:00:00.123456+00`. It has up to 6
781
+ * fraction digits with trailing zeros dropped (`12:00:00.12+00`,
782
+ * `12:00:00+00`), and a UTC offset (currently `+00`). Don't parse a fixed
783
+ * width.
784
+ */
785
+ firstJoinedAt: string;
786
+ /** Present when the person has an avatar URL. */
787
+ avatar?: string;
788
+ }
789
+
790
+ declare class Members {
791
+ private client;
792
+ constructor(client: AirBase);
793
+ /**
794
+ * List people in the workspace. Requires `members.read`.
795
+ * `workspace.read` does not grant it.
796
+ *
797
+ * Sort is fixed: `firstJoinedAt` ascending, then `id`.
798
+ * `email` without `type` searches every type. An unknown email is an empty list.
799
+ */
800
+ list(params?: MemberListParams): PagePromise<Member>;
801
+ }
802
+
536
803
  interface Role {
537
804
  id: string;
538
805
  name: string;
@@ -866,6 +1133,8 @@ declare class AirApi extends AirBase {
866
1133
  readonly libraries: Libraries;
867
1134
  readonly tags: Tags;
868
1135
  readonly customFields: CustomFields;
1136
+ readonly discussions: Discussions;
1137
+ readonly members: Members;
869
1138
  readonly roles: Roles;
870
1139
  readonly imports: Imports;
871
1140
  readonly uploads: Uploads;
@@ -873,4 +1142,4 @@ declare class AirApi extends AirBase {
873
1142
  constructor(options?: AirApiOptions);
874
1143
  }
875
1144
 
876
- export { type AddBoardAssetsParams, type AddGuestParams, type AddShowcaseAssetsParams, type AddShowcaseBoardsParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCdnLinkCreateParams, type AssetCdnLinkListResponse, type AssetCdnLinkUpdateParams, type AssetCustomFieldDateFilter, type AssetCustomFieldDateOperator, type AssetCustomFieldFilter, type AssetCustomFieldSelectFilter, type AssetCustomFieldTextFilter, type AssetCustomFieldTextOperator, type AssetCustomFieldValue, type AssetListParams, type AssetShareLink, type AssetShareLinkCreateParams, type AssetShareLinkListParams, type AssetShareLinkUpdateParams, type AssetShareLinkWriteSettings, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardShareLink, type BoardShareLinkCreateParams, type BoardShareLinkListResponse, type BoardShareLinkUpdateParams, type BoardUpdateParams, Boards, type CdnLink, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, Libraries, type Library, type LibraryCreateParams, type LibraryListParams, type LibraryUpdateParams, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type ShareLink, type ShareLinkCommentsAccess, type ShareLinkCustomFieldsAccess, type ShareLinkWriteSettings, type Showcase, type ShowcaseCreateParams, type ShowcaseListParams, type ShowcaseShareLink, type ShowcaseShareLinkStatus, type ShowcaseShareLinkUpdateParams, type ShowcaseStats, type ShowcaseUpdateParams, Showcases, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads, type Workspace, type WorkspaceListResponse, Workspaces };
1145
+ export { type AddBoardAssetsParams, type AddGuestParams, type AddShowcaseAssetsParams, type AddShowcaseBoardsParams, type AddVersionTagParams, AirApi, type AirApiOptions, type Asset, type AssetBoardListParams, type AssetCdnLinkCreateParams, type AssetCdnLinkListResponse, type AssetCdnLinkUpdateParams, type AssetCustomFieldDateFilter, type AssetCustomFieldDateOperator, type AssetCustomFieldFilter, type AssetCustomFieldSelectFilter, type AssetCustomFieldTextFilter, type AssetCustomFieldTextOperator, type AssetCustomFieldValue, type AssetListParams, type AssetShareLink, type AssetShareLinkCreateParams, type AssetShareLinkListParams, type AssetShareLinkUpdateParams, type AssetShareLinkWriteSettings, type AssetVersion, type AssetVersionDownloadUrl, type AssetVersionListResponse, type AssetVersionUpdateParams, type AssetVersionUrls, Assets, type Board, type BoardCreateParams, type BoardListParams, type BoardShareLink, type BoardShareLinkCreateParams, type BoardShareLinkListResponse, type BoardShareLinkUpdateParams, type BoardUpdateParams, Boards, type BoxAnnotation, type CdnLink, type CompleteMultipartParams, type CustomField, type CustomFieldCreateParams, type CustomFieldListParams, type CustomFieldType, type CustomFieldUpdateParams, type CustomFieldValue, type CustomFieldValueCreateParams, type CustomFieldValueUpdateParams, CustomFields, type Discussion, type DiscussionAnnotation, type DiscussionAuthor, type DiscussionComment, type DiscussionCommentCreateParams, type DiscussionCommentListParams, type DiscussionCommentPage, type DiscussionCommentUpdateParams, type DiscussionCreateParams, type DiscussionListOptions, type DiscussionListParams, type DiscussionMention, type DiscussionMentionInput, type DiscussionUpdateParams, Discussions, type FileMeta, type FileSource, type GetPartUploadUrlParams, type GetPartUploadUrlResponse, type Guest, type GuestListParams, type GuestListResponse, type ImportCreateParams, type ImportCreateResponse, type ImportStatus, type ImportStatusResponse, Imports, type LargeUploadResponse, Libraries, type Library, type LibraryCreateParams, type LibraryListParams, type LibraryUpdateParams, type Member, type MemberListParams, type MemberType, Members, type PencilAnnotation, type PencilLine, type Role, type RoleListParams, type RoleListResponse, Roles, type SetBoardCustomFieldParams, type SetCustomFieldParams, type ShareLink, type ShareLinkCommentsAccess, type ShareLinkCustomFieldsAccess, type ShareLinkWriteSettings, type Showcase, type ShowcaseCreateParams, type ShowcaseListParams, type ShowcaseShareLink, type ShowcaseShareLinkStatus, type ShowcaseShareLinkUpdateParams, type ShowcaseStats, type ShowcaseUpdateParams, Showcases, type SmallUploadResponse, type SmartTag, type Tag, type TagCreateParams, type TagListParams, type TagUpdateParams, Tags, type UpdateGuestParams, type UploadCreateParams, type UploadCreateResponse, type UploadFileOptions, type UploadFileParams, type UploadFileResponse, Uploads, type Workspace, type WorkspaceListResponse, Workspaces };
package/dist/index.js CHANGED
@@ -356,6 +356,118 @@ var CustomFields = class {
356
356
  }
357
357
  };
358
358
 
359
+ // src/resources/discussions.ts
360
+ var Discussions = class {
361
+ constructor(client) {
362
+ this.client = client;
363
+ }
364
+ /**
365
+ * List discussions on an asset or on the assets currently in a board.
366
+ * Exactly one of `assetId` or `boardId` is required.
367
+ *
368
+ * Pages don't overlap. With the default `lastCommentedAt` sort, a reply
369
+ * between pages can move a discussion, so it may repeat or be skipped. For
370
+ * a stable walk, use `sortBy: "createdAt"` and `sortDirection: "asc"`.
371
+ */
372
+ list(params) {
373
+ const query = {
374
+ assetId: params.assetId,
375
+ assetVersionId: params.assetVersionId,
376
+ boardId: params.boardId,
377
+ resolved: params.resolved,
378
+ sortBy: params.sortBy,
379
+ sortDirection: params.sortDirection,
380
+ limit: params.limit,
381
+ cursor: params.cursor
382
+ };
383
+ return this.client.requestCursorPage(
384
+ { method: "GET", path: "/discussions", query },
385
+ query
386
+ );
387
+ }
388
+ /** Get one discussion, including its first 10 comments. A discussion you cannot view is 404. */
389
+ async get(discussionId) {
390
+ return this.client.request({
391
+ method: "GET",
392
+ path: `/discussions/${discussionId}`
393
+ });
394
+ }
395
+ /**
396
+ * List every comment on a discussion, oldest first.
397
+ * `discussion.comments.pagination.cursor` is accepted as `cursor`.
398
+ */
399
+ listComments(discussionId, params = {}) {
400
+ const query = {
401
+ limit: params.limit,
402
+ cursor: params.cursor
403
+ };
404
+ return this.client.requestCursorPage(
405
+ { method: "GET", path: `/discussions/${discussionId}/comments`, query },
406
+ query
407
+ );
408
+ }
409
+ /**
410
+ * Start a discussion on an asset version. `assetVersionId` is required.
411
+ * Mention someone with `{{mention:N}}` and a `mentions` entry at that index.
412
+ * On a document or PDF, every annotation needs a `pageNumber`.
413
+ *
414
+ * The body has no board. In a workspace that scopes comments to boards, a
415
+ * discussion with no board needs `asset.canManageDiscussions` at the
416
+ * workspace level, so a board guest gets 403 even when they can comment in
417
+ * their board. A timeout can create a duplicate: list before retrying.
418
+ */
419
+ async create(params) {
420
+ return this.client.request({
421
+ method: "POST",
422
+ path: "/discussions",
423
+ body: params
424
+ });
425
+ }
426
+ /** Add a comment. The body and mention rules match `create`. */
427
+ async createComment(discussionId, params) {
428
+ return this.client.request({
429
+ method: "POST",
430
+ path: `/discussions/${discussionId}/comments`,
431
+ body: params
432
+ });
433
+ }
434
+ /**
435
+ * Resolve or reopen a discussion. The response is empty, including when the
436
+ * discussion was already in the requested state.
437
+ */
438
+ async update(discussionId, params) {
439
+ return this.client.request({
440
+ method: "PATCH",
441
+ path: `/discussions/${discussionId}`,
442
+ body: params
443
+ });
444
+ }
445
+ /**
446
+ * Replace a comment's text and mentions. Only the author can edit.
447
+ * The response is empty, and the edit notifies no one. An edit that leaves
448
+ * the text and mentions as they are changes nothing and keeps `updatedAt`.
449
+ * Omitting `mentions`, or sending `null`, when the comment has them is 409.
450
+ * `[]` removes them.
451
+ */
452
+ async updateComment(discussionId, commentId, params) {
453
+ return this.client.request({
454
+ method: "PATCH",
455
+ path: `/discussions/${discussionId}/comments/${commentId}`,
456
+ body: params
457
+ });
458
+ }
459
+ /**
460
+ * Delete a comment. Only the author can delete. The response is empty.
461
+ * Deleting the last comment deletes the discussion.
462
+ */
463
+ async deleteComment(discussionId, commentId) {
464
+ return this.client.request({
465
+ method: "DELETE",
466
+ path: `/discussions/${discussionId}/comments/${commentId}`
467
+ });
468
+ }
469
+ };
470
+
359
471
  // src/resources/imports.ts
360
472
  var Imports = class {
361
473
  constructor(client) {
@@ -420,6 +532,30 @@ var Libraries = class {
420
532
  }
421
533
  };
422
534
 
535
+ // src/resources/members.ts
536
+ var Members = class {
537
+ constructor(client) {
538
+ this.client = client;
539
+ }
540
+ /**
541
+ * List people in the workspace. Requires `members.read`.
542
+ * `workspace.read` does not grant it.
543
+ *
544
+ * Sort is fixed: `firstJoinedAt` ascending, then `id`.
545
+ * `email` without `type` searches every type. An unknown email is an empty list.
546
+ */
547
+ list(params = {}) {
548
+ const query = {
549
+ type: params.type,
550
+ email: params.email,
551
+ search: params.search,
552
+ limit: params.limit,
553
+ cursor: params.cursor
554
+ };
555
+ return this.client.requestCursorPage({ method: "GET", path: "/members", query }, query);
556
+ }
557
+ };
558
+
423
559
  // src/resources/roles.ts
424
560
  var Roles = class {
425
561
  constructor(client) {
@@ -859,6 +995,8 @@ var AirApi = class extends AirBase {
859
995
  libraries;
860
996
  tags;
861
997
  customFields;
998
+ discussions;
999
+ members;
862
1000
  roles;
863
1001
  imports;
864
1002
  uploads;
@@ -871,6 +1009,8 @@ var AirApi = class extends AirBase {
871
1009
  this.libraries = new Libraries(this);
872
1010
  this.tags = new Tags(this);
873
1011
  this.customFields = new CustomFields(this);
1012
+ this.discussions = new Discussions(this);
1013
+ this.members = new Members(this);
874
1014
  this.roles = new Roles(this);
875
1015
  this.imports = new Imports(this);
876
1016
  this.uploads = new Uploads(this);
@@ -908,9 +1048,11 @@ export {
908
1048
  ConnectionError,
909
1049
  CursorPage,
910
1050
  CustomFields,
1051
+ Discussions,
911
1052
  Imports,
912
1053
  InternalServerError,
913
1054
  Libraries,
1055
+ Members,
914
1056
  NotFoundError,
915
1057
  PagePromise,
916
1058
  PermissionError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@air/api-rest",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "description": "Typed REST client for Air API",
6
6
  "main": "./dist/index.cjs",
@@ -29,7 +29,7 @@
29
29
  "clean": "rm -rf dist .tsc-out tsconfig.tsbuildinfo"
30
30
  },
31
31
  "dependencies": {
32
- "@air/api-core": "0.10.0"
32
+ "@air/api-core": "0.11.0"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=18"