figmanage 1.3.7 → 1.4.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 (40) hide show
  1. package/README.md +181 -132
  2. package/dist/auth/client.d.ts +1 -0
  3. package/dist/auth/health.js +2 -1
  4. package/dist/cli/comments.js +79 -2
  5. package/dist/cli/components.js +66 -0
  6. package/dist/cli/compound-commands.js +2 -0
  7. package/dist/cli/org.js +143 -5
  8. package/dist/cli/teams.js +41 -1
  9. package/dist/cli/webhooks.js +20 -1
  10. package/dist/clients/internal-api.js +1 -1
  11. package/dist/clients/public-api.js +1 -1
  12. package/dist/mcp.d.ts +1 -0
  13. package/dist/mcp.js +10 -4
  14. package/dist/operations/comments.d.ts +25 -0
  15. package/dist/operations/comments.js +22 -0
  16. package/dist/operations/compound-manager.d.ts +1 -0
  17. package/dist/operations/compound-manager.js +17 -3
  18. package/dist/operations/dev-resources.d.ts +25 -0
  19. package/dist/operations/dev-resources.js +31 -0
  20. package/dist/operations/navigate.d.ts +5 -0
  21. package/dist/operations/navigate.js +20 -0
  22. package/dist/operations/org.d.ts +68 -1
  23. package/dist/operations/org.js +112 -1
  24. package/dist/operations/teams.d.ts +9 -0
  25. package/dist/operations/teams.js +23 -0
  26. package/dist/operations/webhooks.d.ts +14 -0
  27. package/dist/operations/webhooks.js +12 -0
  28. package/dist/tools/analytics.js +2 -0
  29. package/dist/tools/comments.js +99 -3
  30. package/dist/tools/compound-manager.js +7 -2
  31. package/dist/tools/compound.js +3 -0
  32. package/dist/tools/dev-resources.d.ts +2 -0
  33. package/dist/tools/dev-resources.js +78 -0
  34. package/dist/tools/org.js +203 -8
  35. package/dist/tools/permissions.js +3 -0
  36. package/dist/tools/register.d.ts +2 -1
  37. package/dist/tools/register.js +4 -1
  38. package/dist/tools/teams.js +53 -1
  39. package/dist/tools/webhooks.js +25 -2
  40. package/package.json +1 -1
package/dist/cli/org.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Command } from 'commander';
2
- import { listAdmins, listOrgTeams, seatUsage, listTeamMembers, billingOverview, listInvoices, orgDomains, aiCreditUsage, exportMembers, listOrgMembers, contractRates, changeSeat, } from '../operations/org.js';
2
+ import { listAdmins, listOrgTeams, seatUsage, listTeamMembers, billingOverview, listInvoices, orgDomains, aiCreditUsage, exportMembers, listOrgMembers, contractRates, changeSeat, activityLog, listPayments, removeOrgMember, createUserGroup, deleteUserGroups, addUserGroupMembers, removeUserGroupMembers, } from '../operations/org.js';
3
3
  import { output, error } from './format.js';
4
4
  import { formatApiError } from '../helpers.js';
5
5
  import { requireCookie } from './helpers.js';
@@ -130,13 +130,14 @@ export function orgCommand() {
130
130
  }
131
131
  });
132
132
  org
133
- .command('ai-credits <plan-id>')
134
- .description('AI credit usage summary for a billing plan')
133
+ .command('ai-credits <team-id>')
134
+ .description('AI credit usage summary (resolves billing plan from team)')
135
+ .option('--plan-id <id>', 'Plan ID override (skips team folder lookup)')
135
136
  .option('--json', 'Force JSON output')
136
- .action(async (planId, options) => {
137
+ .action(async (teamId, options) => {
137
138
  try {
138
139
  const config = requireCookie();
139
- const result = await aiCreditUsage(config, { plan_id: planId });
140
+ const result = await aiCreditUsage(config, { team_id: teamId, plan_id: options.planId });
140
141
  output(result, options);
141
142
  }
142
143
  catch (e) {
@@ -223,6 +224,143 @@ export function orgCommand() {
223
224
  process.exit(1);
224
225
  }
225
226
  });
227
+ org
228
+ .command('activity-log')
229
+ .description('Org audit log. Filter by email for per-user activity.')
230
+ .option('--org-id <id>', 'Org ID override')
231
+ .option('--emails <list>', 'Comma-separated emails to filter')
232
+ .option('--start <date>', 'Start date (ISO or YYYY-MM-DD)')
233
+ .option('--end <date>', 'End date (ISO or YYYY-MM-DD)')
234
+ .option('--page-size <n>', 'Entries per page')
235
+ .option('--after <cursor>', 'Pagination cursor from previous response')
236
+ .option('--json', 'Force JSON output')
237
+ .action(async (options) => {
238
+ try {
239
+ const config = requireCookie();
240
+ const result = await activityLog(config, {
241
+ org_id: options.orgId,
242
+ emails: options.emails,
243
+ start_time: options.start,
244
+ end_time: options.end,
245
+ page_size: options.pageSize ? parseInt(options.pageSize, 10) : undefined,
246
+ after: options.after,
247
+ });
248
+ output(result, options);
249
+ }
250
+ catch (e) {
251
+ error(formatApiError(e));
252
+ process.exit(1);
253
+ }
254
+ });
255
+ org
256
+ .command('payments')
257
+ .description('List paid invoices / payment history')
258
+ .option('--org-id <id>', 'Org ID override')
259
+ .option('--json', 'Force JSON output')
260
+ .action(async (options) => {
261
+ try {
262
+ const config = requireCookie();
263
+ const result = await listPayments(config, { org_id: options.orgId });
264
+ output(result, options);
265
+ }
266
+ catch (e) {
267
+ error(formatApiError(e));
268
+ process.exit(1);
269
+ }
270
+ });
271
+ org
272
+ .command('remove-org-member <user>')
273
+ .description('Permanently remove a member from the org (cannot be undone)')
274
+ .option('--org-id <id>', 'Org ID override')
275
+ .option('--confirm', 'Confirm permanent removal')
276
+ .option('--json', 'Force JSON output')
277
+ .action(async (user, options) => {
278
+ try {
279
+ const config = requireCookie();
280
+ const msg = await removeOrgMember(config, {
281
+ user_identifier: user,
282
+ org_id: options.orgId,
283
+ confirm: options.confirm,
284
+ });
285
+ output({ message: msg }, options);
286
+ }
287
+ catch (e) {
288
+ error(formatApiError(e));
289
+ process.exit(1);
290
+ }
291
+ });
292
+ org
293
+ .command('create-user-group <name>')
294
+ .description('Create a user group')
295
+ .option('--description <text>', 'Group description')
296
+ .option('--team-id <id>', 'Team ID (resolves billing plan)')
297
+ .option('--plan-id <id>', 'Plan ID override')
298
+ .option('--emails <list>', 'Comma-separated emails to add as initial members')
299
+ .option('--no-notify', 'Skip member notification')
300
+ .option('--json', 'Force JSON output')
301
+ .action(async (name, options) => {
302
+ try {
303
+ const config = requireCookie();
304
+ const result = await createUserGroup(config, {
305
+ name,
306
+ description: options.description,
307
+ team_id: options.teamId,
308
+ plan_id: options.planId,
309
+ emails: options.emails ? options.emails.split(',').map(e => e.trim()) : undefined,
310
+ should_notify: options.notify,
311
+ });
312
+ output(result, options);
313
+ }
314
+ catch (e) {
315
+ error(formatApiError(e));
316
+ process.exit(1);
317
+ }
318
+ });
319
+ org
320
+ .command('delete-user-groups <ids...>')
321
+ .description('Delete one or more user groups')
322
+ .option('--json', 'Force JSON output')
323
+ .action(async (ids, options) => {
324
+ try {
325
+ const config = requireCookie();
326
+ const msg = await deleteUserGroups(config, { user_group_ids: ids });
327
+ output({ message: msg }, options);
328
+ }
329
+ catch (e) {
330
+ error(formatApiError(e));
331
+ process.exit(1);
332
+ }
333
+ });
334
+ org
335
+ .command('add-user-group-members <group-id> <emails...>')
336
+ .description('Add members to a user group by email')
337
+ .option('--json', 'Force JSON output')
338
+ .action(async (groupId, emails, options) => {
339
+ try {
340
+ const config = requireCookie();
341
+ const result = await addUserGroupMembers(config, { user_group_id: groupId, emails });
342
+ output(result, options);
343
+ }
344
+ catch (e) {
345
+ error(formatApiError(e));
346
+ process.exit(1);
347
+ }
348
+ });
349
+ org
350
+ .command('remove-user-group-members <group-id> <user-ids...>')
351
+ .description('Remove members from a user group')
352
+ .option('--json', 'Force JSON output')
353
+ .action(async (groupId, userIds, options) => {
354
+ try {
355
+ const config = requireCookie();
356
+ const result = await removeUserGroupMembers(config, { user_group_id: groupId, user_ids: userIds });
357
+ output({ message: result }, options);
358
+ }
359
+ catch (e) {
360
+ error(formatApiError(e));
361
+ process.exit(1);
362
+ }
363
+ });
226
364
  return org;
227
365
  }
228
366
  //# sourceMappingURL=org.js.map
package/dist/cli/teams.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Command } from 'commander';
2
- import { createTeam, renameTeam, deleteTeam } from '../operations/teams.js';
2
+ import { createTeam, renameTeam, deleteTeam, addTeamMember, removeTeamMember } from '../operations/teams.js';
3
3
  import { output, error } from './format.js';
4
4
  import { formatApiError } from '../helpers.js';
5
5
  import { requireCookie } from './helpers.js';
@@ -57,6 +57,46 @@ export function teamsCommand() {
57
57
  process.exit(1);
58
58
  }
59
59
  });
60
+ teams
61
+ .command('add-member <team-id> <email>')
62
+ .description('Add a member to a team by email')
63
+ .option('--level <n>', 'Permission level: 100 = view (default), 300 = edit, 999 = admin')
64
+ .option('--json', 'Force JSON output')
65
+ .action(async (teamId, email, options) => {
66
+ try {
67
+ const config = requireCookie();
68
+ const msg = await addTeamMember(config, {
69
+ team_id: teamId,
70
+ email,
71
+ level: options.level ? parseInt(options.level, 10) : undefined,
72
+ });
73
+ output({ message: msg }, options);
74
+ }
75
+ catch (e) {
76
+ error(formatApiError(e));
77
+ process.exit(1);
78
+ }
79
+ });
80
+ teams
81
+ .command('remove-member <team-id> <user-id>')
82
+ .description('Remove a member from a team')
83
+ .option('--json', 'Force JSON output')
84
+ .action(async (teamId, userId, options) => {
85
+ try {
86
+ const config = requireCookie();
87
+ const { confirmAction } = await import('./helpers.js');
88
+ if (!await confirmAction(`Remove user ${userId} from team ${teamId}?`)) {
89
+ console.log('Cancelled.');
90
+ return;
91
+ }
92
+ const msg = await removeTeamMember(config, { team_id: teamId, user_id: userId });
93
+ output({ message: msg }, options);
94
+ }
95
+ catch (e) {
96
+ error(formatApiError(e));
97
+ process.exit(1);
98
+ }
99
+ });
60
100
  return teams;
61
101
  }
62
102
  //# sourceMappingURL=teams.js.map
@@ -1,5 +1,5 @@
1
1
  import { Command } from 'commander';
2
- import { listWebhooks, createWebhook, updateWebhook, deleteWebhook, } from '../operations/webhooks.js';
2
+ import { listWebhooks, createWebhook, updateWebhook, deleteWebhook, webhookRequests, } from '../operations/webhooks.js';
3
3
  import { output, error } from './format.js';
4
4
  import { formatApiError } from '../helpers.js';
5
5
  import { requirePat } from './helpers.js';
@@ -85,6 +85,25 @@ export function webhooksCommand() {
85
85
  process.exit(1);
86
86
  }
87
87
  });
88
+ webhooks
89
+ .command('requests <webhook-id>')
90
+ .description('List recent webhook delivery attempts (last 7 days)')
91
+ .option('--json', 'Force JSON output')
92
+ .action(async (webhookId, options) => {
93
+ try {
94
+ const config = requirePat();
95
+ const result = await webhookRequests(config, { webhook_id: webhookId });
96
+ if (result.requests.length === 0) {
97
+ console.log('No webhook deliveries in the last 7 days.');
98
+ return;
99
+ }
100
+ output(result, options);
101
+ }
102
+ catch (e) {
103
+ error(formatApiError(e));
104
+ process.exit(1);
105
+ }
106
+ });
88
107
  webhooks
89
108
  .command('delete <webhook-id>')
90
109
  .description('Delete a webhook')
@@ -8,7 +8,7 @@ export function internalClient(config) {
8
8
  if (existing)
9
9
  return existing;
10
10
  const client = axios.create({
11
- baseURL: 'https://www.figma.com',
11
+ baseURL: process.env.FIGMA_INTERNAL_BASE_URL || 'https://www.figma.com',
12
12
  httpsAgent,
13
13
  headers: {
14
14
  'Cookie': `__Host-figma.authn=${config.cookie || ''}`,
@@ -8,7 +8,7 @@ export function publicClient(config) {
8
8
  if (existing)
9
9
  return existing;
10
10
  const client = axios.create({
11
- baseURL: 'https://api.figma.com',
11
+ baseURL: process.env.FIGMA_PUBLIC_BASE_URL || 'https://api.figma.com',
12
12
  httpsAgent,
13
13
  headers: {
14
14
  'X-Figma-Token': config.pat || '',
package/dist/mcp.d.ts CHANGED
@@ -7,6 +7,7 @@ import './tools/export.js';
7
7
  import './tools/versions.js';
8
8
  import './tools/branching.js';
9
9
  import './tools/components.js';
10
+ import './tools/dev-resources.js';
10
11
  import './tools/webhooks.js';
11
12
  import './tools/reading.js';
12
13
  import './tools/analytics.js';
package/dist/mcp.js CHANGED
@@ -7,6 +7,7 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
7
7
  import { loadAuthConfig, hasPat, hasCookie } from './auth/client.js';
8
8
  import { registerTools } from './tools/register.js';
9
9
  import { registerSetupTools } from './tools/setup.js';
10
+ import { checkIsAdmin } from './operations/navigate.js';
10
11
  // Import tool modules (side-effect: registers via defineTool)
11
12
  import './tools/navigate.js';
12
13
  import './tools/files.js';
@@ -17,6 +18,7 @@ import './tools/export.js';
17
18
  import './tools/versions.js';
18
19
  import './tools/branching.js';
19
20
  import './tools/components.js';
21
+ import './tools/dev-resources.js';
20
22
  import './tools/webhooks.js';
21
23
  import './tools/reading.js';
22
24
  import './tools/analytics.js';
@@ -73,19 +75,23 @@ export async function startMcpServer() {
73
75
  version,
74
76
  });
75
77
  const fullyConfigured = hasPat(config) && hasCookie(config);
78
+ const isAdmin = hasCookie(config) ? await checkIsAdmin(config) : false;
79
+ config.isAdmin = isAdmin;
76
80
  if (fullyConfigured) {
77
- registerTools(server, config, enabledToolsets, readOnly);
81
+ registerTools(server, config, enabledToolsets, readOnly, isAdmin);
78
82
  }
79
83
  else {
80
84
  // No auth or partial auth: register setup tools.
81
85
  // If env vars provide some auth, also register whatever tools are available.
82
86
  if (hasPat(config) || hasCookie(config)) {
83
- registerTools(server, config, enabledToolsets, readOnly);
87
+ registerTools(server, config, enabledToolsets, readOnly, isAdmin);
84
88
  }
85
- registerSetupTools(server, () => {
89
+ registerSetupTools(server, async () => {
86
90
  // Re-load config after setup wrote credentials to disk
87
91
  const newConfig = loadAuthConfig();
88
- registerTools(server, newConfig, enabledToolsets, readOnly);
92
+ const newIsAdmin = await checkIsAdmin(newConfig);
93
+ newConfig.isAdmin = newIsAdmin;
94
+ registerTools(server, newConfig, enabledToolsets, readOnly, newIsAdmin);
89
95
  server.server.sendToolListChanged();
90
96
  });
91
97
  }
@@ -36,6 +36,31 @@ export declare function deleteComment(config: AuthConfig, params: {
36
36
  file_key: string;
37
37
  comment_id: string;
38
38
  }): Promise<void>;
39
+ export declare function resolveComment(config: AuthConfig, params: {
40
+ file_key: string;
41
+ comment_id: string;
42
+ resolved?: boolean;
43
+ }): Promise<string>;
44
+ export declare function editComment(config: AuthConfig, params: {
45
+ file_key: string;
46
+ comment_id: string;
47
+ message: string;
48
+ }): Promise<string>;
49
+ export interface AddedReaction {
50
+ emoji: string;
51
+ user: string;
52
+ created_at: string;
53
+ }
54
+ export declare function addCommentReaction(config: AuthConfig, params: {
55
+ file_key: string;
56
+ comment_id: string;
57
+ emoji: string;
58
+ }): Promise<AddedReaction>;
59
+ export declare function removeCommentReaction(config: AuthConfig, params: {
60
+ file_key: string;
61
+ comment_id: string;
62
+ emoji: string;
63
+ }): Promise<void>;
39
64
  export declare function listCommentReactions(config: AuthConfig, params: {
40
65
  file_key: string;
41
66
  comment_id: string;
@@ -1,4 +1,5 @@
1
1
  import { publicClient } from '../clients/public-api.js';
2
+ import { internalClient } from '../clients/internal-api.js';
2
3
  export async function listComments(config, params) {
3
4
  const res = await publicClient(config).get(`/v1/files/${params.file_key}/comments`);
4
5
  const comments = res.data?.comments || [];
@@ -53,6 +54,27 @@ export async function postComment(config, params) {
53
54
  export async function deleteComment(config, params) {
54
55
  await publicClient(config).delete(`/v1/files/${params.file_key}/comments/${params.comment_id}`);
55
56
  }
57
+ export async function resolveComment(config, params) {
58
+ const resolve = params.resolved !== false;
59
+ await internalClient(config).put(`/api/file/${params.file_key}/comments/${params.comment_id}`, { resolved_at: resolve ? 'true' : null });
60
+ return `Comment ${params.comment_id} ${resolve ? 'resolved' : 'unresolved'}.`;
61
+ }
62
+ export async function editComment(config, params) {
63
+ await internalClient(config).put(`/api/file/${params.file_key}/comments/${params.comment_id}`, { message_meta: [{ t: params.message }] });
64
+ return `Comment ${params.comment_id} updated.`;
65
+ }
66
+ export async function addCommentReaction(config, params) {
67
+ const res = await publicClient(config).post(`/v1/files/${params.file_key}/comments/${params.comment_id}/reactions`, { emoji: params.emoji });
68
+ const r = res.data;
69
+ return {
70
+ emoji: r.emoji || params.emoji,
71
+ user: r.user?.handle || '',
72
+ created_at: r.created_at || new Date().toISOString(),
73
+ };
74
+ }
75
+ export async function removeCommentReaction(config, params) {
76
+ await publicClient(config).delete(`/v1/files/${params.file_key}/comments/${params.comment_id}/reactions`, { params: { emoji: params.emoji } });
77
+ }
56
78
  export async function listCommentReactions(config, params) {
57
79
  const res = await publicClient(config).get(`/v1/files/${params.file_key}/comments/${params.comment_id}/reactions`);
58
80
  const reactions = res.data?.reactions || [];
@@ -3,6 +3,7 @@ export declare function offboardUser(config: AuthConfig, params: {
3
3
  user_identifier: string;
4
4
  execute: boolean;
5
5
  transfer_to?: string;
6
+ remove_from_org?: boolean;
6
7
  org_id?: string;
7
8
  }): Promise<{
8
9
  user: {
@@ -22,7 +22,7 @@ const PAID_STATUSES = {
22
22
  const LEVEL_MAP = { editor: 300, viewer: 100 };
23
23
  // -- offboard_user --
24
24
  export async function offboardUser(config, params) {
25
- const { user_identifier, execute, transfer_to } = params;
25
+ const { user_identifier, execute, transfer_to, remove_from_org } = params;
26
26
  const orgId = requireOrgId(config, params.org_id);
27
27
  const api = internalClient(config);
28
28
  // Step 1: Resolve user
@@ -175,7 +175,7 @@ export async function offboardUser(config, params) {
175
175
  file_ownership: fileOwnership,
176
176
  summary,
177
177
  transfer_plan: transferPlan,
178
- note: 'Run with execute=true to perform offboarding. Provide transfer_to if the user owns files.',
178
+ note: 'Run with execute=true to perform offboarding. Provide transfer_to if the user owns files. Add remove_from_org=true to fully remove from the org (permanent).',
179
179
  };
180
180
  }
181
181
  // --- Execute mode ---
@@ -315,6 +315,18 @@ export async function offboardUser(config, params) {
315
315
  actions.push({ action: 'downgrade_seat', status: 'failed', detail: formatApiError(e) });
316
316
  }
317
317
  }
318
+ // Step F: Remove from org (permanent, requires remove_from_org flag)
319
+ if (remove_from_org) {
320
+ try {
321
+ await api.delete(`/api/orgs/${orgId}/org_users`, {
322
+ data: { org_user_ids: [user.org_user_id] },
323
+ });
324
+ actions.push({ action: 'remove_from_org', status: 'done', detail: 'Permanently removed from org' });
325
+ }
326
+ catch (e) {
327
+ actions.push({ action: 'remove_from_org', status: 'failed', detail: formatApiError(e) });
328
+ }
329
+ }
318
330
  const succeeded = actions.filter(a => a.status === 'done').length;
319
331
  const failed = actions.filter(a => a.status === 'failed').length;
320
332
  return {
@@ -324,7 +336,9 @@ export async function offboardUser(config, params) {
324
336
  summary: { succeeded, failed, total: actions.length },
325
337
  note: failed > 0
326
338
  ? `${failed} action(s) failed. Review and retry manually.`
327
- : 'Offboarding complete.',
339
+ : remove_from_org
340
+ ? 'Offboarding complete. User permanently removed from org.'
341
+ : 'Offboarding complete. User remains in org (use remove_from_org=true to fully remove).',
328
342
  };
329
343
  }
330
344
  // -- onboard_user --
@@ -0,0 +1,25 @@
1
+ import type { AuthConfig } from '../auth/client.js';
2
+ export interface DevResource {
3
+ id: string;
4
+ name: string;
5
+ url: string;
6
+ file_key: string;
7
+ node_id: string;
8
+ dev_status?: string;
9
+ }
10
+ export declare function listDevResources(config: AuthConfig, params: {
11
+ file_key: string;
12
+ node_ids?: string[];
13
+ }): Promise<DevResource[]>;
14
+ export interface CreateDevResourceParams {
15
+ file_key: string;
16
+ node_id: string;
17
+ name: string;
18
+ url: string;
19
+ }
20
+ export declare function createDevResource(config: AuthConfig, params: CreateDevResourceParams): Promise<Record<string, any>>;
21
+ export declare function deleteDevResource(config: AuthConfig, params: {
22
+ file_key: string;
23
+ dev_resource_id: string;
24
+ }): Promise<void>;
25
+ //# sourceMappingURL=dev-resources.d.ts.map
@@ -0,0 +1,31 @@
1
+ import { publicClient } from '../clients/public-api.js';
2
+ export async function listDevResources(config, params) {
3
+ const reqParams = {};
4
+ if (params.node_ids?.length)
5
+ reqParams.node_ids = params.node_ids.join(',');
6
+ const res = await publicClient(config).get(`/v1/files/${params.file_key}/dev_resources`, { params: reqParams });
7
+ const resources = res.data?.dev_resources || [];
8
+ return resources.map((r) => ({
9
+ id: r.id,
10
+ name: r.name,
11
+ url: r.url,
12
+ file_key: r.file_key || params.file_key,
13
+ node_id: r.node_id,
14
+ dev_status: r.dev_status,
15
+ }));
16
+ }
17
+ export async function createDevResource(config, params) {
18
+ const res = await publicClient(config).post('/v1/dev_resources', {
19
+ dev_resources: [{
20
+ file_key: params.file_key,
21
+ node_id: params.node_id,
22
+ name: params.name,
23
+ url: params.url,
24
+ }],
25
+ });
26
+ return res.data;
27
+ }
28
+ export async function deleteDevResource(config, params) {
29
+ await publicClient(config).delete(`/v1/files/${params.file_key}/dev_resources/${params.dev_resource_id}`);
30
+ }
31
+ //# sourceMappingURL=dev-resources.js.map
@@ -72,6 +72,11 @@ export interface Favorite {
72
72
  name: string;
73
73
  type?: string;
74
74
  }
75
+ /**
76
+ * Check if the current user is an org admin.
77
+ * Returns false on any error (no org, 403, network) -- safe default.
78
+ */
79
+ export declare function checkIsAdmin(config: AuthConfig): Promise<boolean>;
75
80
  export declare function checkAuthStatus(config: AuthConfig): Promise<AuthCheckResult>;
76
81
  export declare function listOrgs(config: AuthConfig): Promise<OrgListEntry[]>;
77
82
  export declare function switchOrg(config: AuthConfig, params: {
@@ -10,8 +10,28 @@ function requireOrgId(config, explicit) {
10
10
  throw new Error('Invalid org ID format');
11
11
  return id;
12
12
  }
13
+ /**
14
+ * Check if the current user is an org admin.
15
+ * Returns false on any error (no org, 403, network) -- safe default.
16
+ */
17
+ export async function checkIsAdmin(config) {
18
+ const orgId = config.orgId || process.env.FIGMA_ORG_ID;
19
+ if (!orgId || !config.cookie)
20
+ return false;
21
+ try {
22
+ const res = await internalClient(config).get(`/api/orgs/${orgId}/admins`, { params: { include_license_admins: false } });
23
+ const admins = res.data?.meta?.admins || res.data?.meta || [];
24
+ return admins.some(a => (a.user_id || a.user?.id) === config.userId);
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
13
30
  export async function checkAuthStatus(config) {
14
31
  const status = await checkAuth(config);
32
+ if (config.isAdmin === undefined && config.cookie) {
33
+ config.isAdmin = await checkIsAdmin(config);
34
+ }
15
35
  const formatted = formatAuthStatus(status, config);
16
36
  return { status, formatted };
17
37
  }
@@ -1,8 +1,11 @@
1
1
  import type { AuthConfig } from '../auth/client.js';
2
+ import { internalClient } from '../clients/internal-api.js';
2
3
  export declare const SEAT_HIERARCHY: Record<string, number>;
3
4
  export declare const SEAT_LABELS: Record<string, string>;
4
5
  export declare const PAID_STATUSES: Record<string, Record<string, string>>;
5
6
  export declare const SEAT_KEY_TO_TYPE: Record<string, string>;
7
+ /** Resolve a billing plan_id from a team's folders. */
8
+ export declare function resolvePlanId(client: ReturnType<typeof internalClient>, teamId: string): Promise<string>;
6
9
  export interface Admin {
7
10
  user_id: string;
8
11
  email: string | undefined;
@@ -54,7 +57,8 @@ export declare function orgDomains(config: AuthConfig, params: {
54
57
  org_id?: string;
55
58
  }): Promise<Record<string, any>>;
56
59
  export declare function aiCreditUsage(config: AuthConfig, params: {
57
- plan_id: string;
60
+ team_id: string;
61
+ plan_id?: string;
58
62
  }): Promise<any>;
59
63
  export declare function exportMembers(config: AuthConfig, params: {
60
64
  org_id?: string;
@@ -92,4 +96,67 @@ export declare function changeSeat(config: AuthConfig, params: {
92
96
  org_id?: string;
93
97
  confirm?: boolean;
94
98
  }): Promise<ChangeSeatResult | string>;
99
+ export interface ActivityLogEntry {
100
+ id: string;
101
+ timestamp: string;
102
+ event: string;
103
+ actor: {
104
+ id: string;
105
+ email: string;
106
+ name: string;
107
+ } | null;
108
+ team: string | null;
109
+ ip_address: string | null;
110
+ target: {
111
+ type: string;
112
+ id_or_key: string;
113
+ } | null;
114
+ metadata: Record<string, any> | null;
115
+ }
116
+ export interface ActivityLogResult {
117
+ entries: ActivityLogEntry[];
118
+ pagination?: {
119
+ after: string;
120
+ column: string;
121
+ };
122
+ }
123
+ export declare function activityLog(config: AuthConfig, params: {
124
+ org_id?: string;
125
+ emails?: string;
126
+ start_time?: string;
127
+ end_time?: string;
128
+ page_size?: number;
129
+ after?: string;
130
+ }): Promise<ActivityLogResult>;
131
+ export declare function listPayments(config: AuthConfig, params: {
132
+ org_id?: string;
133
+ }): Promise<any[]>;
134
+ export declare function removeOrgMember(config: AuthConfig, params: {
135
+ user_identifier: string;
136
+ org_id?: string;
137
+ confirm?: boolean;
138
+ }): Promise<string>;
139
+ export interface CreateUserGroupResult {
140
+ user_group_id: string;
141
+ add_user_results: any;
142
+ }
143
+ export declare function createUserGroup(config: AuthConfig, params: {
144
+ name: string;
145
+ description?: string;
146
+ team_id?: string;
147
+ plan_id?: string;
148
+ emails?: string[];
149
+ should_notify?: boolean;
150
+ }): Promise<CreateUserGroupResult>;
151
+ export declare function deleteUserGroups(config: AuthConfig, params: {
152
+ user_group_ids: string[];
153
+ }): Promise<string>;
154
+ export declare function addUserGroupMembers(config: AuthConfig, params: {
155
+ user_group_id: string;
156
+ emails: string[];
157
+ }): Promise<any>;
158
+ export declare function removeUserGroupMembers(config: AuthConfig, params: {
159
+ user_group_id: string;
160
+ user_ids: string[];
161
+ }): Promise<string>;
95
162
  //# sourceMappingURL=org.d.ts.map