@meshagent/meshagent 0.44.13 → 0.45.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/browser/index.d.ts +1 -1
  3. package/dist/browser/index.js +1 -1
  4. package/dist/browser/meshagent-client.d.ts +390 -372
  5. package/dist/browser/meshagent-client.js +841 -1040
  6. package/dist/browser/oauth-scopes.d.ts +1 -1
  7. package/dist/browser/oauth-scopes.js +64 -14
  8. package/dist/browser/participant-token.d.ts +68 -20
  9. package/dist/browser/participant-token.js +232 -61
  10. package/dist/browser/room-client.d.ts +4 -8
  11. package/dist/browser/room-client.js +4 -10
  12. package/dist/browser/services-client.d.ts +11 -0
  13. package/dist/browser/services-client.js +17 -0
  14. package/dist/browser/sqlite-client.d.ts +326 -0
  15. package/dist/browser/sqlite-client.js +630 -0
  16. package/dist/browser/toolkit-config.d.ts +7 -1
  17. package/dist/browser/toolkit-config.js +41 -22
  18. package/dist/esm/index.d.ts +1 -1
  19. package/dist/esm/index.js +1 -1
  20. package/dist/esm/meshagent-client.d.ts +390 -372
  21. package/dist/esm/meshagent-client.js +841 -1038
  22. package/dist/esm/oauth-scopes.d.ts +1 -1
  23. package/dist/esm/oauth-scopes.js +64 -14
  24. package/dist/esm/participant-token.d.ts +68 -20
  25. package/dist/esm/participant-token.js +228 -59
  26. package/dist/esm/room-client.d.ts +4 -8
  27. package/dist/esm/room-client.js +4 -10
  28. package/dist/esm/services-client.d.ts +11 -0
  29. package/dist/esm/services-client.js +17 -0
  30. package/dist/esm/sqlite-client.d.ts +326 -0
  31. package/dist/esm/sqlite-client.js +625 -0
  32. package/dist/esm/toolkit-config.d.ts +7 -1
  33. package/dist/esm/toolkit-config.js +41 -22
  34. package/dist/node/index.d.ts +1 -1
  35. package/dist/node/index.js +1 -1
  36. package/dist/node/meshagent-client.d.ts +390 -372
  37. package/dist/node/meshagent-client.js +841 -1040
  38. package/dist/node/oauth-scopes.d.ts +1 -1
  39. package/dist/node/oauth-scopes.js +64 -14
  40. package/dist/node/participant-token.d.ts +68 -20
  41. package/dist/node/participant-token.js +232 -61
  42. package/dist/node/room-client.d.ts +4 -8
  43. package/dist/node/room-client.js +4 -10
  44. package/dist/node/services-client.d.ts +11 -0
  45. package/dist/node/services-client.js +17 -0
  46. package/dist/node/sqlite-client.d.ts +326 -0
  47. package/dist/node/sqlite-client.js +630 -0
  48. package/dist/node/toolkit-config.d.ts +7 -1
  49. package/dist/node/toolkit-config.js +41 -22
  50. package/package.json +1 -1
  51. package/dist/browser/secrets-client.d.ts +0 -112
  52. package/dist/browser/secrets-client.js +0 -300
  53. package/dist/esm/secrets-client.d.ts +0 -112
  54. package/dist/esm/secrets-client.js +0 -296
  55. package/dist/node/secrets-client.d.ts +0 -112
  56. package/dist/node/secrets-client.js +0 -300
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Meshagent = exports.ManagedAgentGrant = exports.ServiceTemplateSpec = exports.RoomSession = void 0;
4
- exports.normalizeServiceSpec = normalizeServiceSpec;
3
+ exports.Meshagent = exports.ServiceTemplateSpec = exports.RoomSession = void 0;
5
4
  const helpers_js_1 = require("./helpers.js");
6
5
  const requirement_js_1 = require("./requirement.js");
7
- const participant_token_js_1 = require("./participant-token.js");
8
- const utils_js_1 = require("./utils.js");
9
6
  class RoomSession {
10
7
  constructor({ id, roomId, roomName, createdAt, isActive, participants, kind = "room", agentId, agentName, }) {
11
8
  this.id = id;
@@ -32,226 +29,75 @@ class RoomSession {
32
29
  }
33
30
  }
34
31
  exports.RoomSession = RoomSession;
35
- function cloneJsonValue(value) {
36
- if (Array.isArray(value)) {
37
- return value.map((item) => cloneJsonValue(item));
38
- }
39
- if (value != null && typeof value === "object") {
40
- const result = {};
41
- for (const [key, item] of Object.entries(value)) {
42
- result[key] = cloneJsonValue(item);
43
- }
44
- return result;
45
- }
46
- return value;
47
- }
48
- function formatTemplateString(value, values) {
49
- return value.replace(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (token, key) => values[key] ?? token);
50
- }
51
- function formatJsonValue(value, values) {
32
+ function applyTemplateValues(value, values) {
52
33
  if (typeof value === "string") {
53
- return formatTemplateString(value, values);
34
+ return Object.entries(values).reduce((current, [key, replacement]) => current.split(`{${key}}`).join(replacement), value);
54
35
  }
55
36
  if (Array.isArray(value)) {
56
- return value.map((item) => formatJsonValue(item, values));
37
+ return value.map((item) => applyTemplateValues(item, values));
57
38
  }
58
- if (value != null && typeof value === "object") {
39
+ if (value !== null && typeof value === "object") {
59
40
  const result = {};
60
- for (const [key, item] of Object.entries(value)) {
61
- result[key] = formatJsonValue(item, values);
41
+ for (const [key, entry] of Object.entries(value)) {
42
+ result[key] = applyTemplateValues(entry, values);
62
43
  }
63
44
  return result;
64
45
  }
65
46
  return value;
66
47
  }
67
- function objectOrUndefined(value) {
68
- return value != null && typeof value === "object" && !Array.isArray(value)
69
- ? value
70
- : undefined;
71
- }
72
- function objectArray(value) {
73
- return Array.isArray(value)
74
- ? value.filter((item) => objectOrUndefined(item) !== undefined)
75
- : undefined;
76
- }
77
- function stringValue(value) {
78
- return typeof value === "string" ? value : undefined;
79
- }
80
- function booleanValue(value) {
81
- return typeof value === "boolean" ? value : undefined;
82
- }
83
- function normalizeRoomMount(value) {
84
- return {
85
- path: stringValue(value.path) ?? "",
86
- ...(stringValue(value.subpath) !== undefined ? { subpath: stringValue(value.subpath) } : {}),
87
- ...(booleanValue(value.read_only) !== undefined ? { read_only: booleanValue(value.read_only) } : {}),
88
- };
89
- }
90
- function normalizeProjectMount(value) {
91
- return {
92
- path: stringValue(value.path) ?? "",
93
- ...(stringValue(value.subpath) !== undefined ? { subpath: stringValue(value.subpath) } : {}),
94
- read_only: booleanValue(value.read_only) ?? true,
95
- };
96
- }
97
- function normalizeImageMount(value) {
98
- return {
99
- path: stringValue(value.path) ?? "",
100
- ...(stringValue(value.subpath) !== undefined ? { subpath: stringValue(value.subpath) } : {}),
101
- read_only: booleanValue(value.read_only) ?? true,
102
- image: stringValue(value.image) ?? "",
103
- };
104
- }
105
- function normalizeFileMount(value) {
106
- return {
107
- path: stringValue(value.path) ?? "",
108
- ...(stringValue(value.subpath) !== undefined ? { subpath: stringValue(value.subpath) } : {}),
109
- read_only: booleanValue(value.read_only) ?? true,
110
- text: stringValue(value.text) ?? "",
111
- };
112
- }
113
- function normalizeEmptyDirMount(value) {
114
- return {
115
- path: stringValue(value.path) ?? "",
116
- read_only: booleanValue(value.read_only) ?? false,
117
- };
118
- }
119
- function normalizeConfigMount(value) {
120
- return {
121
- path: stringValue(value.path) ?? "/var/run/meshagent",
122
- };
123
- }
124
- function normalizeContainerMountSpec(value) {
125
- const source = objectOrUndefined(value) ?? {};
126
- const room = objectArray(source.room)?.map(normalizeRoomMount);
127
- const project = objectArray(source.project)?.map(normalizeProjectMount);
128
- const images = objectArray(source.images)?.map(normalizeImageMount);
129
- const files = objectArray(source.files)?.map(normalizeFileMount);
130
- const emptyDirs = objectArray(source.empty_dirs)?.map(normalizeEmptyDirMount);
131
- const configs = objectArray(source.configs)?.map(normalizeConfigMount);
132
- return {
133
- ...(room !== undefined ? { room } : {}),
134
- ...(project !== undefined ? { project } : {}),
135
- ...(images !== undefined ? { images } : {}),
136
- ...(files !== undefined ? { files } : {}),
137
- ...(emptyDirs !== undefined ? { empty_dirs: emptyDirs } : {}),
138
- ...(configs !== undefined ? { configs } : {}),
139
- };
140
- }
141
- function normalizeAgentSpec(agent, values) {
142
- const formatted = formatJsonValue(agent, values);
143
- const spec = cloneJsonValue(formatted);
144
- if (spec.email != null && spec.email.public == null) {
145
- spec.email = { ...spec.email, public: false };
146
- }
147
- if (spec.channels?.email) {
148
- spec.channels = {
149
- ...spec.channels,
150
- email: spec.channels.email.map((channel) => ({
151
- ...channel,
152
- private: channel.private ?? false,
153
- })),
154
- };
155
- }
156
- if (spec.channels?.messaging) {
157
- spec.channels = {
158
- ...spec.channels,
159
- messaging: spec.channels.messaging.map((channel) => ({
160
- ...channel,
161
- protocol: channel.protocol ?? "meshagent.agent-message.v1",
162
- })),
163
- };
164
- }
165
- return spec;
166
- }
167
48
  function normalizeServiceSpec(service) {
168
- const normalized = cloneJsonValue(service);
169
- if (normalized.container?.storage != null) {
170
- normalized.container = {
171
- ...normalized.container,
172
- storage: normalizeContainerMountSpec(normalized.container.storage),
49
+ const storage = service.container?.storage;
50
+ const agents = service.agents?.map((agent) => ({
51
+ ...agent,
52
+ email: agent.email == null
53
+ ? agent.email
54
+ : {
55
+ ...agent.email,
56
+ public: agent.email.public ?? false,
57
+ },
58
+ channels: agent.channels == null
59
+ ? agent.channels
60
+ : {
61
+ ...agent.channels,
62
+ messaging: agent.channels.messaging?.map((channel) => ({
63
+ ...channel,
64
+ protocol: channel.protocol ?? "meshagent.agent-message.v1",
65
+ })),
66
+ },
67
+ }));
68
+ const container = service.container == null
69
+ ? service.container
70
+ : {
71
+ ...service.container,
72
+ storage: storage == null
73
+ ? storage
74
+ : {
75
+ ...storage,
76
+ configs: storage.configs?.map((config) => ({
77
+ ...config,
78
+ path: config.path ?? "/var/run/meshagent",
79
+ })),
80
+ files: storage.files?.map((file) => ({
81
+ ...file,
82
+ read_only: file.read_only ?? true,
83
+ })),
84
+ },
173
85
  };
174
- }
175
- return normalized;
86
+ return { ...service, agents, container };
176
87
  }
177
88
  class ServiceTemplateSpec {
178
- constructor({ version = "v1", kind = "ServiceTemplate", variables, metadata, ports = [], container, external, agents = [], }) {
179
- this.version = version;
180
- this.kind = kind;
181
- this.variables = variables;
182
- this.metadata = metadata;
183
- this.ports = ports;
184
- this.container = container;
185
- this.external = external;
186
- this.agents = agents;
89
+ constructor(template) {
90
+ this.template = template;
187
91
  }
188
92
  static fromJson(json) {
189
- const metadata = objectOrUndefined(json.metadata);
190
- if (metadata === undefined || typeof metadata.name !== "string") {
191
- throw new requirement_js_1.RoomException("Invalid service template payload: missing metadata.name");
192
- }
193
- return new ServiceTemplateSpec({
194
- version: stringValue(json.version) ?? "v1",
195
- kind: stringValue(json.kind) ?? "ServiceTemplate",
196
- variables: objectArray(json.variables),
197
- metadata: cloneJsonValue(metadata),
198
- ports: (objectArray(json.ports) ?? []),
199
- container: objectOrUndefined(json.container),
200
- external: objectOrUndefined(json.external),
201
- agents: objectArray(json.agents) ?? [],
202
- });
203
- }
204
- toJson() {
205
- return {
206
- version: this.version,
207
- kind: this.kind,
208
- ...(this.variables != null ? { variables: cloneJsonValue(this.variables) } : {}),
209
- metadata: cloneJsonValue(this.metadata),
210
- ...(this.ports.length > 0 ? { ports: cloneJsonValue(this.ports) } : {}),
211
- ...(this.container != null ? { container: cloneJsonValue(this.container) } : {}),
212
- ...(this.external != null ? { external: cloneJsonValue(this.external) } : {}),
213
- ...(this.agents.length > 0 ? { agents: cloneJsonValue(this.agents) } : {}),
214
- };
93
+ return new ServiceTemplateSpec(json);
215
94
  }
216
95
  toServiceSpec({ values = {} } = {}) {
217
- const service = {
218
- version: "v1",
96
+ const templated = applyTemplateValues(this.template, values);
97
+ return normalizeServiceSpec({
98
+ ...templated,
219
99
  kind: "Service",
220
- metadata: cloneJsonValue(this.metadata),
221
- agents: this.agents.map((agent) => normalizeAgentSpec(agent, values)),
222
- ports: cloneJsonValue(this.ports),
223
- };
224
- if (this.container != null) {
225
- const formattedContainer = formatJsonValue(this.container, values);
226
- const image = stringValue(formattedContainer.image);
227
- if (image === undefined || image.length === 0) {
228
- throw new requirement_js_1.RoomException("ServiceTemplateSpec.image is required to build a ServiceSpec");
229
- }
230
- service.container = {
231
- ...(booleanValue(formattedContainer.private) !== undefined ? { private: booleanValue(formattedContainer.private) } : {}),
232
- ...(stringValue(formattedContainer.command) !== undefined ? { command: stringValue(formattedContainer.command) } : {}),
233
- ...(stringValue(formattedContainer.working_dir) !== undefined ? { working_dir: stringValue(formattedContainer.working_dir) } : {}),
234
- image,
235
- ...(Array.isArray(formattedContainer.environment)
236
- ? { environment: formattedContainer.environment }
237
- : {}),
238
- ...(objectOrUndefined(formattedContainer.storage) !== undefined
239
- ? { storage: normalizeContainerMountSpec(formattedContainer.storage) }
240
- : {}),
241
- ...(booleanValue(formattedContainer.on_demand) !== undefined ? { on_demand: booleanValue(formattedContainer.on_demand) } : {}),
242
- ...(booleanValue(formattedContainer.writable_root_fs) !== undefined
243
- ? { writable_root_fs: booleanValue(formattedContainer.writable_root_fs) }
244
- : {}),
245
- };
246
- }
247
- if (this.external != null) {
248
- const formattedExternal = formatJsonValue(this.external, values);
249
- const url = stringValue(formattedExternal.url);
250
- if (url !== undefined) {
251
- service.external = { url };
252
- }
253
- }
254
- return normalizeServiceSpec(service);
100
+ });
255
101
  }
256
102
  }
257
103
  exports.ServiceTemplateSpec = ServiceTemplateSpec;
@@ -277,28 +123,62 @@ function pruneUndefinedValues(value) {
277
123
  }
278
124
  return value;
279
125
  }
280
- function pruneNullishValues(value) {
281
- if (Array.isArray(value)) {
282
- return value
283
- .map((item) => pruneNullishValues(item))
284
- .filter((item) => item !== undefined);
126
+ function validateServiceSpec(service) {
127
+ const container = service.container;
128
+ if (container == null) {
129
+ return;
285
130
  }
286
- if (value === null || value === undefined) {
287
- return undefined;
131
+ if (typeof container.run_as === "string") {
132
+ throw new Error("container.run_as must be an object with an email field");
288
133
  }
289
- if (typeof value === "object") {
290
- const result = {};
291
- for (const [key, entryValue] of Object.entries(value)) {
292
- const normalized = pruneNullishValues(entryValue);
293
- if (normalized !== undefined) {
294
- result[key] = normalized;
295
- }
134
+ const environment = container.environment ?? [];
135
+ const hasSecretEnvironment = environment.some((entry) => entry.secret != null);
136
+ if (hasSecretEnvironment && container.run_as == null) {
137
+ throw new Error("container.run_as is required when using SecretValue");
138
+ }
139
+ for (const entry of environment) {
140
+ const secret = entry.secret;
141
+ if (secret == null) {
142
+ continue;
143
+ }
144
+ const unsupportedFields = Object.keys(secret).filter((key) => key !== "id");
145
+ if (unsupportedFields.length > 0) {
146
+ throw new Error(`unsupported SecretValue fields: ${unsupportedFields.join(", ")}`);
296
147
  }
297
- return result;
298
148
  }
299
- return value;
149
+ const pullSecret = container.pull_secret;
150
+ if (pullSecret != null) {
151
+ const unsupportedFields = Object.keys(pullSecret).filter((key) => key !== "id");
152
+ if (unsupportedFields.length > 0) {
153
+ throw new Error(`unsupported SecretValue fields: ${unsupportedFields.join(", ")}`);
154
+ }
155
+ }
156
+ }
157
+ const defaultServiceRunAsScopes = ["secrets:proxy"];
158
+ function normalizeServiceRunAs(runAs) {
159
+ if (runAs == null) {
160
+ return runAs;
161
+ }
162
+ const email = runAs.email.trim().toLowerCase();
163
+ if (email.length === 0) {
164
+ throw new Error("container.run_as.email is required");
165
+ }
166
+ const scopes = runAs.scopes == null ? defaultServiceRunAsScopes : runAs.scopes;
167
+ const normalizedScopes = [];
168
+ for (const scope of scopes) {
169
+ const normalized = scope.trim();
170
+ if (normalized.length === 0 || normalizedScopes.includes(normalized)) {
171
+ continue;
172
+ }
173
+ normalizedScopes.push(normalized);
174
+ }
175
+ return {
176
+ email,
177
+ scopes: normalizedScopes.length === 0 ? [...defaultServiceRunAsScopes] : normalizedScopes,
178
+ };
300
179
  }
301
180
  function serializeServiceSpec(service) {
181
+ validateServiceSpec(service);
302
182
  const agents = service.agents?.map((agent) => ({
303
183
  ...agent,
304
184
  channels: agent.channels == null
@@ -311,8 +191,15 @@ function serializeServiceSpec(service) {
311
191
  })),
312
192
  },
313
193
  }));
194
+ const container = service.container == null
195
+ ? service.container
196
+ : {
197
+ ...service.container,
198
+ run_as: normalizeServiceRunAs(service.container.run_as),
199
+ };
314
200
  return pruneUndefinedValues({
315
201
  ...service,
202
+ container,
316
203
  agents,
317
204
  });
318
205
  }
@@ -321,46 +208,6 @@ function serializeCreateServiceSpec(service) {
321
208
  delete payload.id;
322
209
  return payload;
323
210
  }
324
- class ManagedAgentGrant {
325
- constructor({ admin = false } = {}) {
326
- this.admin = admin;
327
- }
328
- static fromJson(json) {
329
- return new ManagedAgentGrant({ admin: json["admin"] === true });
330
- }
331
- toJson() {
332
- return { admin: this.admin };
333
- }
334
- }
335
- exports.ManagedAgentGrant = ManagedAgentGrant;
336
- const globalScope = globalThis;
337
- function bytesToBase64(bytes) {
338
- if (globalScope.Buffer) {
339
- return globalScope.Buffer.from(bytes).toString("base64");
340
- }
341
- if (!globalScope.btoa) {
342
- throw new Error("base64 encoding is not available in this runtime");
343
- }
344
- let binary = "";
345
- for (const byte of bytes) {
346
- binary += String.fromCharCode(byte);
347
- }
348
- return globalScope.btoa(binary);
349
- }
350
- function base64ToBytes(base64) {
351
- if (globalScope.Buffer) {
352
- return Uint8Array.from(globalScope.Buffer.from(base64, "base64"));
353
- }
354
- if (!globalScope.atob) {
355
- throw new Error("base64 decoding is not available in this runtime");
356
- }
357
- const binary = globalScope.atob(base64);
358
- const bytes = new Uint8Array(binary.length);
359
- for (let index = 0; index < binary.length; index += 1) {
360
- bytes[index] = binary.charCodeAt(index);
361
- }
362
- return bytes;
363
- }
364
211
  function toFetchBody(body) {
365
212
  if (body == null) {
366
213
  return undefined;
@@ -372,11 +219,16 @@ function toFetchBody(body) {
372
219
  copy.set(body);
373
220
  return copy.buffer;
374
221
  }
375
- function normalizeBinary(data) {
376
- if (data instanceof Uint8Array) {
377
- return data;
222
+ function bytesToBase64(value) {
223
+ const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
224
+ if (typeof Buffer !== "undefined") {
225
+ return Buffer.from(bytes).toString("base64");
378
226
  }
379
- return new Uint8Array(data);
227
+ let binary = "";
228
+ for (const byte of bytes) {
229
+ binary += String.fromCharCode(byte);
230
+ }
231
+ return btoa(binary);
380
232
  }
381
233
  class Meshagent {
382
234
  constructor({ baseUrl, token } = {}) {
@@ -435,11 +287,10 @@ class Meshagent {
435
287
  catch {
436
288
  message = "<unable to read body>";
437
289
  }
438
- const errorMessage = `Failed to ${action}. Status code: ${response.status}, body: ${message}`;
439
290
  if (response.status === 403) {
440
- throw new requirement_js_1.ForbiddenException(errorMessage);
291
+ throw new requirement_js_1.ForbiddenException(`Failed to ${action}. Status code: ${response.status}, body: ${message}`);
441
292
  }
442
- throw new requirement_js_1.RoomException(errorMessage);
293
+ throw new requirement_js_1.RoomException(`Failed to ${action}. Status code: ${response.status}, body: ${message}`);
443
294
  }
444
295
  switch (responseType) {
445
296
  case "json":
@@ -456,22 +307,46 @@ class Meshagent {
456
307
  return undefined;
457
308
  }
458
309
  }
459
- parseRoomShare(data) {
460
- if (!data || typeof data !== "object") {
461
- throw new requirement_js_1.RoomException("Invalid room share payload: expected object");
462
- }
463
- const { id, project_id: projectId, projectId: projectIdAlt, settings } = data;
464
- if (typeof id !== "string") {
465
- throw new requirement_js_1.RoomException("Invalid room share payload: missing id");
466
- }
467
- const finalProjectId = typeof projectIdAlt === "string" ? projectIdAlt : typeof projectId === "string" ? projectId : undefined;
468
- if (!finalProjectId) {
469
- throw new requirement_js_1.RoomException("Invalid room share payload: missing project id");
470
- }
310
+ secretPayload(input) {
311
+ const payload = {};
312
+ if (input.projectId !== undefined)
313
+ payload.project_id = input.projectId;
314
+ if (input.name !== undefined)
315
+ payload.name = input.name;
316
+ if (input.type !== undefined)
317
+ payload.type = input.type;
318
+ if (input.httpOnly !== undefined)
319
+ payload.http_only = input.httpOnly;
320
+ if (input.metadata !== undefined)
321
+ payload.metadata = input.metadata;
322
+ if (input.annotations !== undefined)
323
+ payload.annotations = input.annotations;
324
+ return payload;
325
+ }
326
+ secretSearchPayload(input) {
327
+ const payload = {
328
+ page_size: input.pageSize ?? 100,
329
+ };
330
+ if (input.filter !== undefined)
331
+ payload.filter = input.filter;
332
+ if (input.name !== undefined)
333
+ payload.name = input.name;
334
+ if (input.type !== undefined)
335
+ payload.type = input.type;
336
+ if (input.httpOnly !== undefined)
337
+ payload.http_only = input.httpOnly;
338
+ if (input.metadata !== undefined)
339
+ payload.metadata = input.metadata;
340
+ if (input.annotations !== undefined)
341
+ payload.annotations = input.annotations;
342
+ if (input.continuationToken !== undefined)
343
+ payload.continuation_token = input.continuationToken;
344
+ return payload;
345
+ }
346
+ secretVersionPayload(input) {
471
347
  return {
472
- id,
473
- projectId: finalProjectId,
474
- settings: (settings && typeof settings === "object") ? settings : {},
348
+ value_base64: bytesToBase64(input.value),
349
+ set_current: input.setCurrent ?? true,
475
350
  };
476
351
  }
477
352
  parseRoomSession(data) {
@@ -501,34 +376,33 @@ class Meshagent {
501
376
  createdAt: new Date(created),
502
377
  isActive: isActiveValue,
503
378
  participants: participants && typeof participants === "object" ? participants : undefined,
504
- kind: typeof kind === "string" ? kind : "room",
379
+ kind: typeof kind === "string" ? kind : undefined,
505
380
  agentId: typeof agentId === "string" ? agentId : typeof agentIdRaw === "string" ? agentIdRaw : undefined,
506
381
  agentName: typeof agentName === "string" ? agentName : typeof agentNameRaw === "string" ? agentNameRaw : undefined,
507
382
  });
508
383
  }
509
- parseManagedAgent(data) {
384
+ parseRoom(data) {
510
385
  if (!data || typeof data !== "object") {
511
- throw new requirement_js_1.RoomException("Invalid managed agent payload");
386
+ throw new requirement_js_1.RoomException("Invalid room payload");
512
387
  }
513
- const { id, name, configuration } = data;
388
+ const { id, name, metadata, annotations } = data;
514
389
  if (typeof id !== "string" || typeof name !== "string") {
515
- throw new requirement_js_1.RoomException("Invalid managed agent payload: missing id or name");
390
+ throw new requirement_js_1.RoomException("Invalid room payload: missing id or name");
516
391
  }
517
392
  return {
518
393
  id,
519
394
  name,
520
- configuration: configuration && typeof configuration === "object" && !Array.isArray(configuration)
521
- ? configuration
522
- : {},
395
+ metadata: metadata && typeof metadata === "object" ? metadata : {},
396
+ annotations: annotations && typeof annotations === "object" ? annotations : {},
523
397
  };
524
398
  }
525
- parseRoom(data) {
399
+ parseGroup(data) {
526
400
  if (!data || typeof data !== "object") {
527
- throw new requirement_js_1.RoomException("Invalid room payload");
401
+ throw new requirement_js_1.RoomException("Invalid group payload");
528
402
  }
529
403
  const { id, name, metadata, annotations } = data;
530
404
  if (typeof id !== "string" || typeof name !== "string") {
531
- throw new requirement_js_1.RoomException("Invalid room payload: missing id or name");
405
+ throw new requirement_js_1.RoomException("Invalid group payload: missing id or name");
532
406
  }
533
407
  return {
534
408
  id,
@@ -688,53 +562,170 @@ class Meshagent {
688
562
  createdAt: new Date(createdAtValue),
689
563
  };
690
564
  }
691
- parseProjectRoomGrant(data) {
692
- if (!data || typeof data !== "object") {
693
- throw new requirement_js_1.RoomException("Invalid room grant payload");
694
- }
695
- const roomData = data.room;
696
- const room = this.parseRoom(roomData);
697
- const userId = data.user_id ?? data.userId;
698
- if (typeof userId !== "string") {
699
- throw new requirement_js_1.RoomException("Invalid room grant payload: missing user_id");
565
+ parseAccessResource(resource) {
566
+ if (!resource || typeof resource !== "object" || typeof resource.type !== "string" || typeof resource.id !== "string") {
567
+ throw new requirement_js_1.RoomException("Invalid access resource payload");
700
568
  }
701
- const permissionsRaw = data.permissions;
702
- const permissions = permissionsRaw && typeof permissionsRaw === "object" ? participant_token_js_1.ApiScope.fromJSON(permissionsRaw) : new participant_token_js_1.ApiScope();
703
- return { room, userId, permissions };
569
+ return {
570
+ type: resource.type,
571
+ id: resource.id,
572
+ name: typeof resource.name === "string" ? resource.name : null,
573
+ metadata: resource.metadata && typeof resource.metadata === "object" ? resource.metadata : {},
574
+ annotations: resource.annotations && typeof resource.annotations === "object" ? resource.annotations : {},
575
+ };
704
576
  }
705
- parseProjectRoomGrantCount(data) {
706
- const roomData = (data && typeof data === "object") ? (data.room ?? { id: data.room_id, name: data.room_name, metadata: data.metadata ?? {} }) : undefined;
707
- if (!roomData) {
708
- throw new requirement_js_1.RoomException("Invalid room grant count payload: missing room");
709
- }
710
- const room = this.parseRoom(roomData);
711
- const count = data.count;
712
- if (typeof count !== "number") {
713
- throw new requirement_js_1.RoomException("Invalid room grant count payload: missing count");
577
+ parseAccessSubject(subject) {
578
+ if (!subject || typeof subject !== "object" || typeof subject.type !== "string" || typeof subject.id !== "string") {
579
+ throw new requirement_js_1.RoomException("Invalid access subject payload");
714
580
  }
715
- return { room, count };
581
+ return {
582
+ type: subject.type,
583
+ id: subject.id,
584
+ name: typeof subject.name === "string" ? subject.name : null,
585
+ firstName: typeof subject.first_name === "string" ? subject.first_name : null,
586
+ lastName: typeof subject.last_name === "string" ? subject.last_name : null,
587
+ email: typeof subject.email === "string" ? subject.email : null,
588
+ objectType: typeof subject.object_type === "string" ? subject.object_type : null,
589
+ relation: typeof subject.relation === "string" ? subject.relation : null,
590
+ };
591
+ }
592
+ serializeAccessSubject(subject) {
593
+ return {
594
+ type: subject.type,
595
+ id: subject.id,
596
+ ...(subject.name !== undefined ? { name: subject.name } : {}),
597
+ ...(subject.firstName !== undefined ? { first_name: subject.firstName } : {}),
598
+ ...(subject.lastName !== undefined ? { last_name: subject.lastName } : {}),
599
+ ...(subject.email !== undefined ? { email: subject.email } : {}),
600
+ ...(subject.objectType !== undefined ? { object_type: subject.objectType } : {}),
601
+ ...(subject.relation !== undefined ? { relation: subject.relation } : {}),
602
+ };
716
603
  }
717
- parseProjectUserGrantCount(data) {
604
+ serializeAccessResource(resource) {
605
+ return {
606
+ type: resource.type,
607
+ id: resource.id,
608
+ ...(resource.name !== undefined ? { name: resource.name } : {}),
609
+ ...(resource.metadata !== undefined ? { metadata: resource.metadata } : {}),
610
+ ...(resource.annotations !== undefined ? { annotations: resource.annotations } : {}),
611
+ };
612
+ }
613
+ parseProjectMember(data) {
718
614
  if (!data || typeof data !== "object") {
719
- throw new requirement_js_1.RoomException("Invalid room grant user count payload");
720
- }
721
- const { user_id: userIdRaw, userId, count, first_name: firstNameRaw, firstName, last_name: lastNameRaw, lastName, email } = data;
722
- const userIdValue = typeof userId === "string" ? userId : userIdRaw;
723
- if (typeof userIdValue !== "string") {
724
- throw new requirement_js_1.RoomException("Invalid room grant user count payload: missing user_id");
725
- }
726
- if (typeof count !== "number") {
727
- throw new requirement_js_1.RoomException("Invalid room grant user count payload: missing count");
615
+ throw new requirement_js_1.RoomException("Invalid project member payload");
616
+ }
617
+ const user = data.user && typeof data.user === "object" ? data.user : data;
618
+ const directRoles = Array.isArray(data.direct_roles)
619
+ ? data.direct_roles.filter((item) => item === "member" ||
620
+ item === "admin" ||
621
+ item === "developer" ||
622
+ item === "room_creator" ||
623
+ item === "agent_creator" ||
624
+ item === "mailbox_creator" ||
625
+ item === "route_creator" ||
626
+ item === "scheduled_task_creator" ||
627
+ item === "llm_proxy_user" ||
628
+ item === "usage_reporter" ||
629
+ item === "billing_manager" ||
630
+ item === "group_manager")
631
+ : [];
632
+ const id = typeof user.id === "string" ? user.id : "";
633
+ const email = typeof user.email === "string" ? user.email : "";
634
+ return {
635
+ id,
636
+ email,
637
+ firstName: typeof user.first_name === "string" ? user.first_name : null,
638
+ lastName: typeof user.last_name === "string" ? user.last_name : null,
639
+ directRoles,
640
+ };
641
+ }
642
+ parseGroupMember(data) {
643
+ if (!data || typeof data !== "object") {
644
+ throw new requirement_js_1.RoomException("Invalid group member payload");
728
645
  }
729
- if (typeof email !== "string") {
730
- throw new requirement_js_1.RoomException("Invalid room grant user count payload: missing email");
646
+ const directRoles = Array.isArray(data.direct_roles)
647
+ ? data.direct_roles.filter((item) => item === "member" || item === "manager")
648
+ : [];
649
+ return {
650
+ subject: this.parseAccessSubject(data.subject),
651
+ directRoles,
652
+ };
653
+ }
654
+ parseProjectRoomGrant(data) {
655
+ if (!data || typeof data !== "object") {
656
+ throw new requirement_js_1.RoomException("Invalid room grant payload");
731
657
  }
658
+ const parsedResource = this.parseAccessResource(data.resource);
659
+ const parsedSubject = this.parseAccessSubject(data.subject);
660
+ const parsedDirectRoles = Array.isArray(data.direct_roles)
661
+ ? data.direct_roles.filter((item) => item === "member" ||
662
+ item === "viewer" ||
663
+ item === "operator" ||
664
+ item === "developer" ||
665
+ item === "admin" ||
666
+ item === "room_creator" ||
667
+ item === "room_inventory" ||
668
+ item === "room_manager" ||
669
+ item === "session_inventory" ||
670
+ item === "agent_creator" ||
671
+ item === "agent_inventory" ||
672
+ item === "agent_manager" ||
673
+ item === "repository_creator" ||
674
+ item === "repository_inventory" ||
675
+ item === "repository_manager" ||
676
+ item === "feed_creator" ||
677
+ item === "feed_inventory" ||
678
+ item === "feed_manager" ||
679
+ item === "oauth_client_creator" ||
680
+ item === "oauth_client_inventory" ||
681
+ item === "oauth_client_manager" ||
682
+ item === "api_key_creator" ||
683
+ item === "api_key_inventory" ||
684
+ item === "api_key_manager" ||
685
+ item === "service_creator" ||
686
+ item === "service_inventory" ||
687
+ item === "service_manager" ||
688
+ item === "service_account_creator" ||
689
+ item === "service_account_inventory" ||
690
+ item === "service_account_manager" ||
691
+ item === "participant_token_creator" ||
692
+ item === "mailbox_creator" ||
693
+ item === "mailbox_inventory" ||
694
+ item === "mailbox_manager" ||
695
+ item === "route_creator" ||
696
+ item === "route_inventory" ||
697
+ item === "route_manager" ||
698
+ item === "scheduled_task_creator" ||
699
+ item === "scheduled_task_inventory" ||
700
+ item === "scheduled_task_manager" ||
701
+ item === "feed_subscription_creator" ||
702
+ item === "feed_subscription_inventory" ||
703
+ item === "feed_subscription_manager" ||
704
+ item === "llm_logger_creator" ||
705
+ item === "llm_logger_inventory" ||
706
+ item === "llm_logger_manager" ||
707
+ item === "llm_proxy_user" ||
708
+ item === "usage_reporter" ||
709
+ item === "billing_manager" ||
710
+ item === "group_manager" ||
711
+ item === "reader" ||
712
+ item === "subscriber" ||
713
+ item === "publisher" ||
714
+ item === "manager" ||
715
+ item === "list")
716
+ : [];
717
+ const room = {
718
+ id: parsedResource.id,
719
+ name: parsedResource.name ?? parsedResource.id,
720
+ metadata: parsedResource.metadata ?? {},
721
+ annotations: parsedResource.annotations ?? {},
722
+ };
732
723
  return {
733
- userId: userIdValue,
734
- count,
735
- firstName: typeof firstName === "string" ? firstName : firstNameRaw,
736
- lastName: typeof lastName === "string" ? lastName : lastNameRaw,
737
- email,
724
+ resource: parsedResource,
725
+ subject: parsedSubject,
726
+ directRoles: parsedDirectRoles,
727
+ room,
728
+ userId: parsedSubject.id,
738
729
  };
739
730
  }
740
731
  parseBalance(data) {
@@ -783,196 +774,13 @@ class Meshagent {
783
774
  createdAt: new Date(createdValue),
784
775
  };
785
776
  }
786
- parseSecret(data) {
787
- if (!data || typeof data !== "object") {
788
- throw new requirement_js_1.RoomException("Invalid secret payload");
789
- }
790
- const type = data.type;
791
- if (type === "docker") {
792
- const server = data.server;
793
- const username = data.username;
794
- const password = data.password;
795
- if (typeof server !== "string" || typeof username !== "string" || typeof password !== "string") {
796
- throw new requirement_js_1.RoomException("Invalid docker secret payload");
797
- }
798
- return {
799
- id: typeof data.id === "string" ? data.id : undefined,
800
- name: data.name,
801
- type: "docker",
802
- server,
803
- username,
804
- password,
805
- email: typeof data.email === "string" ? data.email : undefined,
806
- };
807
- }
808
- if (type === "keys") {
809
- const record = data.data;
810
- if (!record || typeof record !== "object") {
811
- throw new requirement_js_1.RoomException("Invalid keys secret payload");
812
- }
813
- return {
814
- id: typeof data.id === "string" ? data.id : undefined,
815
- name: data.name,
816
- type: "keys",
817
- data: record,
818
- };
819
- }
820
- throw new requirement_js_1.RoomException(`Unknown secret type: ${type}`);
821
- }
822
- parseManagedSecretInfo(data) {
823
- if (!data || typeof data !== "object") {
824
- throw new requirement_js_1.RoomException("Invalid managed secret payload");
825
- }
826
- const { id, type, name, delegated_to: delegatedToRaw, delegatedTo } = data;
827
- if (typeof id !== "string" || typeof type !== "string" || typeof name !== "string") {
828
- throw new requirement_js_1.RoomException("Invalid managed secret payload: missing id, type, or name");
829
- }
830
- const delegatedToValue = typeof delegatedTo === "string"
831
- ? delegatedTo
832
- : typeof delegatedToRaw === "string"
833
- ? delegatedToRaw
834
- : null;
835
- return {
836
- id,
837
- type,
838
- name,
839
- delegatedTo: delegatedToValue,
840
- };
841
- }
842
- parseManagedSecret(data) {
843
- const secret = this.parseManagedSecretInfo(data);
844
- const dataBase64 = data.data_base64 ?? data.dataBase64;
845
- if (typeof dataBase64 !== "string") {
846
- throw new requirement_js_1.RoomException("Invalid managed secret payload: missing data_base64");
847
- }
848
- return {
849
- ...secret,
850
- dataBase64,
851
- data: base64ToBytes(dataBase64),
852
- };
853
- }
854
- parseSecretPayload(secret, rawData) {
855
- let payload;
856
- try {
857
- payload = JSON.parse(utils_js_1.decoder.decode(rawData));
858
- }
859
- catch {
860
- throw new requirement_js_1.RoomException(`Invalid secret payload for ${secret.id}`);
861
- }
862
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
863
- throw new requirement_js_1.RoomException(`Invalid secret payload for ${secret.id}`);
864
- }
865
- if (secret.type === "docker") {
866
- const { server, username, password, email } = payload;
867
- if (typeof server !== "string" || typeof username !== "string" || typeof password !== "string") {
868
- throw new requirement_js_1.RoomException(`Invalid secret payload for ${secret.id}`);
869
- }
870
- return {
871
- id: secret.id,
872
- name: secret.name,
873
- type: "docker",
874
- server,
875
- username,
876
- password,
877
- email: typeof email === "string" ? email : "none@example.com",
878
- };
879
- }
880
- const entries = Object.entries(payload);
881
- if (entries.some(([, value]) => typeof value !== "string")) {
882
- throw new requirement_js_1.RoomException(`Invalid secret payload for ${secret.id}`);
883
- }
884
- return {
885
- id: secret.id,
886
- name: secret.name,
887
- type: "keys",
888
- data: Object.fromEntries(entries),
889
- };
890
- }
891
- toSecretPayload(secret) {
892
- if (secret.type === "docker") {
893
- return {
894
- name: secret.name,
895
- type: secret.type,
896
- data: {
897
- server: secret.server,
898
- username: secret.username,
899
- password: secret.password,
900
- email: secret.email ?? "none@example.com",
901
- },
902
- };
903
- }
904
- return {
905
- name: secret.name,
906
- type: secret.type,
907
- data: { ...secret.data },
908
- };
909
- }
910
- parseConnectorRef(data) {
911
- if (data == null) {
912
- return null;
913
- }
914
- if (typeof data !== "object") {
915
- throw new requirement_js_1.RoomException("Invalid connector payload");
916
- }
917
- const { openai_connector_id: openaiConnectorIdRaw, openaiConnectorId, server_url: serverUrlRaw, serverUrl, client_secret_id: clientSecretIdRaw, clientSecretId, } = data;
918
- return {
919
- openaiConnectorId: typeof openaiConnectorId === "string"
920
- ? openaiConnectorId
921
- : typeof openaiConnectorIdRaw === "string"
922
- ? openaiConnectorIdRaw
923
- : null,
924
- serverUrl: typeof serverUrl === "string"
925
- ? serverUrl
926
- : typeof serverUrlRaw === "string"
927
- ? serverUrlRaw
928
- : null,
929
- clientSecretId: typeof clientSecretId === "string"
930
- ? clientSecretId
931
- : typeof clientSecretIdRaw === "string"
932
- ? clientSecretIdRaw
933
- : null,
934
- };
935
- }
936
- serializeConnectorRef(connector) {
937
- if (connector == null) {
938
- return null;
939
- }
940
- const payload = {};
941
- if (connector.openaiConnectorId) {
942
- payload.openai_connector_id = connector.openaiConnectorId;
943
- }
944
- if (connector.serverUrl) {
945
- payload.server_url = connector.serverUrl;
946
- }
947
- if (connector.clientSecretId) {
948
- payload.client_secret_id = connector.clientSecretId;
949
- }
950
- return payload;
951
- }
952
- parseExternalOAuthClientRegistration(data) {
953
- if (!data || typeof data !== "object") {
954
- throw new requirement_js_1.RoomException("Invalid external oauth registration payload");
955
- }
956
- const { id, delegated_to: delegatedToRaw, delegatedTo, connector, oauth, client_id: clientIdRaw, clientId, client_secret: clientSecretRaw, clientSecret, } = data;
957
- const delegatedToValue = typeof delegatedTo === "string" ? delegatedTo : delegatedToRaw;
958
- const clientIdValue = typeof clientId === "string" ? clientId : clientIdRaw;
959
- const clientSecretValue = typeof clientSecret === "string" ? clientSecret : clientSecretRaw;
960
- if (typeof id !== "string" || typeof delegatedToValue !== "string" || typeof clientIdValue !== "string") {
961
- throw new requirement_js_1.RoomException("Invalid external oauth registration payload: missing fields");
962
- }
963
- return {
964
- id,
965
- delegatedTo: delegatedToValue,
966
- connector: this.parseConnectorRef(connector),
967
- oauth: oauth && typeof oauth === "object" ? oauth : null,
968
- clientId: clientIdValue,
969
- clientSecret: typeof clientSecretValue === "string" ? clientSecretValue : null,
970
- };
971
- }
972
777
  parseOAuthClient(data) {
973
778
  if (!data || typeof data !== "object") {
974
779
  throw new requirement_js_1.RoomException("Invalid OAuth client payload");
975
780
  }
781
+ if ("client" in data && data.client && typeof data.client === "object") {
782
+ data = data.client;
783
+ }
976
784
  const { client_id: clientIdRaw, clientId, client_secret: clientSecretRaw, clientSecret, grant_types: grantTypesRaw, grantTypes, response_types: responseTypesRaw, responseTypes, redirect_uris: redirectUrisRaw, redirectUris, scope, project_id: projectIdRaw, projectId, metadata } = data;
977
785
  const clientIdValue = typeof clientId === "string" ? clientId : clientIdRaw;
978
786
  const clientSecretValue = typeof clientSecret === "string" ? clientSecret : clientSecretRaw;
@@ -998,6 +806,7 @@ class Meshagent {
998
806
  scope,
999
807
  projectId: projectIdValue,
1000
808
  metadata: metadata && typeof metadata === "object" ? metadata : {},
809
+ official: Boolean(data.official),
1001
810
  };
1002
811
  }
1003
812
  parseRoomConnectionInfo(data) {
@@ -1038,45 +847,6 @@ class Meshagent {
1038
847
  responseType: "arrayBuffer",
1039
848
  });
1040
849
  }
1041
- async getProjectRole(projectId) {
1042
- const payload = await this.request(`/accounts/projects/${projectId}/role`, {
1043
- action: "fetch project role",
1044
- });
1045
- const role = payload?.role;
1046
- if (role !== "member" && role !== "admin" && role !== "developer") {
1047
- throw new requirement_js_1.RoomException("Invalid role payload");
1048
- }
1049
- return role;
1050
- }
1051
- async createShare(projectId, settings) {
1052
- return await this.request(`/accounts/projects/${projectId}/shares`, {
1053
- method: "POST",
1054
- json: { settings: settings ?? {} },
1055
- action: "create share",
1056
- });
1057
- }
1058
- async deleteShare(projectId, shareId) {
1059
- await this.request(`/accounts/projects/${projectId}/shares/${shareId}`, {
1060
- method: "DELETE",
1061
- action: "delete share",
1062
- responseType: "void",
1063
- });
1064
- }
1065
- async updateShare(projectId, shareId, settings) {
1066
- await this.request(`/accounts/projects/${projectId}/shares/${shareId}`, {
1067
- method: "PUT",
1068
- json: { settings: settings ?? {} },
1069
- action: "update share",
1070
- responseType: "void",
1071
- });
1072
- }
1073
- async listShares(projectId) {
1074
- const data = await this.request(`/accounts/projects/${projectId}/shares`, {
1075
- action: "list shares",
1076
- });
1077
- const shares = Array.isArray(data?.shares) ? data.shares : [];
1078
- return shares.map((item) => this.parseRoomShare(item));
1079
- }
1080
850
  async createProject(name, settings) {
1081
851
  return await this.request(`/accounts/projects`, {
1082
852
  method: "POST",
@@ -1085,39 +855,15 @@ class Meshagent {
1085
855
  });
1086
856
  }
1087
857
  async addUserToProject(projectId, userId, options = {}) {
1088
- const { isAdmin, isDeveloper, canCreateRooms, inviteRedirectUrl } = options;
858
+ const { roles = ["member"], email, inviteRedirectUrl } = options;
1089
859
  return await this.request(`/accounts/projects/${projectId}/users`, {
1090
860
  method: "POST",
1091
861
  json: {
1092
862
  project_id: projectId,
1093
863
  user_id: userId,
1094
- ...(isAdmin !== undefined ? { is_admin: isAdmin } : {}),
1095
- ...(isDeveloper !== undefined ? { is_developer: isDeveloper } : {}),
1096
- ...(canCreateRooms !== undefined
1097
- ? { can_create_rooms: canCreateRooms }
1098
- : {}),
1099
- ...(inviteRedirectUrl !== undefined
1100
- ? { invite_redirect_url: inviteRedirectUrl }
1101
- : {}),
1102
- },
1103
- action: "add user to project",
1104
- });
1105
- }
1106
- async addUserToProjectByEmail(projectId, email, options = {}) {
1107
- const { isAdmin, isDeveloper, canCreateRooms, inviteRedirectUrl } = options;
1108
- return await this.request(`/accounts/projects/${projectId}/users`, {
1109
- method: "POST",
1110
- json: {
1111
- project_id: projectId,
1112
- email,
1113
- ...(isAdmin !== undefined ? { is_admin: isAdmin } : {}),
1114
- ...(isDeveloper !== undefined ? { is_developer: isDeveloper } : {}),
1115
- ...(canCreateRooms !== undefined
1116
- ? { can_create_rooms: canCreateRooms }
1117
- : {}),
1118
- ...(inviteRedirectUrl !== undefined
1119
- ? { invite_redirect_url: inviteRedirectUrl }
1120
- : {}),
864
+ roles,
865
+ ...(email !== undefined ? { email } : {}),
866
+ ...(inviteRedirectUrl !== undefined ? { invite_redirect_url: inviteRedirectUrl } : {}),
1121
867
  },
1122
868
  action: "add user to project",
1123
869
  });
@@ -1135,79 +881,281 @@ class Meshagent {
1135
881
  action: "update project settings",
1136
882
  });
1137
883
  }
884
+ async updateUserInProject(projectId, userId, roles) {
885
+ return await this.request(`/accounts/projects/${projectId}/users/${userId}`, {
886
+ method: "PUT",
887
+ json: { roles },
888
+ action: "update project user",
889
+ });
890
+ }
1138
891
  async getUsersInProjectPage(projectId, options = {}) {
1139
- const { count = 100, offset = 0, filter } = options;
892
+ const { pageSize = 100, continuationToken, filter, email } = options;
1140
893
  const data = await this.request(`/accounts/projects/${projectId}/users`, {
1141
- query: { count, offset, filter },
894
+ query: { page_size: pageSize, continuation_token: continuationToken, filter, email },
1142
895
  action: "fetch project users",
1143
896
  });
1144
- const users = Array.isArray(data?.users) ? data.users : [];
1145
- return { users, total: typeof data?.total === "number" ? data.total : users.length };
1146
- }
1147
- async getUsersInProject(projectId) {
1148
- const page = await this.getUsersInProjectPage(projectId);
1149
- return { users: page.users, total: page.total };
897
+ const users = Array.isArray(data?.users) ? data.users : [];
898
+ return { users: users.map((user) => this.parseProjectMember(user)), continuationToken: data?.continuation_token ?? null };
899
+ }
900
+ async getUsersInProject(projectId) {
901
+ const page = await this.getUsersInProjectPage(projectId);
902
+ return page.users;
903
+ }
904
+ async getUserProfile(userId) {
905
+ return await this.request(`/accounts/profiles/${userId}`, {
906
+ action: "fetch user profile",
907
+ });
908
+ }
909
+ async updateUserProfile(userId, firstName, lastName) {
910
+ return await this.request(`/accounts/profiles/${userId}`, {
911
+ method: "PUT",
912
+ json: { first_name: firstName, last_name: lastName },
913
+ action: "update user profile",
914
+ });
915
+ }
916
+ async listProjects() {
917
+ return await this.request(`/accounts/projects`, {
918
+ action: "list projects",
919
+ });
920
+ }
921
+ async getProject(projectId) {
922
+ return await this.request(`/accounts/projects/${projectId}`, {
923
+ action: "get project",
924
+ });
925
+ }
926
+ async getProjectByKey(projectKey) {
927
+ return await this.request(`/accounts/projects/by-key/${encodeURIComponent(projectKey)}`, {
928
+ action: "get project by key",
929
+ });
930
+ }
931
+ async listServiceAccounts(projectId, options = {}) {
932
+ const params = new URLSearchParams();
933
+ if (options.pageSize !== undefined)
934
+ params.set("page_size", String(options.pageSize));
935
+ if (options.continuationToken !== undefined)
936
+ params.set("continuation_token", options.continuationToken);
937
+ if (options.filter !== undefined)
938
+ params.set("filter", options.filter);
939
+ if (options.view !== undefined)
940
+ params.set("view", options.view);
941
+ const query = params.toString();
942
+ return await this.request(`/accounts/projects/${projectId}/service-accounts${query ? `?${query}` : ""}`, {
943
+ action: "list service accounts",
944
+ });
945
+ }
946
+ async createServiceAccount(projectId, name, options = {}) {
947
+ return await this.request(`/accounts/projects/${projectId}/service-accounts`, {
948
+ method: "POST",
949
+ json: { name, ...options },
950
+ action: "create service account",
951
+ });
952
+ }
953
+ async mintParticipantToken(projectId, options) {
954
+ const json = options.grants !== undefined
955
+ ? { name: options.name, grants: options.grants }
956
+ : {
957
+ name: options.name,
958
+ room_name: options.roomName,
959
+ role: options.role,
960
+ api: options.api,
961
+ };
962
+ const data = await this.request(`/accounts/projects/${projectId}/participant-tokens`, {
963
+ method: "POST",
964
+ json,
965
+ action: "mint participant token",
966
+ });
967
+ if (typeof data?.token !== "string" || data.token.trim() === "") {
968
+ throw new Error("Invalid participant token mint response");
969
+ }
970
+ return data.token;
971
+ }
972
+ async createApiKey(projectId, serviceAccountId, name, description) {
973
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/api-keys`, {
974
+ method: "POST",
975
+ json: { name, description },
976
+ action: "create api key",
977
+ });
978
+ }
979
+ async deleteApiKey(projectId, serviceAccountId, id) {
980
+ await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/api-keys/${id}`, {
981
+ method: "DELETE",
982
+ action: "delete api key",
983
+ responseType: "void",
984
+ });
985
+ }
986
+ async revokeApiKeysByMsid(projectId, serviceAccountId, msid) {
987
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/api-keys:revoke`, {
988
+ method: "POST",
989
+ json: { msid },
990
+ action: "revoke api keys",
991
+ });
992
+ }
993
+ async listApiKeys(projectId, serviceAccountId) {
994
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/api-keys`, {
995
+ action: "list api keys",
996
+ });
997
+ }
998
+ async createUserSecret(input) {
999
+ return await this.request(`/accounts/users/me/secrets`, {
1000
+ method: "POST",
1001
+ json: this.secretPayload(input),
1002
+ action: "create user secret",
1003
+ });
1004
+ }
1005
+ async listUserSecrets(options = {}) {
1006
+ return await this.request(`/accounts/users/me/secrets`, {
1007
+ query: {
1008
+ page_size: options.pageSize ?? 100,
1009
+ continuation_token: options.continuationToken,
1010
+ filter: options.filter,
1011
+ },
1012
+ action: "list user secrets",
1013
+ });
1014
+ }
1015
+ async searchUserSecrets(input = {}) {
1016
+ return await this.request(`/accounts/users/me/secrets:search`, {
1017
+ method: "POST",
1018
+ json: this.secretSearchPayload(input),
1019
+ action: "search user secrets",
1020
+ });
1021
+ }
1022
+ async getUserSecret(secretId, options = {}) {
1023
+ return await this.request(`/accounts/users/me/secrets/${secretId}`, {
1024
+ query: {
1025
+ include_value: options.includeValue ? "true" : undefined,
1026
+ },
1027
+ action: "get user secret",
1028
+ });
1029
+ }
1030
+ async updateUserSecret(secretId, input) {
1031
+ return await this.request(`/accounts/users/me/secrets/${secretId}`, {
1032
+ method: "PATCH",
1033
+ json: this.secretPayload(input),
1034
+ action: "update user secret",
1035
+ });
1036
+ }
1037
+ async deleteUserSecret(secretId) {
1038
+ await this.request(`/accounts/users/me/secrets/${secretId}`, {
1039
+ method: "DELETE",
1040
+ action: "delete user secret",
1041
+ responseType: "void",
1042
+ });
1043
+ }
1044
+ async listUserSecretVersions(secretId) {
1045
+ const page = await this.request(`/accounts/users/me/secrets/${secretId}/versions`, {
1046
+ action: "list user secret versions",
1047
+ });
1048
+ return page.versions;
1049
+ }
1050
+ async createUserSecretVersion(secretId, input) {
1051
+ return await this.request(`/accounts/users/me/secrets/${secretId}/versions`, {
1052
+ method: "POST",
1053
+ json: this.secretVersionPayload(input),
1054
+ action: "create user secret version",
1055
+ });
1056
+ }
1057
+ async listUserSecretProxyAccess(secretId, options = {}) {
1058
+ return await this.request(`/accounts/users/me/secrets/${secretId}/access`, {
1059
+ query: {
1060
+ page_size: options.pageSize ?? 100,
1061
+ continuation_token: options.continuationToken,
1062
+ },
1063
+ action: "list user secret proxy access",
1064
+ });
1065
+ }
1066
+ async grantUserSecretProxyAccess(secretId, serviceAccountId) {
1067
+ await this.request(`/accounts/users/me/secrets/${secretId}/access:grant-proxy`, {
1068
+ method: "POST",
1069
+ json: { subject: { type: "service_account", id: serviceAccountId } },
1070
+ action: "grant user secret proxy access",
1071
+ responseType: "void",
1072
+ });
1073
+ }
1074
+ async revokeUserSecretProxyAccess(secretId, serviceAccountId) {
1075
+ await this.request(`/accounts/users/me/secrets/${secretId}/access:revoke-proxy`, {
1076
+ method: "POST",
1077
+ json: { subject: { type: "service_account", id: serviceAccountId } },
1078
+ action: "revoke user secret proxy access",
1079
+ responseType: "void",
1080
+ });
1081
+ }
1082
+ async createServiceAccountSecret(projectId, serviceAccountId, input) {
1083
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets`, {
1084
+ method: "POST",
1085
+ json: this.secretPayload(input),
1086
+ action: "create service account secret",
1087
+ });
1088
+ }
1089
+ async listServiceAccountSecrets(projectId, serviceAccountId, options = {}) {
1090
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets`, {
1091
+ query: {
1092
+ page_size: options.pageSize ?? 100,
1093
+ continuation_token: options.continuationToken,
1094
+ filter: options.filter,
1095
+ },
1096
+ action: "list service account secrets",
1097
+ });
1150
1098
  }
1151
- async getUserProfile(userId) {
1152
- return await this.request(`/accounts/profiles/${userId}`, {
1153
- action: "fetch user profile",
1099
+ async searchServiceAccountSecrets(projectId, serviceAccountId, input = {}) {
1100
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets:search`, {
1101
+ method: "POST",
1102
+ json: this.secretSearchPayload(input),
1103
+ action: "search service account secrets",
1154
1104
  });
1155
1105
  }
1156
- async updateUserProfile(userId, firstName, lastName) {
1157
- return await this.request(`/accounts/profiles/${userId}`, {
1158
- method: "PUT",
1159
- json: { first_name: firstName, last_name: lastName },
1160
- action: "update user profile",
1106
+ async getServiceAccountSecret(projectId, serviceAccountId, secretId, options = {}) {
1107
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets/${secretId}`, {
1108
+ query: {
1109
+ include_value: options.includeValue ? "true" : undefined,
1110
+ },
1111
+ action: "get service account secret",
1161
1112
  });
1162
1113
  }
1163
- async listProjects() {
1164
- return await this.request(`/accounts/projects`, {
1165
- action: "list projects",
1114
+ async updateServiceAccountSecret(projectId, serviceAccountId, secretId, input) {
1115
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets/${secretId}`, {
1116
+ method: "PATCH",
1117
+ json: this.secretPayload(input),
1118
+ action: "update service account secret",
1166
1119
  });
1167
1120
  }
1168
- async getProject(projectId) {
1169
- return await this.request(`/accounts/projects/${projectId}`, {
1170
- action: "get project",
1121
+ async deleteServiceAccountSecret(projectId, serviceAccountId, secretId) {
1122
+ await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets/${secretId}`, {
1123
+ method: "DELETE",
1124
+ action: "delete service account secret",
1125
+ responseType: "void",
1171
1126
  });
1172
1127
  }
1173
- async getProjectByKey(projectKey) {
1174
- return await this.request(`/accounts/projects/by-key/${encodeURIComponent(projectKey)}`, {
1175
- action: "get project by key",
1128
+ async listServiceAccountSecretVersions(projectId, serviceAccountId, secretId) {
1129
+ const page = await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets/${secretId}/versions`, {
1130
+ action: "list service account secret versions",
1176
1131
  });
1132
+ return page.versions;
1177
1133
  }
1178
- async createAgent(params) {
1179
- const { projectId, configuration, ifNotExists = false, permissions } = params;
1180
- const permissionsJson = permissions == null
1181
- ? undefined
1182
- : Object.fromEntries(Object.entries(permissions).map(([userId, grant]) => [userId, grant.toJson()]));
1183
- const data = await this.request(`/accounts/projects/${this.encodePathComponent(projectId)}/agents`, {
1134
+ async createServiceAccountSecretVersion(projectId, serviceAccountId, secretId, input) {
1135
+ return await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/secrets/${secretId}/versions`, {
1184
1136
  method: "POST",
1185
- json: {
1186
- configuration: pruneNullishValues(configuration),
1187
- if_not_exists: ifNotExists,
1188
- ...(permissionsJson !== undefined ? { permissions: permissionsJson } : {}),
1189
- },
1190
- action: "create agent",
1137
+ json: this.secretVersionPayload(input),
1138
+ action: "create service account secret version",
1191
1139
  });
1192
- return this.parseManagedAgent(data);
1193
1140
  }
1194
- async createApiKey(projectId, name, description) {
1195
- return await this.request(`/accounts/projects/${projectId}/api-keys`, {
1196
- method: "POST",
1197
- json: { name, description },
1198
- action: "create api key",
1141
+ async listServiceAccountPullSecrets(projectId, serviceAccountId) {
1142
+ const page = await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/pull-secrets`, {
1143
+ action: "list service account pull secrets",
1199
1144
  });
1145
+ return page.secrets;
1200
1146
  }
1201
- async deleteApiKey(projectId, id) {
1202
- await this.request(`/accounts/projects/${projectId}/api-keys/${id}`, {
1203
- method: "DELETE",
1204
- action: "delete api key",
1147
+ async addServiceAccountPullSecret(projectId, serviceAccountId, secretId) {
1148
+ await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/pull-secrets/${secretId}`, {
1149
+ method: "PUT",
1150
+ action: "add service account pull secret",
1205
1151
  responseType: "void",
1206
1152
  });
1207
1153
  }
1208
- async listApiKeys(projectId) {
1209
- return await this.request(`/accounts/projects/${projectId}/api-keys`, {
1210
- action: "list api keys",
1154
+ async removeServiceAccountPullSecret(projectId, serviceAccountId, secretId) {
1155
+ await this.request(`/accounts/projects/${projectId}/service-accounts/${serviceAccountId}/pull-secrets/${secretId}`, {
1156
+ method: "DELETE",
1157
+ action: "remove service account pull secret",
1158
+ responseType: "void",
1211
1159
  });
1212
1160
  }
1213
1161
  async getPricing() {
@@ -1318,6 +1266,40 @@ class Meshagent {
1318
1266
  const sessions = Array.isArray(data?.sessions) ? data.sessions : [];
1319
1267
  return sessions.map((item) => this.parseRoomSession(item));
1320
1268
  }
1269
+ async listRecentRoomSessions(projectId, roomName, options = {}) {
1270
+ const params = new URLSearchParams();
1271
+ if (options.limit !== undefined) {
1272
+ params.set("limit", String(options.limit));
1273
+ }
1274
+ const query = params.size > 0 ? `?${params.toString()}` : "";
1275
+ const data = await this.request(`/accounts/projects/${projectId}/rooms/${encodeURIComponent(roomName)}/sessions${query}`, { action: "list recent room sessions" });
1276
+ const sessions = Array.isArray(data?.sessions) ? data.sessions : [];
1277
+ return sessions.map((item) => this.parseRoomSession(item));
1278
+ }
1279
+ async listRecentSingleAgentSessions(projectId, agentName, options = {}) {
1280
+ const params = new URLSearchParams();
1281
+ if (options.limit !== undefined) {
1282
+ params.set("limit", String(options.limit));
1283
+ }
1284
+ const query = params.size > 0 ? `?${params.toString()}` : "";
1285
+ const data = await this.request(`/accounts/projects/${projectId}/agents/${encodeURIComponent(agentName)}/sessions${query}`, { action: "list recent agent sessions" });
1286
+ const sessions = Array.isArray(data?.sessions) ? data.sessions : [];
1287
+ return sessions.map((item) => this.parseRoomSession(item));
1288
+ }
1289
+ async createAgent(params) {
1290
+ const body = {
1291
+ configuration: params.configuration,
1292
+ if_not_exists: params.ifNotExists ?? false,
1293
+ };
1294
+ if (params.permissions != null) {
1295
+ body.permissions = params.permissions;
1296
+ }
1297
+ return await this.request(`/accounts/projects/${params.projectId}/agents`, {
1298
+ method: "POST",
1299
+ json: body,
1300
+ action: "create agent",
1301
+ });
1302
+ }
1321
1303
  async listSessionEvents(projectId, sessionId) {
1322
1304
  const data = await this.request(`/accounts/projects/${projectId}/sessions/${sessionId}/events`, {
1323
1305
  action: "list session events",
@@ -1346,34 +1328,6 @@ class Meshagent {
1346
1328
  const metrics = data?.["metrics"];
1347
1329
  return Array.isArray(metrics) ? metrics : [];
1348
1330
  }
1349
- async createWebhook(projectId, params) {
1350
- const { name, url, events, description = "", action: webhookAction = "", payload = null } = params;
1351
- return await this.request(`/accounts/projects/${projectId}/webhooks`, {
1352
- method: "POST",
1353
- json: { name, description, url, events, action: webhookAction, payload },
1354
- action: "create webhook",
1355
- });
1356
- }
1357
- async updateWebhook(projectId, webhookId, params) {
1358
- const { name, url, events, description = "", action: webhookAction = null, payload = null } = params;
1359
- return await this.request(`/accounts/projects/${projectId}/webhooks/${webhookId}`, {
1360
- method: "PUT",
1361
- json: { name, description, url, events, action: webhookAction, payload },
1362
- action: "update webhook",
1363
- });
1364
- }
1365
- async listWebhooks(projectId) {
1366
- return await this.request(`/accounts/projects/${projectId}/webhooks`, {
1367
- action: "list webhooks",
1368
- });
1369
- }
1370
- async deleteWebhook(projectId, webhookId) {
1371
- await this.request(`/accounts/projects/${projectId}/webhooks/${webhookId}`, {
1372
- method: "DELETE",
1373
- action: "delete webhook",
1374
- responseType: "void",
1375
- });
1376
- }
1377
1331
  async createMailbox(params) {
1378
1332
  const { projectId, address, room, queue, isPublic } = params;
1379
1333
  await this.request(`/accounts/projects/${projectId}/mailboxes`, {
@@ -1406,18 +1360,24 @@ class Meshagent {
1406
1360
  return { address, room, roomId: room_id, queue };
1407
1361
  }
1408
1362
  async listMailboxesPage(projectId, options = {}) {
1409
- const { count = 100, offset = 0, filter } = options;
1363
+ const { pageSize = 100, continuationToken, filter } = options;
1410
1364
  const data = await this.request(`/accounts/projects/${projectId}/mailboxes`, {
1411
- query: { count, offset, filter },
1365
+ query: { page_size: pageSize, continuation_token: continuationToken, filter },
1412
1366
  action: "list mailboxes",
1413
1367
  });
1414
1368
  const mailboxes = Array.isArray(data?.mailboxes) ? data.mailboxes : [];
1415
1369
  const parsed = mailboxes.map((item) => this.parseMailbox(item));
1416
- return { mailboxes: parsed, total: typeof data?.total === "number" ? data.total : parsed.length };
1370
+ return { mailboxes: parsed, total: typeof data?.total === "number" ? data.total : parsed.length, continuationToken: data.continuation_token ?? null };
1417
1371
  }
1418
1372
  async listMailboxes(projectId, options = {}) {
1419
- const page = await this.listMailboxesPage(projectId, options);
1420
- return page.mailboxes;
1373
+ const mailboxes = [];
1374
+ let continuationToken;
1375
+ do {
1376
+ const page = await this.listMailboxesPage(projectId, { ...options, continuationToken });
1377
+ mailboxes.push(...page.mailboxes);
1378
+ continuationToken = page.continuationToken ?? undefined;
1379
+ } while (continuationToken);
1380
+ return mailboxes;
1421
1381
  }
1422
1382
  async deleteMailbox(projectId, address) {
1423
1383
  await this.request(`/accounts/projects/${projectId}/mailboxes/${address}`, {
@@ -1464,18 +1424,24 @@ class Meshagent {
1464
1424
  return this.parseFeed(data.feed);
1465
1425
  }
1466
1426
  async listFeedsPage(projectId, options = {}) {
1467
- const { count = 100, offset = 0, filter } = options;
1427
+ const { pageSize = 100, continuationToken, filter, view } = options;
1468
1428
  const data = await this.request(`/accounts/projects/${projectId}/feeds`, {
1469
- query: { count, offset, filter },
1429
+ query: { page_size: pageSize, continuation_token: continuationToken, filter, view },
1470
1430
  action: "list feeds",
1471
1431
  });
1472
1432
  const feeds = Array.isArray(data?.feeds) ? data.feeds : [];
1473
1433
  const parsed = feeds.map((item) => this.parseFeed(item));
1474
- return { feeds: parsed, total: typeof data?.total === "number" ? data.total : parsed.length };
1434
+ return { feeds: parsed, total: typeof data?.total === "number" ? data.total : parsed.length, continuationToken: data.continuation_token ?? null };
1475
1435
  }
1476
1436
  async listFeeds(projectId, options = {}) {
1477
- const page = await this.listFeedsPage(projectId, options);
1478
- return page.feeds;
1437
+ const feeds = [];
1438
+ let continuationToken;
1439
+ do {
1440
+ const page = await this.listFeedsPage(projectId, { ...options, continuationToken });
1441
+ feeds.push(...page.feeds);
1442
+ continuationToken = page.continuationToken ?? undefined;
1443
+ } while (continuationToken);
1444
+ return feeds;
1479
1445
  }
1480
1446
  async listRoomFeedsPage(projectId, roomName, options = {}) {
1481
1447
  const { count = 100, offset = 0, filter } = options;
@@ -1634,12 +1600,28 @@ class Meshagent {
1634
1600
  });
1635
1601
  return this.parseProjectRepository(data);
1636
1602
  }
1637
- async listRepositories(projectId) {
1603
+ async listRepositoriesPage(projectId, options = {}) {
1604
+ const { pageSize = 100, view, continuationToken } = options;
1638
1605
  const data = await this.request(`/accounts/projects/${projectId}/repositories`, {
1606
+ query: { page_size: pageSize, view, continuation_token: continuationToken },
1639
1607
  action: "list repositories",
1640
1608
  });
1641
1609
  const repositories = Array.isArray(data?.repositories) ? data.repositories : [];
1642
- return repositories.map((item) => this.parseProjectRepository(item));
1610
+ return {
1611
+ repositories: repositories.map((item) => this.parseProjectRepository(item)),
1612
+ total: Number(data.total ?? repositories.length),
1613
+ continuationToken: data.continuation_token ?? null,
1614
+ };
1615
+ }
1616
+ async listRepositories(projectId, options = {}) {
1617
+ const repositories = [];
1618
+ let continuationToken;
1619
+ do {
1620
+ const page = await this.listRepositoriesPage(projectId, { view: options.view, continuationToken });
1621
+ repositories.push(...page.repositories);
1622
+ continuationToken = page.continuationToken ?? undefined;
1623
+ } while (continuationToken);
1624
+ return repositories;
1643
1625
  }
1644
1626
  async deleteRepository(projectId, repositoryId) {
1645
1627
  await this.request(`/accounts/projects/${projectId}/repositories/${repositoryId}`, {
@@ -1729,279 +1711,14 @@ class Meshagent {
1729
1711
  responseType: "void",
1730
1712
  });
1731
1713
  }
1732
- async createProjectSecret(params) {
1733
- const { projectId, name, type, data } = params;
1734
- const payload = await this.request(`/accounts/projects/${projectId}/secrets`, {
1735
- method: "POST",
1736
- json: {
1737
- name,
1738
- type,
1739
- data_base64: bytesToBase64(normalizeBinary(data)),
1740
- },
1741
- action: "create project secret",
1742
- });
1743
- if (!payload || typeof payload !== "object" || typeof payload.id !== "string") {
1744
- throw new requirement_js_1.RoomException("Invalid create project secret response payload");
1745
- }
1746
- return payload.id;
1747
- }
1748
- async updateProjectSecret(params) {
1749
- const { projectId, secretId, name, type, data } = params;
1750
- await this.request(`/accounts/projects/${projectId}/secrets/${secretId}`, {
1751
- method: "PUT",
1752
- json: {
1753
- name,
1754
- type,
1755
- data_base64: bytesToBase64(normalizeBinary(data)),
1756
- },
1757
- action: "update project secret",
1758
- responseType: "void",
1759
- });
1760
- }
1761
- async getProjectSecret(projectId, secretId) {
1762
- const data = await this.request(`/accounts/projects/${projectId}/secrets/${secretId}`, {
1763
- action: "fetch project secret",
1764
- });
1765
- return this.parseManagedSecret(data);
1766
- }
1767
- async listProjectSecrets(projectId) {
1768
- const data = await this.request(`/accounts/projects/${projectId}/secrets`, {
1769
- action: "list project secrets",
1770
- });
1771
- const secrets = Array.isArray(data?.secrets) ? data.secrets : [];
1772
- return secrets.map((item) => this.parseManagedSecretInfo(item));
1773
- }
1774
- async deleteProjectSecret(projectId, secretId) {
1775
- await this.request(`/accounts/projects/${projectId}/secrets/${secretId}`, {
1776
- method: "DELETE",
1777
- action: "delete project secret",
1778
- responseType: "void",
1779
- });
1780
- }
1781
- async createRoomSecret(params) {
1782
- const { projectId, roomName, data, secretId, name, type, delegatedTo, forIdentity } = params;
1783
- const payload = await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/secrets`, {
1784
- method: "POST",
1785
- json: {
1786
- data_base64: bytesToBase64(normalizeBinary(data)),
1787
- secret_id: secretId,
1788
- name,
1789
- type,
1790
- delegated_to: delegatedTo,
1791
- for_identity: forIdentity,
1792
- },
1793
- action: "create room secret",
1794
- });
1795
- if (!payload || typeof payload !== "object" || typeof payload.id !== "string") {
1796
- throw new requirement_js_1.RoomException("Invalid create room secret response payload");
1797
- }
1798
- return payload.id;
1799
- }
1800
- async updateRoomSecret(params) {
1801
- const { projectId, roomName, secretId, data, name, type, delegatedTo, forIdentity } = params;
1802
- await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/secrets/${secretId}`, {
1803
- method: "PUT",
1804
- json: {
1805
- data_base64: bytesToBase64(normalizeBinary(data)),
1806
- name,
1807
- type,
1808
- delegated_to: delegatedTo,
1809
- for_identity: forIdentity,
1810
- },
1811
- action: "update room secret",
1812
- responseType: "void",
1813
- });
1814
- }
1815
- async getRoomSecret(params) {
1816
- const { projectId, roomName, secretId, delegatedTo, forIdentity } = params;
1817
- const data = await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/secrets/${secretId}`, {
1818
- query: {
1819
- delegated_to: delegatedTo,
1820
- for_identity: forIdentity,
1821
- },
1822
- action: "fetch room secret",
1823
- });
1824
- return this.parseManagedSecret(data);
1825
- }
1826
- async listRoomSecrets(params) {
1827
- const { projectId, roomName, forIdentity } = params;
1828
- const data = await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/secrets`, {
1829
- query: {
1830
- for_identity: forIdentity,
1831
- },
1832
- action: "list room secrets",
1833
- });
1834
- const secrets = Array.isArray(data?.secrets) ? data.secrets : [];
1835
- return secrets.map((item) => this.parseManagedSecretInfo(item));
1836
- }
1837
- async deleteRoomSecret(params) {
1838
- const { projectId, roomName, secretId, delegatedTo, forIdentity } = params;
1839
- await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/secrets/${secretId}`, {
1840
- method: "DELETE",
1841
- query: {
1842
- delegated_to: delegatedTo,
1843
- for_identity: forIdentity,
1844
- },
1845
- action: "delete room secret",
1846
- responseType: "void",
1847
- });
1848
- }
1849
- async createSecret(projectId, secret) {
1850
- await this.createProjectSecret({
1851
- projectId,
1852
- name: secret.name,
1853
- type: secret.type,
1854
- data: utils_js_1.encoder.encode(JSON.stringify(this.toSecretPayload(secret).data)),
1855
- });
1856
- }
1857
- async updateSecret(projectId, secret) {
1858
- if (!secret.id) {
1859
- throw new requirement_js_1.RoomException("Secret id is required to update a secret");
1860
- }
1861
- await this.updateProjectSecret({
1862
- projectId,
1863
- secretId: secret.id,
1864
- name: secret.name,
1865
- type: secret.type,
1866
- data: utils_js_1.encoder.encode(JSON.stringify(this.toSecretPayload(secret).data)),
1867
- });
1868
- }
1869
- async deleteSecret(projectId, secretId) {
1870
- await this.deleteProjectSecret(projectId, secretId);
1871
- }
1872
- async listSecrets(projectId) {
1873
- const secretInfos = await this.listProjectSecrets(projectId);
1874
- const secrets = await Promise.all(secretInfos.map(async (secretInfo) => {
1875
- const secret = await this.getProjectSecret(projectId, secretInfo.id);
1876
- return this.parseSecretPayload(secret, secret.data);
1877
- }));
1878
- return secrets;
1879
- }
1880
- async createProjectExternalOAuthRegistration(params) {
1881
- const { projectId, oauth, clientId, clientSecret, delegatedTo, connector } = params;
1882
- const payload = await this.request(`/accounts/projects/${projectId}/external-oauth`, {
1883
- method: "POST",
1884
- json: {
1885
- oauth,
1886
- client_id: clientId,
1887
- client_secret: clientSecret,
1888
- delegated_to: delegatedTo,
1889
- connector: this.serializeConnectorRef(connector),
1890
- },
1891
- action: "create project external oauth registration",
1892
- });
1893
- if (!payload || typeof payload !== "object" || typeof payload.id !== "string") {
1894
- throw new requirement_js_1.RoomException("Invalid create project external oauth registration response payload");
1895
- }
1896
- return payload.id;
1897
- }
1898
- async updateProjectExternalOAuthRegistration(params) {
1899
- const { projectId, registrationId, oauth, clientId, clientSecret, delegatedTo, connector } = params;
1900
- await this.request(`/accounts/projects/${projectId}/external-oauth/${registrationId}`, {
1901
- method: "PUT",
1902
- json: {
1903
- oauth,
1904
- client_id: clientId,
1905
- client_secret: clientSecret,
1906
- delegated_to: delegatedTo,
1907
- connector: this.serializeConnectorRef(connector),
1908
- },
1909
- action: "update project external oauth registration",
1910
- responseType: "void",
1911
- });
1912
- }
1913
- async listProjectExternalOAuthRegistrations(params) {
1914
- const { projectId, delegatedTo } = params;
1915
- const data = await this.request(`/accounts/projects/${projectId}/external-oauth`, {
1916
- query: {
1917
- delegated_to: delegatedTo,
1918
- },
1919
- action: "list project external oauth registrations",
1920
- });
1921
- const registrations = Array.isArray(data?.registrations) ? data.registrations : [];
1922
- return registrations.map((item) => this.parseExternalOAuthClientRegistration(item));
1923
- }
1924
- async deleteProjectExternalOAuthRegistration(params) {
1925
- const { projectId, registrationId, delegatedTo } = params;
1926
- await this.request(`/accounts/projects/${projectId}/external-oauth/${registrationId}`, {
1927
- method: "DELETE",
1928
- query: {
1929
- delegated_to: delegatedTo,
1930
- },
1931
- action: "delete project external oauth registration",
1932
- responseType: "void",
1933
- });
1934
- }
1935
- async createRoomExternalOAuthRegistration(params) {
1936
- const { projectId, roomName, oauth, clientId, clientSecret, delegatedTo, connector } = params;
1937
- const payload = await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/external-oauth`, {
1938
- method: "POST",
1939
- json: {
1940
- oauth,
1941
- client_id: clientId,
1942
- client_secret: clientSecret,
1943
- delegated_to: delegatedTo,
1944
- connector: this.serializeConnectorRef(connector),
1945
- },
1946
- action: "create room external oauth registration",
1947
- });
1948
- if (!payload || typeof payload !== "object" || typeof payload.id !== "string") {
1949
- throw new requirement_js_1.RoomException("Invalid create room external oauth registration response payload");
1950
- }
1951
- return payload.id;
1952
- }
1953
- async updateRoomExternalOAuthRegistration(params) {
1954
- const { projectId, roomName, registrationId, oauth, clientId, clientSecret, delegatedTo, connector } = params;
1955
- await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/external-oauth/${registrationId}`, {
1956
- method: "PUT",
1957
- json: {
1958
- oauth,
1959
- client_id: clientId,
1960
- client_secret: clientSecret,
1961
- delegated_to: delegatedTo,
1962
- connector: this.serializeConnectorRef(connector),
1963
- },
1964
- action: "update room external oauth registration",
1965
- responseType: "void",
1966
- });
1967
- }
1968
- async listRoomExternalOAuthRegistrations(params) {
1969
- const { projectId, roomName, delegatedTo } = params;
1970
- const data = await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/external-oauth`, {
1971
- query: {
1972
- delegated_to: delegatedTo,
1973
- },
1974
- action: "list room external oauth registrations",
1975
- });
1976
- const registrations = Array.isArray(data?.registrations) ? data.registrations : [];
1977
- return registrations.map((item) => this.parseExternalOAuthClientRegistration(item));
1978
- }
1979
- async deleteRoomExternalOAuthRegistration(params) {
1980
- const { projectId, roomName, registrationId, delegatedTo } = params;
1981
- await this.request(`/accounts/projects/${projectId}/rooms/${roomName}/external-oauth/${registrationId}`, {
1982
- method: "DELETE",
1983
- query: {
1984
- delegated_to: delegatedTo,
1985
- },
1986
- action: "delete room external oauth registration",
1987
- responseType: "void",
1988
- });
1989
- }
1990
1714
  async createRoom(params) {
1991
- const { projectId, name, ifNotExists = false, metadata, annotations, permissions } = params;
1715
+ const { projectId, name, ifNotExists = false, metadata, annotations } = params;
1992
1716
  const payload = {
1993
1717
  name,
1994
1718
  if_not_exists: Boolean(ifNotExists),
1995
1719
  metadata,
1996
1720
  annotations,
1997
1721
  };
1998
- if (permissions) {
1999
- const serialized = {};
2000
- for (const [key, value] of Object.entries(permissions)) {
2001
- serialized[key] = value instanceof participant_token_js_1.ApiScope ? value.toJSON() : value;
2002
- }
2003
- payload["permissions"] = serialized;
2004
- }
2005
1722
  const data = await this.request(`/accounts/projects/${projectId}/rooms`, {
2006
1723
  method: "POST",
2007
1724
  json: payload,
@@ -2037,78 +1754,103 @@ class Meshagent {
2037
1754
  responseType: "void",
2038
1755
  });
2039
1756
  }
2040
- async connectRoom(projectId, room) {
2041
- const data = await this.request(`/accounts/projects/${projectId}/rooms/${room}/connect`, {
1757
+ async createGroup(params) {
1758
+ const { projectId, name, metadata, annotations } = params;
1759
+ const data = await this.request(`/accounts/projects/${projectId}/groups`, {
2042
1760
  method: "POST",
2043
- json: {},
2044
- action: "connect room",
1761
+ json: { name, metadata, annotations },
1762
+ action: "create group",
2045
1763
  });
2046
- return this.parseRoomConnectionInfo(data);
1764
+ return this.parseGroup(data);
2047
1765
  }
2048
- async createRoomGrant(params) {
2049
- const { projectId, roomId, userId, permissions } = params;
2050
- await this.request(`/accounts/projects/${projectId}/room-grants`, {
2051
- method: "POST",
2052
- json: {
2053
- room_id: roomId,
2054
- user_id: userId,
2055
- permissions: permissions.toJSON(),
2056
- },
2057
- action: "create room grant",
1766
+ async getGroup(projectId, groupId) {
1767
+ const data = await this.request(`/accounts/projects/${projectId}/groups/${groupId}`, {
1768
+ action: "fetch group",
1769
+ });
1770
+ return this.parseGroup(data);
1771
+ }
1772
+ async updateGroup(projectId, groupId, name, options = {}) {
1773
+ const payload = { name };
1774
+ if (options.metadata !== undefined) {
1775
+ payload["metadata"] = options.metadata;
1776
+ }
1777
+ if (options.annotations !== undefined) {
1778
+ payload["annotations"] = options.annotations;
1779
+ }
1780
+ await this.request(`/accounts/projects/${projectId}/groups/${groupId}`, {
1781
+ method: "PUT",
1782
+ json: payload,
1783
+ action: "update group",
2058
1784
  responseType: "void",
2059
1785
  });
2060
1786
  }
2061
- async createRoomGrantByEmail(params) {
2062
- const { projectId, roomId, email, permissions, inviteRedirectUrl } = params;
2063
- await this.request(`/accounts/projects/${projectId}/room-grants`, {
2064
- method: "POST",
2065
- json: {
2066
- room_id: roomId,
2067
- email,
2068
- permissions: permissions.toJSON(),
2069
- ...(inviteRedirectUrl !== undefined
2070
- ? { invite_redirect_url: inviteRedirectUrl }
2071
- : {}),
2072
- },
2073
- action: "create room grant",
1787
+ async deleteGroup(projectId, groupId) {
1788
+ await this.request(`/accounts/projects/${projectId}/groups/${groupId}`, {
1789
+ method: "DELETE",
1790
+ action: "delete group",
2074
1791
  responseType: "void",
2075
1792
  });
2076
1793
  }
2077
- async updateRoomGrant(params) {
2078
- const { projectId, roomId, userId, permissions, grantId } = params;
2079
- const gid = grantId ?? "unused";
2080
- await this.request(`/accounts/projects/${projectId}/room-grants/${gid}`, {
2081
- method: "PUT",
2082
- json: {
2083
- room_id: roomId,
2084
- user_id: userId,
2085
- permissions: permissions.toJSON(),
1794
+ async listGroupsPage(projectId, options = {}) {
1795
+ const data = await this.request(`/accounts/projects/${projectId}/groups`, {
1796
+ query: {
1797
+ page_size: options.pageSize ?? 50,
1798
+ continuation_token: options.continuationToken,
1799
+ filter: options.filter,
2086
1800
  },
2087
- action: "update room grant",
1801
+ action: "list groups",
1802
+ });
1803
+ const groups = Array.isArray(data?.groups) ? data.groups : [];
1804
+ return {
1805
+ groups: groups.map((item) => this.parseGroup(item)),
1806
+ continuationToken: data?.continuation_token ?? null,
1807
+ };
1808
+ }
1809
+ async listGroups(projectId, options = {}) {
1810
+ const page = await this.listGroupsPage(projectId, options);
1811
+ return page.groups;
1812
+ }
1813
+ async setGroupMember(params) {
1814
+ const { projectId, groupId, subject, role = "member" } = params;
1815
+ await this.request(`/accounts/projects/${projectId}/groups/${groupId}/members`, {
1816
+ method: "POST",
1817
+ json: { subject, role },
1818
+ action: "set group member",
2088
1819
  responseType: "void",
2089
1820
  });
2090
1821
  }
2091
- async deleteRoomGrant(projectId, roomId, userId) {
2092
- const room = this.encodePathComponent(roomId);
2093
- const user = this.encodePathComponent(userId);
2094
- await this.request(`/accounts/projects/${projectId}/room-grants/${room}/${user}`, {
1822
+ async listGroupMembersPage(projectId, groupId, options = {}) {
1823
+ const data = await this.request(`/accounts/projects/${projectId}/groups/${groupId}/members`, {
1824
+ query: { page_size: options.pageSize ?? 50, continuation_token: options.continuationToken },
1825
+ action: "list group members",
1826
+ });
1827
+ const members = Array.isArray(data?.members) ? data.members : [];
1828
+ return { members: members.map((item) => this.parseGroupMember(item)), continuationToken: data?.continuation_token ?? null };
1829
+ }
1830
+ async listGroupMembers(projectId, groupId, options = {}) {
1831
+ const page = await this.listGroupMembersPage(projectId, groupId, options);
1832
+ return page.members;
1833
+ }
1834
+ async deleteGroupMember(params) {
1835
+ const { projectId, groupId, subjectType, subjectId } = params;
1836
+ await this.request(`/accounts/projects/${projectId}/groups/${groupId}/members/${subjectType}/${subjectId}`, {
2095
1837
  method: "DELETE",
2096
- action: "delete room grant",
1838
+ action: "delete group member",
2097
1839
  responseType: "void",
2098
1840
  });
2099
1841
  }
2100
- async getRoomGrant(projectId, roomId, userId) {
2101
- const room = this.encodePathComponent(roomId);
2102
- const user = this.encodePathComponent(userId);
2103
- const data = await this.request(`/accounts/projects/${projectId}/room-grants/${room}/${user}`, {
2104
- action: "fetch room grant",
1842
+ async connectRoom(projectId, room) {
1843
+ const data = await this.request(`/accounts/projects/${projectId}/rooms/${room}/connect`, {
1844
+ method: "POST",
1845
+ json: {},
1846
+ action: "connect room",
2105
1847
  });
2106
- return this.parseProjectRoomGrant(data);
1848
+ return this.parseRoomConnectionInfo(data);
2107
1849
  }
2108
1850
  async listRooms(projectId, options = {}) {
2109
- const { limit = 50, offset = 0, orderBy = "room_name" } = options;
1851
+ const { pageSize = 50, continuationToken, filter, view } = options;
2110
1852
  const data = await this.request(`/accounts/projects/${projectId}/rooms`, {
2111
- query: { limit, offset, order_by: orderBy },
1853
+ query: { page_size: pageSize, continuation_token: continuationToken, filter, view },
2112
1854
  action: "list rooms",
2113
1855
  });
2114
1856
  const rooms = Array.isArray(data?.rooms) ? data.rooms : [];
@@ -2139,16 +1881,23 @@ class Meshagent {
2139
1881
  return this.parseRoute(data.route);
2140
1882
  }
2141
1883
  async listRoutesPage(projectId, options = {}) {
2142
- const { count = 100, offset = 0, filter } = options;
1884
+ const { pageSize = 100, continuationToken, filter } = options;
2143
1885
  const data = await this.request(`/accounts/projects/${projectId}/routes`, {
2144
- query: { count, offset, filter },
1886
+ query: { page_size: pageSize, continuation_token: continuationToken, filter },
2145
1887
  action: "list routes",
2146
1888
  });
2147
1889
  const routes = Array.isArray(data.routes) ? data.routes.map((item) => this.parseRoute(item)) : [];
2148
- return { routes, total: Number(data.total ?? routes.length) };
1890
+ return { routes, total: Number(data.total ?? routes.length), continuationToken: data.continuation_token ?? null };
2149
1891
  }
2150
1892
  async listRoutes(projectId, options = {}) {
2151
- return (await this.listRoutesPage(projectId, options)).routes;
1893
+ const routes = [];
1894
+ let continuationToken;
1895
+ do {
1896
+ const page = await this.listRoutesPage(projectId, { ...options, continuationToken });
1897
+ routes.push(...page.routes);
1898
+ continuationToken = page.continuationToken ?? undefined;
1899
+ } while (continuationToken);
1900
+ return routes;
2152
1901
  }
2153
1902
  async listRoomRoutesPage(params) {
2154
1903
  const { projectId, roomName, count = 100, offset = 0, filter } = params;
@@ -2184,63 +1933,115 @@ class Meshagent {
2184
1933
  responseType: "void",
2185
1934
  });
2186
1935
  }
2187
- async listRoomGrants(projectId, options = {}) {
2188
- const { limit = 50, offset = 0, orderBy = "room_name" } = options;
2189
- const data = await this.request(`/accounts/projects/${projectId}/room-grants`, {
2190
- query: { limit, offset, order_by: orderBy },
2191
- action: "list room grants",
1936
+ async testAccess(projectId, params) {
1937
+ const data = await this.request(`/accounts/projects/${projectId}/access:test`, {
1938
+ method: "POST",
1939
+ json: {
1940
+ subject: this.serializeAccessSubject(params.subject),
1941
+ resource: this.serializeAccessResource(params.resource),
1942
+ relation: params.relation,
1943
+ },
1944
+ action: "test access",
1945
+ });
1946
+ return {
1947
+ allowed: data?.allowed === true,
1948
+ resource: data?.resource && typeof data.resource === "object" ? this.parseAccessResource(data.resource) : undefined,
1949
+ subject: data?.subject && typeof data.subject === "object" ? this.parseAccessSubject(data.subject) : undefined,
1950
+ relation: typeof data?.relation === "string" ? data.relation : undefined,
1951
+ };
1952
+ }
1953
+ async getEffectiveAccess(projectId, params) {
1954
+ const data = await this.request(`/accounts/projects/${projectId}/access:effective`, {
1955
+ method: "POST",
1956
+ json: {
1957
+ subject: this.serializeAccessSubject(params.subject),
1958
+ resource: this.serializeAccessResource(params.resource),
1959
+ ...(params.relations ? { relations: params.relations } : {}),
1960
+ },
1961
+ action: "get effective access",
2192
1962
  });
2193
- const grants = Array.isArray(data?.room_grants) ? data.room_grants : [];
2194
- return grants.map((item) => this.parseProjectRoomGrant(item));
1963
+ return {
1964
+ resource: this.parseAccessResource(data?.resource),
1965
+ subject: this.parseAccessSubject(data?.subject),
1966
+ effectiveRoles: Array.isArray(data?.effective_roles) ? data.effective_roles.filter((item) => typeof item === "string") : [],
1967
+ capabilities: data?.capabilities && typeof data.capabilities === "object" ? data.capabilities : {},
1968
+ };
1969
+ }
1970
+ async listAccessBindings(projectId, params) {
1971
+ const page = await this.listAccessBindingsPage(projectId, params);
1972
+ return page.accessGrants;
2195
1973
  }
2196
- async listRoomGrantsByUser(projectId, userId, options = {}) {
2197
- const { limit = 50, offset = 0 } = options;
2198
- const encodedUser = this.encodePathComponent(userId);
2199
- const data = await this.request(`/accounts/projects/${projectId}/room-grants/by-user/${encodedUser}`, {
2200
- query: { limit, offset },
2201
- action: "list room grants by user",
1974
+ async listAccessBindingsPage(projectId, params) {
1975
+ const data = await this.request(`/accounts/projects/${projectId}/access:bindings`, {
1976
+ method: "POST",
1977
+ json: {
1978
+ subject: this.serializeAccessSubject(params.subject),
1979
+ },
1980
+ action: "list access bindings",
2202
1981
  });
2203
- const grants = Array.isArray(data?.room_grants) ? data.room_grants : [];
2204
- return grants.map((item) => this.parseProjectRoomGrant(item));
1982
+ return {
1983
+ accessGrants: Array.isArray(data?.access_grants)
1984
+ ? data.access_grants.map((item) => this.parseProjectRoomGrant(item))
1985
+ : [],
1986
+ };
2205
1987
  }
2206
- async listRoomGrantsByRoom(projectId, roomId, options = {}) {
2207
- const { limit = 50, offset = 0 } = options;
2208
- const encodedRoom = this.encodePathComponent(roomId);
2209
- const data = await this.request(`/accounts/projects/${projectId}/room-grants/by-room/${encodedRoom}`, {
2210
- query: { limit, offset },
2211
- action: "list room grants by room",
1988
+ async getResourcePolicyPage(projectId, params) {
1989
+ this.validateResourcePolicyType(params.resourceType);
1990
+ const data = await this.request(`/accounts/projects/${projectId}/iam/${params.resourceType}/${params.resourceId}/policy`, {
1991
+ method: "GET",
1992
+ query: { page_size: params.pageSize ?? 50, continuation_token: params.continuationToken },
1993
+ action: "get resource policy",
2212
1994
  });
2213
- const grants = Array.isArray(data?.room_grants) ? data.room_grants : [];
2214
- return grants.map((item) => this.parseProjectRoomGrant(item));
1995
+ return {
1996
+ resource: this.parseAccessResource(data?.resource),
1997
+ accessGrants: Array.isArray(data?.access_grants)
1998
+ ? data.access_grants.map((item) => this.parseProjectRoomGrant(item))
1999
+ : [],
2000
+ continuationToken: typeof data?.continuation_token === "string" ? data.continuation_token : null,
2001
+ };
2215
2002
  }
2216
- async listUniqueRoomsWithGrants(projectId, options = {}) {
2217
- const { limit = 50, offset = 0 } = options;
2218
- const data = await this.request(`/accounts/projects/${projectId}/room-grants/by-room`, {
2219
- query: { limit, offset },
2220
- action: "list unique rooms with grants",
2003
+ async getResourcePolicy(projectId, params) {
2004
+ const grants = [];
2005
+ let continuationToken = params.continuationToken;
2006
+ do {
2007
+ const page = await this.getResourcePolicyPage(projectId, { ...params, continuationToken });
2008
+ grants.push(...page.accessGrants);
2009
+ continuationToken = page.continuationToken ?? undefined;
2010
+ } while (continuationToken);
2011
+ return grants;
2012
+ }
2013
+ async grantResourcePolicy(projectId, params) {
2014
+ this.validateResourcePolicyType(params.resourceType);
2015
+ await this.request(`/accounts/projects/${projectId}/iam/${params.resourceType}/${params.resourceId}/policy:grant`, {
2016
+ method: "POST",
2017
+ json: {
2018
+ subject: this.serializeAccessSubject(params.subject),
2019
+ roles: params.roles,
2020
+ ...(params.inviteRedirectUrl ? { invite_redirect_url: params.inviteRedirectUrl } : {}),
2021
+ },
2022
+ action: "grant resource policy",
2221
2023
  });
2222
- const rooms = Array.isArray(data?.rooms) ? data.rooms : [];
2223
- return rooms.map((item) => this.parseProjectRoomGrantCount(item));
2224
2024
  }
2225
- async listUniqueUsersWithGrantsPage(projectId, options = {}) {
2226
- const { limit = 100, offset = 0, filter } = options;
2227
- const data = await this.request(`/accounts/projects/${projectId}/room-grants/by-user`, {
2228
- query: { limit, offset, filter },
2229
- action: "list unique users with grants",
2025
+ async revokeResourcePolicy(projectId, params) {
2026
+ this.validateResourcePolicyType(params.resourceType);
2027
+ await this.request(`/accounts/projects/${projectId}/iam/${params.resourceType}/${params.resourceId}/policy:revoke`, {
2028
+ method: "POST",
2029
+ json: {
2030
+ subject: this.serializeAccessSubject(params.subject),
2031
+ },
2032
+ action: "revoke resource policy",
2230
2033
  });
2231
- const users = Array.isArray(data?.users) ? data.users : [];
2232
- const parsed = users.map((item) => this.parseProjectUserGrantCount(item));
2233
- return { users: parsed, total: typeof data?.total === "number" ? data.total : parsed.length };
2234
2034
  }
2235
- async listUniqueUsersWithGrants(projectId, options = {}) {
2236
- const page = await this.listUniqueUsersWithGrantsPage(projectId, options);
2237
- return page.users;
2035
+ validateResourcePolicyType(resourceType) {
2036
+ if (resourceType === "agent") {
2037
+ throw new Error("managed agent resource policies are not supported; use agent run_as instead");
2038
+ }
2238
2039
  }
2239
2040
  async createOAuthClient(projectId, params) {
2240
- const { grantTypes, responseTypes, redirectUris, scope, metadata = {} } = params;
2041
+ const { grantTypes, responseTypes, redirectUris, scope, metadata = {}, official = false } = params;
2241
2042
  const data = await this.request(`/accounts/projects/${projectId}/oauth/clients`, {
2242
2043
  method: "POST",
2243
- json: { grant_types: grantTypes, response_types: responseTypes, redirect_uris: redirectUris, scope, metadata },
2044
+ json: { grant_types: grantTypes, response_types: responseTypes, redirect_uris: redirectUris, scope, metadata, official },
2244
2045
  action: "create oauth client",
2245
2046
  });
2246
2047
  return this.parseOAuthClient(data);