@37signals/basecamp 0.16.0 → 0.17.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.
@@ -1901,6 +1901,41 @@ export interface paths {
1901
1901
  patch?: never;
1902
1902
  trace?: never;
1903
1903
  };
1904
+ "/projects/{projectId}/client_enablement.json": {
1905
+ parameters: {
1906
+ query?: never;
1907
+ header?: never;
1908
+ path?: never;
1909
+ cookie?: never;
1910
+ };
1911
+ get?: never;
1912
+ put?: never;
1913
+ /**
1914
+ * @description Enable clients on a project so client users can be added to it
1915
+ *
1916
+ * A deliberate step separate from adding clients: it turns on the project's
1917
+ * client-facing surface and applies the default client visibility (the
1918
+ * timeline and most docked tools become client-visible; the card table,
1919
+ * Campfire, and Doors stay private). UpdateProjectClientAccess never enables
1920
+ * clients implicitly — enable first, then add. 403 unless the project can have
1921
+ * clients (the account supports clients and the project is a standard
1922
+ * project). Naturally idempotent: enabling an enabled project re-answers
1923
+ * `{"clients_enabled": true}`.
1924
+ */
1925
+ post: operations["EnableProjectClients"];
1926
+ /**
1927
+ * @description Disable clients on a project
1928
+ *
1929
+ * 403 while the project still has any client users — revoke them first with
1930
+ * UpdateProjectClientAccess. Naturally idempotent: disabling a project with
1931
+ * clients already off re-answers `{"clients_enabled": false}`.
1932
+ */
1933
+ delete: operations["DisableProjectClients"];
1934
+ options?: never;
1935
+ head?: never;
1936
+ patch?: never;
1937
+ trace?: never;
1938
+ };
1904
1939
  "/projects/{projectId}/gauge.json": {
1905
1940
  parameters: {
1906
1941
  query?: never;
@@ -1958,6 +1993,46 @@ export interface paths {
1958
1993
  patch?: never;
1959
1994
  trace?: never;
1960
1995
  };
1996
+ "/projects/{projectId}/people/client_users.json": {
1997
+ parameters: {
1998
+ query?: never;
1999
+ header?: never;
2000
+ path?: never;
2001
+ cookie?: never;
2002
+ };
2003
+ get?: never;
2004
+ /**
2005
+ * @description Update project client access (grant/revoke/create client users)
2006
+ *
2007
+ * The client-side counterpart to UpdateProjectAccess: `grant` adds existing
2008
+ * client users by id, `revoke` removes client users, and `create` invites
2009
+ * brand-new clients by email (`name` optional, defaulting to the address).
2010
+ * Only client users are eligible — a `grant` id belonging to a team member is
2011
+ * rejected (omitted from `granted`) rather than cross-graded, and `revoke` never removes a team
2012
+ * member. The response mirrors UpdateProjectAccess: `granted` and `revoked`
2013
+ * people, each with `client: true`.
2014
+ *
2015
+ * Requires clients to be enabled on the project (EnableProjectClients);
2016
+ * otherwise 403. Invitations are all-or-nothing: an invalid `create` row
2017
+ * (including one with no email address) answers 422 with the rejected
2018
+ * addresses and nobody is invited; new addresses that would exceed the
2019
+ * account's user limit answer 429 and nobody is invited. Addresses already on
2020
+ * the account take no seat and a repeated address counts once.
2021
+ *
2022
+ * The seat-limit 429 is a verdict, not throttling: it carries no Retry-After
2023
+ * and re-asking cannot change the answer, so this operation declares
2024
+ * `retryOn: [503]` and a 429 surfaces on the first attempt (status-mapped to
2025
+ * `rate_limit`, since the wire status is the only signal). Every other
2026
+ * operation retries on 429.
2027
+ */
2028
+ put: operations["UpdateProjectClientAccess"];
2029
+ post?: never;
2030
+ delete?: never;
2031
+ options?: never;
2032
+ head?: never;
2033
+ patch?: never;
2034
+ trace?: never;
2035
+ };
1961
2036
  "/projects/{projectId}/people/users.json": {
1962
2037
  parameters: {
1963
2038
  query?: never;
@@ -3969,6 +4044,23 @@ export interface components {
3969
4044
  replies_count?: number;
3970
4045
  replies_url?: string;
3971
4046
  };
4047
+ /**
4048
+ * @description One rejected `create` row: the address as submitted and the validation
4049
+ * messages for it. Always emitted; `null` when the row carried no address (the
4050
+ * row is still rejected, with a "can't be blank" message). `@required` models
4051
+ * the presence and the nullability is layered on in the OpenAPI
4052
+ * (smithy-build.json jsonAdd -> type: ["string","null"]), the Wormhole.color
4053
+ * treatment.
4054
+ */
4055
+ ClientInvitationError: {
4056
+ email_address: string | null;
4057
+ messages: string[];
4058
+ };
4059
+ /** @description The per-row 422 body: {"errors": [{"email_address": ..., "messages": [...]}]}. */
4060
+ ClientInvitationErrors: {
4061
+ errors: components["schemas"]["ClientInvitationError"][];
4062
+ };
4063
+ ClientInvitationValidationErrorResponseContent: components["schemas"]["ClientInvitationErrors"];
3972
4064
  ClientReply: {
3973
4065
  /** Format: int64 */
3974
4066
  id: number;
@@ -4131,6 +4223,20 @@ export interface components {
4131
4223
  command_url?: string;
4132
4224
  };
4133
4225
  CreateChatbotResponseContent: components["schemas"]["Chatbot"];
4226
+ /**
4227
+ * @description A new client to invite. Unlike CreatePersonRequest, only the address is
4228
+ * required: bc3 defaults `name` to the email address when omitted.
4229
+ */
4230
+ CreateClientRequest: {
4231
+ /** Format: password */
4232
+ email_address: string;
4233
+ /** Format: password */
4234
+ name?: string;
4235
+ /** Format: password */
4236
+ title?: string;
4237
+ /** Format: password */
4238
+ company_name?: string;
4239
+ };
4134
4240
  CreateCloudFileRequestContent: {
4135
4241
  url: string;
4136
4242
  /**
@@ -4439,6 +4545,7 @@ export interface components {
4439
4545
  };
4440
4546
  CreateWormholeResponseContent: components["schemas"]["Wormhole"];
4441
4547
  DisableCardColumnOnHoldResponseContent: components["schemas"]["CardColumn"];
4548
+ DisableProjectClientsResponseContent: components["schemas"]["ProjectClientEnablement"];
4442
4549
  DockItem: {
4443
4550
  /** Format: int64 */
4444
4551
  id: number;
@@ -4537,6 +4644,7 @@ export interface components {
4537
4644
  out_of_office: components["schemas"]["OutOfOfficePayload"];
4538
4645
  };
4539
4646
  EnableOutOfOfficeResponseContent: components["schemas"]["OutOfOffice"];
4647
+ EnableProjectClientsResponseContent: components["schemas"]["ProjectClientEnablement"];
4540
4648
  Event: {
4541
4649
  /** Format: int64 */
4542
4650
  id: number;
@@ -5501,6 +5609,10 @@ export interface components {
5501
5609
  granted?: components["schemas"]["Person"][];
5502
5610
  revoked?: components["schemas"]["Person"][];
5503
5611
  };
5612
+ /** @description The project's client-enablement state after a toggle. */
5613
+ ProjectClientEnablement: {
5614
+ clients_enabled: boolean;
5615
+ };
5504
5616
  ProjectConstruction: {
5505
5617
  /** Format: int64 */
5506
5618
  id: number;
@@ -7171,6 +7283,15 @@ export interface components {
7171
7283
  create?: components["schemas"]["CreatePersonRequest"][];
7172
7284
  };
7173
7285
  UpdateProjectAccessResponseContent: components["schemas"]["ProjectAccessResult"];
7286
+ UpdateProjectClientAccessRequestContent: {
7287
+ /** @description Existing client people IDs to add to the project. */
7288
+ grant?: number[];
7289
+ /** @description Client people IDs to remove from the project. */
7290
+ revoke?: number[];
7291
+ /** @description New clients to invite by email. */
7292
+ create?: components["schemas"]["CreateClientRequest"][];
7293
+ };
7294
+ UpdateProjectClientAccessResponseContent: components["schemas"]["ProjectAccessResult"];
7174
7295
  UpdateProjectRequestContent: {
7175
7296
  name: string;
7176
7297
  description?: string;
@@ -16005,6 +16126,140 @@ export interface operations {
16005
16126
  };
16006
16127
  };
16007
16128
  };
16129
+ EnableProjectClients: {
16130
+ parameters: {
16131
+ query?: never;
16132
+ header?: never;
16133
+ path: {
16134
+ projectId: number;
16135
+ };
16136
+ cookie?: never;
16137
+ };
16138
+ requestBody?: never;
16139
+ responses: {
16140
+ /** @description EnableProjectClients 200 response */
16141
+ 200: {
16142
+ headers: {
16143
+ [name: string]: unknown;
16144
+ };
16145
+ content: {
16146
+ "application/json": components["schemas"]["EnableProjectClientsResponseContent"];
16147
+ };
16148
+ };
16149
+ /** @description UnauthorizedError 401 response */
16150
+ 401: {
16151
+ headers: {
16152
+ [name: string]: unknown;
16153
+ };
16154
+ content: {
16155
+ "application/json": components["schemas"]["UnauthorizedErrorResponseContent"];
16156
+ };
16157
+ };
16158
+ /** @description ForbiddenError 403 response */
16159
+ 403: {
16160
+ headers: {
16161
+ [name: string]: unknown;
16162
+ };
16163
+ content: {
16164
+ "application/json": components["schemas"]["ForbiddenErrorResponseContent"];
16165
+ };
16166
+ };
16167
+ /** @description NotFoundError 404 response */
16168
+ 404: {
16169
+ headers: {
16170
+ [name: string]: unknown;
16171
+ };
16172
+ content: {
16173
+ "application/json": components["schemas"]["NotFoundErrorResponseContent"];
16174
+ };
16175
+ };
16176
+ /** @description RateLimitError 429 response */
16177
+ 429: {
16178
+ headers: {
16179
+ [name: string]: unknown;
16180
+ };
16181
+ content: {
16182
+ "application/json": components["schemas"]["RateLimitErrorResponseContent"];
16183
+ };
16184
+ };
16185
+ /** @description InternalServerError 500 response */
16186
+ 500: {
16187
+ headers: {
16188
+ [name: string]: unknown;
16189
+ };
16190
+ content: {
16191
+ "application/json": components["schemas"]["InternalServerErrorResponseContent"];
16192
+ };
16193
+ };
16194
+ };
16195
+ };
16196
+ DisableProjectClients: {
16197
+ parameters: {
16198
+ query?: never;
16199
+ header?: never;
16200
+ path: {
16201
+ projectId: number;
16202
+ };
16203
+ cookie?: never;
16204
+ };
16205
+ requestBody?: never;
16206
+ responses: {
16207
+ /** @description DisableProjectClients 200 response */
16208
+ 200: {
16209
+ headers: {
16210
+ [name: string]: unknown;
16211
+ };
16212
+ content: {
16213
+ "application/json": components["schemas"]["DisableProjectClientsResponseContent"];
16214
+ };
16215
+ };
16216
+ /** @description UnauthorizedError 401 response */
16217
+ 401: {
16218
+ headers: {
16219
+ [name: string]: unknown;
16220
+ };
16221
+ content: {
16222
+ "application/json": components["schemas"]["UnauthorizedErrorResponseContent"];
16223
+ };
16224
+ };
16225
+ /** @description ForbiddenError 403 response */
16226
+ 403: {
16227
+ headers: {
16228
+ [name: string]: unknown;
16229
+ };
16230
+ content: {
16231
+ "application/json": components["schemas"]["ForbiddenErrorResponseContent"];
16232
+ };
16233
+ };
16234
+ /** @description NotFoundError 404 response */
16235
+ 404: {
16236
+ headers: {
16237
+ [name: string]: unknown;
16238
+ };
16239
+ content: {
16240
+ "application/json": components["schemas"]["NotFoundErrorResponseContent"];
16241
+ };
16242
+ };
16243
+ /** @description RateLimitError 429 response */
16244
+ 429: {
16245
+ headers: {
16246
+ [name: string]: unknown;
16247
+ };
16248
+ content: {
16249
+ "application/json": components["schemas"]["RateLimitErrorResponseContent"];
16250
+ };
16251
+ };
16252
+ /** @description InternalServerError 500 response */
16253
+ 500: {
16254
+ headers: {
16255
+ [name: string]: unknown;
16256
+ };
16257
+ content: {
16258
+ "application/json": components["schemas"]["InternalServerErrorResponseContent"];
16259
+ };
16260
+ };
16261
+ };
16262
+ };
16008
16263
  ToggleGauge: {
16009
16264
  parameters: {
16010
16265
  query?: never;
@@ -16267,6 +16522,86 @@ export interface operations {
16267
16522
  };
16268
16523
  };
16269
16524
  };
16525
+ UpdateProjectClientAccess: {
16526
+ parameters: {
16527
+ query?: never;
16528
+ header?: never;
16529
+ path: {
16530
+ projectId: number;
16531
+ };
16532
+ cookie?: never;
16533
+ };
16534
+ requestBody?: {
16535
+ content: {
16536
+ "application/json": components["schemas"]["UpdateProjectClientAccessRequestContent"];
16537
+ };
16538
+ };
16539
+ responses: {
16540
+ /** @description UpdateProjectClientAccess 200 response */
16541
+ 200: {
16542
+ headers: {
16543
+ [name: string]: unknown;
16544
+ };
16545
+ content: {
16546
+ "application/json": components["schemas"]["UpdateProjectClientAccessResponseContent"];
16547
+ };
16548
+ };
16549
+ /** @description UnauthorizedError 401 response */
16550
+ 401: {
16551
+ headers: {
16552
+ [name: string]: unknown;
16553
+ };
16554
+ content: {
16555
+ "application/json": components["schemas"]["UnauthorizedErrorResponseContent"];
16556
+ };
16557
+ };
16558
+ /** @description ForbiddenError 403 response */
16559
+ 403: {
16560
+ headers: {
16561
+ [name: string]: unknown;
16562
+ };
16563
+ content: {
16564
+ "application/json": components["schemas"]["ForbiddenErrorResponseContent"];
16565
+ };
16566
+ };
16567
+ /** @description NotFoundError 404 response */
16568
+ 404: {
16569
+ headers: {
16570
+ [name: string]: unknown;
16571
+ };
16572
+ content: {
16573
+ "application/json": components["schemas"]["NotFoundErrorResponseContent"];
16574
+ };
16575
+ };
16576
+ /** @description ClientInvitationValidationError 422 response */
16577
+ 422: {
16578
+ headers: {
16579
+ [name: string]: unknown;
16580
+ };
16581
+ content: {
16582
+ "application/json": components["schemas"]["ClientInvitationValidationErrorResponseContent"];
16583
+ };
16584
+ };
16585
+ /** @description RateLimitError 429 response */
16586
+ 429: {
16587
+ headers: {
16588
+ [name: string]: unknown;
16589
+ };
16590
+ content: {
16591
+ "application/json": components["schemas"]["RateLimitErrorResponseContent"];
16592
+ };
16593
+ };
16594
+ /** @description InternalServerError 500 response */
16595
+ 500: {
16596
+ headers: {
16597
+ [name: string]: unknown;
16598
+ };
16599
+ content: {
16600
+ "application/json": components["schemas"]["InternalServerErrorResponseContent"];
16601
+ };
16602
+ };
16603
+ };
16604
+ };
16270
16605
  UpdateProjectAccess: {
16271
16606
  parameters: {
16272
16607
  query?: never;
@@ -77,6 +77,18 @@ export interface ListForProjectPeopleOptions extends PaginationOptions {
77
77
  page?: number;
78
78
  }
79
79
 
80
+ /**
81
+ * Request parameters for updateProjectClientAccess.
82
+ */
83
+ export interface UpdateProjectClientAccessPeopleRequest {
84
+ /** Existing client people IDs to add to the project. */
85
+ grant?: number[];
86
+ /** Client people IDs to remove from the project. */
87
+ revoke?: number[];
88
+ /** New clients to invite by email. */
89
+ create?: components["schemas"]["CreateClientRequest"][];
90
+ }
91
+
80
92
  /**
81
93
  * Request parameters for updateProjectAccess.
82
94
  */
@@ -395,6 +407,66 @@ export class PeopleService extends BaseService {
395
407
  );
396
408
  }
397
409
 
410
+ /**
411
+ * Enable clients on a project so client users can be added to it
412
+ * @param projectId - The project ID
413
+ * @returns The project
414
+ * @throws {BasecampError} If the request fails
415
+ *
416
+ * @example
417
+ * ```ts
418
+ * const result = await client.people.enableProjectClients(123);
419
+ * ```
420
+ */
421
+ async enableProjectClients(projectId: number): Promise<components["schemas"]["EnableProjectClientsResponseContent"]> {
422
+ const response = await this.request(
423
+ {
424
+ service: "People",
425
+ operation: "EnableProjectClients",
426
+ resourceType: "project",
427
+ isMutation: true,
428
+ projectId,
429
+ },
430
+ () =>
431
+ this.client.POST("/projects/{projectId}/client_enablement.json", {
432
+ params: {
433
+ path: { projectId },
434
+ },
435
+ })
436
+ );
437
+ return response;
438
+ }
439
+
440
+ /**
441
+ * Disable clients on a project
442
+ * @param projectId - The project ID
443
+ * @returns The project
444
+ * @throws {BasecampError} If the request fails
445
+ *
446
+ * @example
447
+ * ```ts
448
+ * const result = await client.people.disableProjectClients(123);
449
+ * ```
450
+ */
451
+ async disableProjectClients(projectId: number): Promise<components["schemas"]["DisableProjectClientsResponseContent"]> {
452
+ const response = await this.request(
453
+ {
454
+ service: "People",
455
+ operation: "DisableProjectClients",
456
+ resourceType: "project",
457
+ isMutation: true,
458
+ projectId,
459
+ },
460
+ () =>
461
+ this.client.DELETE("/projects/{projectId}/client_enablement.json", {
462
+ params: {
463
+ path: { projectId },
464
+ },
465
+ })
466
+ );
467
+ return response;
468
+ }
469
+
398
470
  /**
399
471
  * List all active people on a project
400
472
  * @param projectId - The project ID
@@ -429,6 +501,42 @@ export class PeopleService extends BaseService {
429
501
  );
430
502
  }
431
503
 
504
+ /**
505
+ * Update project client access (grant/revoke/create client users)
506
+ * @param projectId - The project ID
507
+ * @param req - Project_access update parameters
508
+ * @returns The project_access
509
+ * @throws {BasecampError} If the resource is not found or fields are invalid
510
+ *
511
+ * @example
512
+ * ```ts
513
+ * const result = await client.people.updateProjectClientAccess(123, { });
514
+ * ```
515
+ */
516
+ async updateProjectClientAccess(projectId: number, req: UpdateProjectClientAccessPeopleRequest): Promise<components["schemas"]["UpdateProjectClientAccessResponseContent"]> {
517
+ const response = await this.request(
518
+ {
519
+ service: "People",
520
+ operation: "UpdateProjectClientAccess",
521
+ resourceType: "project_access",
522
+ isMutation: true,
523
+ projectId,
524
+ },
525
+ () =>
526
+ this.client.PUT("/projects/{projectId}/people/client_users.json", {
527
+ params: {
528
+ path: { projectId },
529
+ },
530
+ body: {
531
+ grant: req.grant,
532
+ revoke: req.revoke,
533
+ create: req.create,
534
+ },
535
+ })
536
+ );
537
+ return response;
538
+ }
539
+
432
540
  /**
433
541
  * Update project access (grant/revoke/create people)
434
542
  * @param projectId - The project ID