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
15 changes: 15 additions & 0 deletions .changeset/client-remove-env-member-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@objectstack/client": patch
---

chore(client): remove dead `projects.*` env-member SDK methods (cloud#533 / ADR-0024 D9)

Removes `projects.listMembers` / `addMember` / `updateMemberRole` / `removeMember`,
which called `GET/POST/PATCH/DELETE /api/v1/cloud/environments/:id/members`. Those
control-plane endpoints were deleted in cloud#533 (retiring `sys_environment_member`),
so the methods returned 404. Org membership/invites now flow through the better-auth
`organization` plugin (`organization.inviteMember` / `listMembers` / …); objectui
already uses `organization.*` and no in-repo callers remained.

The `membership` field on the `projects.get()` response is unchanged — cloud#533 still
returns it on the single-env GET (re-sourced to the caller's org `sys_member` role).
58 changes: 0 additions & 58 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -879,64 +879,6 @@ export class ObjectStackClient {
return this.unwrapResponse<{ project: any }>(res);
},

/**
* List members of a project (per-project RBAC).
*/
listMembers: async (id: string) => {
const res = await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(id)}/members`);
return this.unwrapResponse<{ members: any[] }>(res);
},

/**
* Invite a member to a project. Caller must be `owner` or `admin`.
* Pass either `email` (resolved against the user table) or `user_id`.
* Returns `{ member, alreadyMember }` — `alreadyMember=true` means the
* row already existed; the call is idempotent.
*/
addMember: async (
id: string,
payload: { email?: string; user_id?: string; role?: 'owner' | 'admin' | 'member' | 'viewer' },
) => {
const res = await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(id)}/members`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(payload),
});
return this.unwrapResponse<{ member: any; alreadyMember: boolean }>(res);
},

/**
* Update a member's role. Caller must be `owner` or `admin`. Demoting
* the last `owner` returns 409.
*/
updateMemberRole: async (
id: string,
memberId: string,
role: 'owner' | 'admin' | 'member' | 'viewer',
) => {
const res = await this.fetch(
`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(id)}/members/${encodeURIComponent(memberId)}`,
{
method: 'PATCH',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ role }),
},
);
return this.unwrapResponse<{ member: any }>(res);
},

/**
* Remove a member. Owners/admins may remove anyone; non-privileged
* users may only remove themselves. Removing the last `owner` returns 409.
*/
removeMember: async (id: string, memberId: string) => {
const res = await this.fetch(
`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(id)}/members/${encodeURIComponent(memberId)}`,
{ method: 'DELETE' },
);
return this.unwrapResponse<{ removed: boolean; memberId: string }>(res);
},

/**
* List ObjectQL drivers registered on the server. Useful for populating a
* driver selector when provisioning a new project (memory / turso /
Expand Down