Skip to content

Commit 8137d5b

Browse files
committed
chore: add e2e test package
1 parent 7fc4fc3 commit 8137d5b

23 files changed

Lines changed: 2759 additions & 81 deletions

packages/admin/src/client.ts

Lines changed: 122 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
11
import type {
22
ReplaneAdminOptions,
3+
Workspace,
4+
ListWorkspacesResponse,
5+
GetWorkspaceRequest,
6+
CreateWorkspaceRequest,
7+
CreateWorkspaceResponse,
8+
DeleteWorkspaceRequest,
39
Project,
4-
ProjectListResponse,
10+
ListProjectsResponse,
11+
GetProjectRequest,
512
CreateProjectRequest,
613
CreateProjectResponse,
714
UpdateProjectRequest,
815
UpdateProjectResponse,
16+
DeleteProjectRequest,
917
Config,
10-
ConfigListResponse,
18+
ListConfigsRequest,
19+
ListConfigsResponse,
20+
GetConfigRequest,
1121
CreateConfigRequest,
1222
CreateConfigResponse,
1323
UpdateConfigRequest,
1424
UpdateConfigResponse,
15-
EnvironmentListResponse,
16-
SdkKeyListResponse,
25+
DeleteConfigRequest,
26+
ListEnvironmentsRequest,
27+
ListEnvironmentsResponse,
28+
ListSdkKeysRequest,
29+
ListSdkKeysResponse,
1730
SdkKeyWithToken,
1831
CreateSdkKeyRequest,
19-
MemberListResponse,
32+
DeleteSdkKeyRequest,
33+
ListMembersRequest,
34+
ListMembersResponse,
2035
ApiError,
2136
} from "./types.js";
2237
import { DEFAULT_AGENT } from "./version.js";
@@ -54,7 +69,8 @@ export class ReplaneAdminError extends Error {
5469
* const { projects } = await admin.projects.list();
5570
*
5671
* // Create a new config
57-
* const { id } = await admin.configs.create("project-id", {
72+
* const { id } = await admin.configs.create({
73+
* projectId: "project-id",
5874
* name: "my-config",
5975
* description: "My config",
6076
* editors: [],
@@ -70,6 +86,7 @@ export class ReplaneAdmin {
7086
private readonly agent: string;
7187
private readonly fetchFn: typeof fetch;
7288

89+
public readonly workspaces: WorkspacesApi;
7390
public readonly projects: ProjectsApi;
7491
public readonly configs: ConfigsApi;
7592
public readonly environments: EnvironmentsApi;
@@ -82,6 +99,7 @@ export class ReplaneAdmin {
8299
this.agent = options.agent ?? DEFAULT_AGENT;
83100
this.fetchFn = options.fetchFn ?? globalThis.fetch;
84101

102+
this.workspaces = new WorkspacesApi(this);
85103
this.projects = new ProjectsApi(this);
86104
this.configs = new ConfigsApi(this);
87105
this.environments = new EnvironmentsApi(this);
@@ -122,11 +140,15 @@ export class ReplaneAdmin {
122140
} catch {
123141
// Ignore JSON parse errors
124142
}
125-
throw new ReplaneAdminError(
126-
errorResponse?.error ?? `Request failed with status ${response.status}`,
127-
response.status,
128-
errorResponse
129-
);
143+
// Handle both string and object error messages
144+
let errorMessage = `Request failed with status ${response.status}`;
145+
if (errorResponse?.error) {
146+
errorMessage =
147+
typeof errorResponse.error === "string"
148+
? errorResponse.error
149+
: JSON.stringify(errorResponse.error);
150+
}
151+
throw new ReplaneAdminError(errorMessage, response.status, errorResponse);
130152
}
131153

132154
// Handle 204 No Content
@@ -138,6 +160,42 @@ export class ReplaneAdmin {
138160
}
139161
}
140162

163+
/**
164+
* Workspaces API
165+
* Note: Most workspace operations require superuser access
166+
*/
167+
class WorkspacesApi {
168+
constructor(private readonly client: ReplaneAdmin) {}
169+
170+
/**
171+
* List all workspaces (requires superuser access)
172+
*/
173+
async list(): Promise<ListWorkspacesResponse> {
174+
return this.client.request<ListWorkspacesResponse>("GET", "/workspaces");
175+
}
176+
177+
/**
178+
* Get a workspace by ID (requires superuser access)
179+
*/
180+
async get(request: GetWorkspaceRequest): Promise<Workspace> {
181+
return this.client.request<Workspace>("GET", `/workspaces/${request.workspaceId}`);
182+
}
183+
184+
/**
185+
* Create a new workspace (requires superuser access)
186+
*/
187+
async create(request: CreateWorkspaceRequest): Promise<CreateWorkspaceResponse> {
188+
return this.client.request<CreateWorkspaceResponse>("POST", "/workspaces", request);
189+
}
190+
191+
/**
192+
* Delete a workspace (requires superuser access)
193+
*/
194+
async delete(request: DeleteWorkspaceRequest): Promise<void> {
195+
return this.client.request<void>("DELETE", `/workspaces/${request.workspaceId}`);
196+
}
197+
}
198+
141199
/**
142200
* Projects API
143201
*/
@@ -147,36 +205,42 @@ class ProjectsApi {
147205
/**
148206
* List all projects
149207
*/
150-
async list(): Promise<ProjectListResponse> {
151-
return this.client.request<ProjectListResponse>("GET", "/projects");
208+
async list(): Promise<ListProjectsResponse> {
209+
return this.client.request<ListProjectsResponse>("GET", "/projects");
152210
}
153211

154212
/**
155213
* Get a project by ID
156214
*/
157-
async get(projectId: string): Promise<Project> {
158-
return this.client.request<Project>("GET", `/projects/${projectId}`);
215+
async get(request: GetProjectRequest): Promise<Project> {
216+
return this.client.request<Project>("GET", `/projects/${request.projectId}`);
159217
}
160218

161219
/**
162-
* Create a new project
220+
* Create a new project in a workspace
163221
*/
164-
async create(data: CreateProjectRequest): Promise<CreateProjectResponse> {
165-
return this.client.request<CreateProjectResponse>("POST", "/projects", data);
222+
async create(request: CreateProjectRequest): Promise<CreateProjectResponse> {
223+
const { workspaceId, ...body } = request;
224+
return this.client.request<CreateProjectResponse>(
225+
"POST",
226+
`/workspaces/${workspaceId}/projects`,
227+
body
228+
);
166229
}
167230

168231
/**
169232
* Update a project
170233
*/
171-
async update(projectId: string, data: UpdateProjectRequest): Promise<UpdateProjectResponse> {
172-
return this.client.request<UpdateProjectResponse>("PATCH", `/projects/${projectId}`, data);
234+
async update(request: UpdateProjectRequest): Promise<UpdateProjectResponse> {
235+
const { projectId, ...body } = request;
236+
return this.client.request<UpdateProjectResponse>("PATCH", `/projects/${projectId}`, body);
173237
}
174238

175239
/**
176240
* Delete a project
177241
*/
178-
async delete(projectId: string): Promise<void> {
179-
return this.client.request<void>("DELETE", `/projects/${projectId}`);
242+
async delete(request: DeleteProjectRequest): Promise<void> {
243+
return this.client.request<void>("DELETE", `/projects/${request.projectId}`);
180244
}
181245
}
182246

@@ -189,53 +253,54 @@ class ConfigsApi {
189253
/**
190254
* List all configs in a project
191255
*/
192-
async list(projectId: string): Promise<ConfigListResponse> {
193-
return this.client.request<ConfigListResponse>("GET", `/projects/${projectId}/configs`);
256+
async list(request: ListConfigsRequest): Promise<ListConfigsResponse> {
257+
return this.client.request<ListConfigsResponse>(
258+
"GET",
259+
`/projects/${request.projectId}/configs`
260+
);
194261
}
195262

196263
/**
197264
* Get a config by name
198265
*/
199-
async get(projectId: string, configName: string): Promise<Config> {
266+
async get(request: GetConfigRequest): Promise<Config> {
200267
return this.client.request<Config>(
201268
"GET",
202-
`/projects/${projectId}/configs/${encodeURIComponent(configName)}`
269+
`/projects/${request.projectId}/configs/${encodeURIComponent(request.configName)}`
203270
);
204271
}
205272

206273
/**
207274
* Create a new config
208275
*/
209-
async create(projectId: string, data: CreateConfigRequest): Promise<CreateConfigResponse> {
276+
async create(request: CreateConfigRequest): Promise<CreateConfigResponse> {
277+
const { projectId, ...body } = request;
210278
return this.client.request<CreateConfigResponse>(
211279
"POST",
212280
`/projects/${projectId}/configs`,
213-
data
281+
body
214282
);
215283
}
216284

217285
/**
218286
* Update a config
219287
*/
220-
async update(
221-
projectId: string,
222-
configName: string,
223-
data: UpdateConfigRequest
224-
): Promise<UpdateConfigResponse> {
288+
async update(request: UpdateConfigRequest): Promise<UpdateConfigResponse> {
289+
const { projectId, configName, ...body } = request;
225290
return this.client.request<UpdateConfigResponse>(
226291
"PUT",
227292
`/projects/${projectId}/configs/${encodeURIComponent(configName)}`,
228-
data
293+
body
229294
);
230295
}
231296

232297
/**
233298
* Delete a config
234299
*/
235-
async delete(projectId: string, configName: string): Promise<void> {
300+
async delete(request: DeleteConfigRequest): Promise<void> {
236301
return this.client.request<void>(
237302
"DELETE",
238-
`/projects/${projectId}/configs/${encodeURIComponent(configName)}`
303+
`/projects/${request.projectId}/configs/${encodeURIComponent(request.configName)}`
239304
);
240305
}
241306
}
@@ -249,10 +314,10 @@ class EnvironmentsApi {
249314
/**
250315
* List all environments in a project
251316
*/
252-
async list(projectId: string): Promise<EnvironmentListResponse> {
253-
return this.client.request<EnvironmentListResponse>(
317+
async list(request: ListEnvironmentsRequest): Promise<ListEnvironmentsResponse> {
318+
return this.client.request<ListEnvironmentsResponse>(
254319
"GET",
255-
`/projects/${projectId}/environments`
320+
`/projects/${request.projectId}/environments`
256321
);
257322
}
258323
}
@@ -266,23 +331,30 @@ class SdkKeysApi {
266331
/**
267332
* List all SDK keys in a project
268333
*/
269-
async list(projectId: string): Promise<SdkKeyListResponse> {
270-
return this.client.request<SdkKeyListResponse>("GET", `/projects/${projectId}/sdk-keys`);
334+
async list(request: ListSdkKeysRequest): Promise<ListSdkKeysResponse> {
335+
return this.client.request<ListSdkKeysResponse>(
336+
"GET",
337+
`/projects/${request.projectId}/sdk-keys`
338+
);
271339
}
272340

273341
/**
274342
* Create a new SDK key
275343
* Note: The returned key is only shown once and cannot be retrieved again
276344
*/
277-
async create(projectId: string, data: CreateSdkKeyRequest): Promise<SdkKeyWithToken> {
278-
return this.client.request<SdkKeyWithToken>("POST", `/projects/${projectId}/sdk-keys`, data);
345+
async create(request: CreateSdkKeyRequest): Promise<SdkKeyWithToken> {
346+
const { projectId, ...body } = request;
347+
return this.client.request<SdkKeyWithToken>("POST", `/projects/${projectId}/sdk-keys`, body);
279348
}
280349

281350
/**
282351
* Delete an SDK key
283352
*/
284-
async delete(projectId: string, sdkKeyId: string): Promise<void> {
285-
return this.client.request<void>("DELETE", `/projects/${projectId}/sdk-keys/${sdkKeyId}`);
353+
async delete(request: DeleteSdkKeyRequest): Promise<void> {
354+
return this.client.request<void>(
355+
"DELETE",
356+
`/projects/${request.projectId}/sdk-keys/${request.sdkKeyId}`
357+
);
286358
}
287359
}
288360

@@ -295,7 +367,10 @@ class MembersApi {
295367
/**
296368
* List all members in a project
297369
*/
298-
async list(projectId: string): Promise<MemberListResponse> {
299-
return this.client.request<MemberListResponse>("GET", `/projects/${projectId}/members`);
370+
async list(request: ListMembersRequest): Promise<ListMembersResponse> {
371+
return this.client.request<ListMembersResponse>(
372+
"GET",
373+
`/projects/${request.projectId}/members`
374+
);
300375
}
301376
}

0 commit comments

Comments
 (0)