figmanage 1.0.1 → 1.2.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 (98) hide show
  1. package/README.md +74 -59
  2. package/dist/cli/analytics.d.ts +3 -0
  3. package/dist/cli/analytics.js +48 -0
  4. package/dist/cli/branching.d.ts +3 -0
  5. package/dist/cli/branching.js +56 -0
  6. package/dist/cli/comments.d.ts +3 -0
  7. package/dist/cli/comments.js +86 -0
  8. package/dist/cli/completion.d.ts +7 -0
  9. package/dist/cli/completion.js +160 -0
  10. package/dist/cli/components.d.ts +3 -0
  11. package/dist/cli/components.js +82 -0
  12. package/dist/cli/compound-commands.d.ts +14 -0
  13. package/dist/cli/compound-commands.js +291 -0
  14. package/dist/cli/export.d.ts +3 -0
  15. package/dist/cli/export.js +51 -0
  16. package/dist/cli/files.d.ts +3 -0
  17. package/dist/cli/files.js +156 -0
  18. package/dist/cli/format.js +147 -2
  19. package/dist/cli/helpers.d.ts +7 -0
  20. package/dist/cli/helpers.js +43 -0
  21. package/dist/cli/index.js +68 -89
  22. package/dist/cli/libraries.d.ts +3 -0
  23. package/dist/cli/libraries.js +26 -0
  24. package/dist/cli/navigate.d.ts +3 -0
  25. package/dist/cli/navigate.js +192 -0
  26. package/dist/cli/org.d.ts +3 -0
  27. package/dist/cli/org.js +227 -0
  28. package/dist/cli/permissions.d.ts +3 -0
  29. package/dist/cli/permissions.js +133 -0
  30. package/dist/cli/projects.d.ts +3 -0
  31. package/dist/cli/projects.js +110 -0
  32. package/dist/cli/reading.d.ts +3 -0
  33. package/dist/cli/reading.js +51 -0
  34. package/dist/cli/teams.d.ts +3 -0
  35. package/dist/cli/teams.js +56 -0
  36. package/dist/cli/variables.d.ts +3 -0
  37. package/dist/cli/variables.js +80 -0
  38. package/dist/cli/versions.d.ts +3 -0
  39. package/dist/cli/versions.js +46 -0
  40. package/dist/cli/webhooks.d.ts +3 -0
  41. package/dist/cli/webhooks.js +100 -0
  42. package/dist/operations/analytics.d.ts +10 -0
  43. package/dist/operations/analytics.js +15 -0
  44. package/dist/operations/branching.d.ts +24 -0
  45. package/dist/operations/branching.js +41 -0
  46. package/dist/operations/comments.d.ts +43 -0
  47. package/dist/operations/comments.js +65 -0
  48. package/dist/operations/components.d.ts +24 -0
  49. package/dist/operations/components.js +30 -0
  50. package/dist/operations/compound-manager.d.ts +101 -0
  51. package/dist/operations/compound-manager.js +629 -0
  52. package/dist/operations/compound.d.ts +102 -0
  53. package/dist/operations/compound.js +595 -0
  54. package/dist/operations/export.d.ts +19 -0
  55. package/dist/operations/export.js +27 -0
  56. package/dist/operations/files.d.ts +55 -0
  57. package/dist/operations/files.js +89 -0
  58. package/dist/operations/libraries.d.ts +5 -0
  59. package/dist/operations/libraries.js +10 -0
  60. package/dist/operations/navigate.d.ts +99 -0
  61. package/dist/operations/navigate.js +266 -0
  62. package/dist/operations/org.d.ts +95 -0
  63. package/dist/operations/org.js +205 -0
  64. package/dist/operations/permissions.d.ts +59 -0
  65. package/dist/operations/permissions.js +112 -0
  66. package/dist/operations/projects.d.ts +29 -0
  67. package/dist/operations/projects.js +40 -0
  68. package/dist/operations/reading.d.ts +12 -0
  69. package/dist/operations/reading.js +20 -0
  70. package/dist/operations/teams.d.ts +17 -0
  71. package/dist/operations/teams.js +17 -0
  72. package/dist/operations/variables.d.ts +17 -0
  73. package/dist/operations/variables.js +39 -0
  74. package/dist/operations/versions.d.ts +23 -0
  75. package/dist/operations/versions.js +27 -0
  76. package/dist/operations/webhooks.d.ts +25 -0
  77. package/dist/operations/webhooks.js +38 -0
  78. package/dist/tools/analytics.js +6 -16
  79. package/dist/tools/branching.js +7 -36
  80. package/dist/tools/comments.js +9 -56
  81. package/dist/tools/components.js +7 -19
  82. package/dist/tools/compound-manager.js +21 -644
  83. package/dist/tools/compound.js +32 -566
  84. package/dist/tools/export.js +4 -23
  85. package/dist/tools/files.js +21 -68
  86. package/dist/tools/libraries.js +4 -11
  87. package/dist/tools/navigate.js +23 -246
  88. package/dist/tools/org.js +29 -245
  89. package/dist/tools/permissions.js +18 -97
  90. package/dist/tools/projects.js +8 -27
  91. package/dist/tools/reading.js +5 -15
  92. package/dist/tools/teams.js +8 -16
  93. package/dist/tools/variables.js +13 -30
  94. package/dist/tools/versions.js +6 -24
  95. package/dist/tools/webhooks.js +7 -24
  96. package/package.json +1 -1
  97. package/dist/cli/commands.d.ts +0 -47
  98. package/dist/cli/commands.js +0 -1204
@@ -0,0 +1,82 @@
1
+ import { Command } from 'commander';
2
+ import { listFileComponents, listFileStyles, listTeamComponents, listTeamStyles, } from '../operations/components.js';
3
+ import { output, error } from './format.js';
4
+ import { requirePat } from './helpers.js';
5
+ export function componentsCommand() {
6
+ const components = new Command('components')
7
+ .description('Manage components and styles');
8
+ components
9
+ .command('list-file-components <file-key>')
10
+ .description('List components published from a specific file')
11
+ .option('--json', 'Force JSON output')
12
+ .action(async (fileKey, options) => {
13
+ try {
14
+ const config = requirePat();
15
+ const result = await listFileComponents(config, { file_key: fileKey });
16
+ output(result, options);
17
+ }
18
+ catch (e) {
19
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
20
+ process.exit(1);
21
+ }
22
+ });
23
+ components
24
+ .command('list-file-styles <file-key>')
25
+ .description('List styles in a specific file')
26
+ .option('--json', 'Force JSON output')
27
+ .action(async (fileKey, options) => {
28
+ try {
29
+ const config = requirePat();
30
+ const result = await listFileStyles(config, { file_key: fileKey });
31
+ output(result, options);
32
+ }
33
+ catch (e) {
34
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
35
+ process.exit(1);
36
+ }
37
+ });
38
+ components
39
+ .command('list-team-components <team-id>')
40
+ .description('List published components across a team')
41
+ .option('--page-size <n>', 'Max items per page (default: 30)')
42
+ .option('--cursor <cursor>', 'Pagination cursor from previous response')
43
+ .option('--json', 'Force JSON output')
44
+ .action(async (teamId, options) => {
45
+ try {
46
+ const config = requirePat();
47
+ const result = await listTeamComponents(config, {
48
+ team_id: teamId,
49
+ page_size: options.pageSize ? parseInt(options.pageSize, 10) : undefined,
50
+ cursor: options.cursor,
51
+ });
52
+ output(result, options);
53
+ }
54
+ catch (e) {
55
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
56
+ process.exit(1);
57
+ }
58
+ });
59
+ components
60
+ .command('list-team-styles <team-id>')
61
+ .description('List published styles across a team')
62
+ .option('--page-size <n>', 'Max items per page (default: 30)')
63
+ .option('--cursor <cursor>', 'Pagination cursor from previous response')
64
+ .option('--json', 'Force JSON output')
65
+ .action(async (teamId, options) => {
66
+ try {
67
+ const config = requirePat();
68
+ const result = await listTeamStyles(config, {
69
+ team_id: teamId,
70
+ page_size: options.pageSize ? parseInt(options.pageSize, 10) : undefined,
71
+ cursor: options.cursor,
72
+ });
73
+ output(result, options);
74
+ }
75
+ catch (e) {
76
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
77
+ process.exit(1);
78
+ }
79
+ });
80
+ return components;
81
+ }
82
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1,14 @@
1
+ import { Command } from 'commander';
2
+ export declare function fileSummaryCommand(): Command;
3
+ export declare function workspaceOverviewCommand(): Command;
4
+ export declare function openCommentsCommand(): Command;
5
+ export declare function cleanupStaleFilesCommand(): Command;
6
+ export declare function organizeProjectCommand(): Command;
7
+ export declare function setupProjectStructureCommand(): Command;
8
+ export declare function seatOptimizationCommand(): Command;
9
+ export declare function permissionAuditCommand(): Command;
10
+ export declare function branchCleanupCommand(): Command;
11
+ export declare function offboardUserCommand(): Command;
12
+ export declare function onboardUserCommand(): Command;
13
+ export declare function quarterlyReportCommand(): Command;
14
+ //# sourceMappingURL=compound-commands.d.ts.map
@@ -0,0 +1,291 @@
1
+ import { Command } from 'commander';
2
+ import { fileSummary, workspaceOverview, openComments, cleanupStaleFiles, organizeProject, setupProjectStructure, seatOptimization, permissionAudit, branchCleanup, } from '../operations/compound.js';
3
+ import { offboardUser, onboardUser, quarterlyDesignOpsReport, } from '../operations/compound-manager.js';
4
+ import { output, error } from './format.js';
5
+ import { requireAuth, requirePat, requireCookie, validateId, parsePositiveInt } from './helpers.js';
6
+ // -- compound.ts tools --
7
+ export function fileSummaryCommand() {
8
+ return new Command('summary')
9
+ .description('Quick overview of a Figma file')
10
+ .argument('<file-key>', 'File key')
11
+ .option('--json', 'Force JSON output')
12
+ .action(async (fileKey, options) => {
13
+ try {
14
+ validateId(fileKey, 'file key');
15
+ const config = requirePat();
16
+ const result = await fileSummary(config, { file_key: fileKey });
17
+ output(result, options);
18
+ }
19
+ catch (e) {
20
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
21
+ process.exit(1);
22
+ }
23
+ });
24
+ }
25
+ export function workspaceOverviewCommand() {
26
+ return new Command('overview')
27
+ .description('Full org snapshot: teams, seats, and billing')
28
+ .option('--json', 'Force JSON output')
29
+ .action(async (options) => {
30
+ try {
31
+ const config = requireCookie();
32
+ const result = await workspaceOverview(config, {});
33
+ output(result, options);
34
+ }
35
+ catch (e) {
36
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
37
+ process.exit(1);
38
+ }
39
+ });
40
+ }
41
+ export function openCommentsCommand() {
42
+ return new Command('open')
43
+ .description('Aggregated unresolved comments across project files')
44
+ .argument('<project-id>', 'Project ID')
45
+ .option('--json', 'Force JSON output')
46
+ .action(async (projectId, options) => {
47
+ try {
48
+ validateId(projectId, 'project ID');
49
+ const config = requirePat();
50
+ const result = await openComments(config, { project_id: projectId });
51
+ output(result, options);
52
+ }
53
+ catch (e) {
54
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
55
+ process.exit(1);
56
+ }
57
+ });
58
+ }
59
+ export function cleanupStaleFilesCommand() {
60
+ return new Command('cleanup-stale')
61
+ .description('Find and optionally trash stale files in a project')
62
+ .argument('<project-id>', 'Project ID')
63
+ .option('--days-stale <days>', 'Days since last modification', '90')
64
+ .option('--execute', 'Trash stale files (default: dry run)')
65
+ .option('--json', 'Force JSON output')
66
+ .action(async (projectId, options) => {
67
+ try {
68
+ validateId(projectId, 'project ID');
69
+ const config = requireAuth();
70
+ const daysStale = parsePositiveInt(options.daysStale || '90', '--days-stale', 90);
71
+ const result = await cleanupStaleFiles(config, {
72
+ project_id: projectId,
73
+ days_stale: daysStale,
74
+ dry_run: !options.execute,
75
+ });
76
+ output(result, options);
77
+ }
78
+ catch (e) {
79
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
80
+ process.exit(1);
81
+ }
82
+ });
83
+ }
84
+ export function organizeProjectCommand() {
85
+ return new Command('organize')
86
+ .description('Move multiple files into a target project')
87
+ .requiredOption('--files <keys...>', 'File keys to move')
88
+ .requiredOption('--target <project-id>', 'Destination project ID')
89
+ .option('--json', 'Force JSON output')
90
+ .action(async (options) => {
91
+ try {
92
+ for (const key of options.files)
93
+ validateId(key, 'file key');
94
+ validateId(options.target, 'target project ID');
95
+ const config = requireCookie();
96
+ const result = await organizeProject(config, {
97
+ file_keys: options.files,
98
+ target_project_id: options.target,
99
+ });
100
+ output(result, options);
101
+ }
102
+ catch (e) {
103
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
104
+ process.exit(1);
105
+ }
106
+ });
107
+ }
108
+ export function setupProjectStructureCommand() {
109
+ return new Command('setup-structure')
110
+ .description('Create multiple projects in a team from a JSON plan')
111
+ .argument('<team-id>', 'Team ID')
112
+ .requiredOption('--projects <json>', 'JSON array of {name, description?} objects')
113
+ .option('--json', 'Force JSON output')
114
+ .action(async (teamId, options) => {
115
+ try {
116
+ validateId(teamId, 'team ID');
117
+ let projects;
118
+ try {
119
+ projects = JSON.parse(options.projects);
120
+ }
121
+ catch {
122
+ error('--projects must be valid JSON. Example: \'[{"name":"Design","description":"Main design files"}]\'');
123
+ process.exit(1);
124
+ }
125
+ if (!Array.isArray(projects) || projects.length === 0) {
126
+ error('--projects must be a non-empty array.');
127
+ process.exit(1);
128
+ }
129
+ const config = requireCookie();
130
+ const result = await setupProjectStructure(config, { team_id: teamId, projects });
131
+ output(result, options);
132
+ }
133
+ catch (e) {
134
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
135
+ process.exit(1);
136
+ }
137
+ });
138
+ }
139
+ export function seatOptimizationCommand() {
140
+ return new Command('seat-optimization')
141
+ .description('Identify inactive paid seats and calculate savings')
142
+ .option('--days-inactive <days>', 'Days threshold', '90')
143
+ .option('--no-cost', 'Skip cost analysis')
144
+ .option('--json', 'Force JSON output')
145
+ .action(async (options) => {
146
+ try {
147
+ const config = requireCookie();
148
+ const daysInactive = parsePositiveInt(options.daysInactive || '90', '--days-inactive', 90);
149
+ const result = await seatOptimization(config, {
150
+ days_inactive: daysInactive,
151
+ include_cost: options.cost !== false,
152
+ });
153
+ output(result, options);
154
+ }
155
+ catch (e) {
156
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
157
+ process.exit(1);
158
+ }
159
+ });
160
+ }
161
+ export function permissionAuditCommand() {
162
+ return new Command('audit')
163
+ .description('Audit permissions across a team or project')
164
+ .requiredOption('--scope <type>', 'Scope to audit: team or project', 'team')
165
+ .requiredOption('--id <id>', 'Team ID or project ID')
166
+ .option('--json', 'Force JSON output')
167
+ .action(async (options) => {
168
+ try {
169
+ const scopeType = options.scope;
170
+ if (scopeType !== 'team' && scopeType !== 'project') {
171
+ error(`Invalid scope: ${scopeType}. Must be "team" or "project".`);
172
+ process.exit(1);
173
+ }
174
+ validateId(options.id, 'scope ID');
175
+ const config = requireCookie();
176
+ const result = await permissionAudit(config, {
177
+ scope_type: scopeType,
178
+ scope_id: options.id,
179
+ flag_external: true,
180
+ });
181
+ output(result, options);
182
+ }
183
+ catch (e) {
184
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
185
+ process.exit(1);
186
+ }
187
+ });
188
+ }
189
+ export function branchCleanupCommand() {
190
+ return new Command('cleanup')
191
+ .description('Find and optionally archive stale branches in a project')
192
+ .argument('<project-id>', 'Project ID')
193
+ .option('--days-stale <days>', 'Days threshold', '60')
194
+ .option('--execute', 'Archive stale branches (default: dry run)')
195
+ .option('--json', 'Force JSON output')
196
+ .action(async (projectId, options) => {
197
+ try {
198
+ validateId(projectId, 'project ID');
199
+ const config = requireAuth();
200
+ const daysStale = parsePositiveInt(options.daysStale || '60', '--days-stale', 60);
201
+ const result = await branchCleanup(config, {
202
+ project_id: projectId,
203
+ days_stale: daysStale,
204
+ dry_run: !options.execute,
205
+ });
206
+ output(result, options);
207
+ }
208
+ catch (e) {
209
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
210
+ process.exit(1);
211
+ }
212
+ });
213
+ }
214
+ // -- compound-manager.ts tools --
215
+ export function offboardUserCommand() {
216
+ return new Command('offboard')
217
+ .description('Audit and optionally execute user offboarding')
218
+ .argument('<user>', 'Email or user_id to offboard')
219
+ .option('--execute', 'Execute the offboarding (default: audit only)')
220
+ .option('--transfer-to <user>', 'Email or user_id to transfer file ownership to')
221
+ .option('--json', 'Force JSON output')
222
+ .action(async (user, options) => {
223
+ try {
224
+ const config = requireCookie();
225
+ const result = await offboardUser(config, {
226
+ user_identifier: user,
227
+ execute: options.execute === true,
228
+ transfer_to: options.transferTo,
229
+ });
230
+ output(result, options);
231
+ }
232
+ catch (e) {
233
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
234
+ process.exit(1);
235
+ }
236
+ });
237
+ }
238
+ export function onboardUserCommand() {
239
+ return new Command('onboard')
240
+ .description('Invite a user to teams and optionally share files and set seat type')
241
+ .argument('<email>', 'Email address to invite')
242
+ .requiredOption('--teams <ids...>', 'Team IDs to invite the user to')
243
+ .option('--role <role>', 'Role for team access: editor or viewer', 'editor')
244
+ .option('--share-files <keys...>', 'File keys to share (viewer access)')
245
+ .option('--seat <type>', 'Seat type: full, dev, collab, view')
246
+ .option('--confirm', 'Required to execute seat change')
247
+ .option('--json', 'Force JSON output')
248
+ .action(async (email, options) => {
249
+ try {
250
+ for (const id of options.teams)
251
+ validateId(id, 'team ID');
252
+ if (options.shareFiles) {
253
+ for (const key of options.shareFiles)
254
+ validateId(key, 'file key');
255
+ }
256
+ const config = requireCookie();
257
+ const result = await onboardUser(config, {
258
+ email,
259
+ team_ids: options.teams,
260
+ role: options.role || 'editor',
261
+ share_files: options.shareFiles,
262
+ seat_type: options.seat,
263
+ confirm: options.confirm,
264
+ });
265
+ output(result, options);
266
+ }
267
+ catch (e) {
268
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
269
+ process.exit(1);
270
+ }
271
+ });
272
+ }
273
+ export function quarterlyReportCommand() {
274
+ return new Command('quarterly-report')
275
+ .description('Org-wide design ops report: seats, teams, billing, library adoption')
276
+ .option('--days <days>', 'Lookback period in days', '90')
277
+ .option('--json', 'Force JSON output')
278
+ .action(async (options) => {
279
+ try {
280
+ const config = requireCookie();
281
+ const days = parsePositiveInt(options.days || '90', '--days', 90);
282
+ const result = await quarterlyDesignOpsReport(config, { days });
283
+ output(result, options);
284
+ }
285
+ catch (e) {
286
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
287
+ process.exit(1);
288
+ }
289
+ });
290
+ }
291
+ //# sourceMappingURL=compound-commands.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function exportCommand(): Command;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1,51 @@
1
+ import { Command } from 'commander';
2
+ import { exportNodes, getImageFills } from '../operations/export.js';
3
+ import { output, error } from './format.js';
4
+ import { requirePat } from './helpers.js';
5
+ export function exportCommand() {
6
+ const exp = new Command('export')
7
+ .description('Export images and fills from files');
8
+ exp
9
+ .command('nodes <file-key> <node-ids...>')
10
+ .description('Export nodes as images (returns temporary URLs)')
11
+ .option('--format <fmt>', 'Image format: png, svg, pdf, jpg (default: png)')
12
+ .option('--scale <n>', 'Scale factor, 0.01-4 (default: 1)')
13
+ .option('--json', 'Force JSON output')
14
+ .action(async (fileKey, nodeIds, options) => {
15
+ try {
16
+ const config = requirePat();
17
+ const result = await exportNodes(config, {
18
+ file_key: fileKey,
19
+ node_ids: nodeIds,
20
+ format: options.format,
21
+ scale: options.scale ? parseFloat(options.scale) : undefined,
22
+ });
23
+ output(result, options);
24
+ }
25
+ catch (e) {
26
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
27
+ process.exit(1);
28
+ }
29
+ });
30
+ exp
31
+ .command('image-fills <file-key>')
32
+ .description('Get download URLs for all images used as fills')
33
+ .option('--json', 'Force JSON output')
34
+ .action(async (fileKey, options) => {
35
+ try {
36
+ const config = requirePat();
37
+ const result = await getImageFills(config, { file_key: fileKey });
38
+ if (result.length === 0) {
39
+ console.log('No image fills in this file.');
40
+ return;
41
+ }
42
+ output(result, options);
43
+ }
44
+ catch (e) {
45
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
46
+ process.exit(1);
47
+ }
48
+ });
49
+ return exp;
50
+ }
51
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function filesCommand(): Command;
3
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1,156 @@
1
+ import { Command } from 'commander';
2
+ import { createFile, renameFile, moveFiles, duplicateFile, trashFiles, restoreFiles, favoriteFile, setLinkAccess, } from '../operations/files.js';
3
+ import { output, error } from './format.js';
4
+ import { requireCookie } from './helpers.js';
5
+ export function filesCommand() {
6
+ const files = new Command('files')
7
+ .description('Manage Figma files');
8
+ files
9
+ .command('create <project-id>')
10
+ .description('Create a new file in a project')
11
+ .option('--editor-type <type>', 'File type: design, whiteboard, slides, sites', 'design')
12
+ .option('--org-id <id>', 'Org ID override')
13
+ .option('--json', 'Force JSON output')
14
+ .action(async (projectId, options) => {
15
+ try {
16
+ const config = requireCookie();
17
+ const result = await createFile(config, {
18
+ project_id: projectId,
19
+ editor_type: options.editorType,
20
+ org_id: options.orgId,
21
+ });
22
+ output(result, options);
23
+ }
24
+ catch (e) {
25
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
26
+ process.exit(1);
27
+ }
28
+ });
29
+ files
30
+ .command('rename <file-key>')
31
+ .description('Rename a file')
32
+ .requiredOption('--name <name>', 'New name')
33
+ .option('--json', 'Force JSON output')
34
+ .action(async (fileKey, options) => {
35
+ try {
36
+ const config = requireCookie();
37
+ await renameFile(config, { file_key: fileKey, name: options.name });
38
+ output({ renamed: fileKey, name: options.name }, options);
39
+ }
40
+ catch (e) {
41
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
42
+ process.exit(1);
43
+ }
44
+ });
45
+ files
46
+ .command('move')
47
+ .description('Move files to a different project')
48
+ .requiredOption('--file-keys <keys>', 'Comma-separated file keys', (v) => v.split(','))
49
+ .requiredOption('--destination <project-id>', 'Destination project ID')
50
+ .option('--json', 'Force JSON output')
51
+ .action(async (options) => {
52
+ try {
53
+ const config = requireCookie();
54
+ const result = await moveFiles(config, {
55
+ file_keys: options.fileKeys,
56
+ destination_project_id: options.destination,
57
+ });
58
+ output(result, options);
59
+ }
60
+ catch (e) {
61
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ files
66
+ .command('duplicate <file-key>')
67
+ .description('Duplicate a file')
68
+ .option('--project-id <id>', 'Destination project ID')
69
+ .option('--json', 'Force JSON output')
70
+ .action(async (fileKey, options) => {
71
+ try {
72
+ const config = requireCookie();
73
+ const result = await duplicateFile(config, {
74
+ file_key: fileKey,
75
+ project_id: options.projectId,
76
+ });
77
+ output(result, options);
78
+ }
79
+ catch (e) {
80
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
81
+ process.exit(1);
82
+ }
83
+ });
84
+ files
85
+ .command('trash')
86
+ .description('Move files to trash')
87
+ .requiredOption('--file-keys <keys>', 'Comma-separated file keys', (v) => v.split(','))
88
+ .option('--json', 'Force JSON output')
89
+ .action(async (options) => {
90
+ try {
91
+ const config = requireCookie();
92
+ const result = await trashFiles(config, { file_keys: options.fileKeys });
93
+ output(result, options);
94
+ }
95
+ catch (e) {
96
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ files
101
+ .command('restore')
102
+ .description('Restore files from trash')
103
+ .requiredOption('--file-keys <keys>', 'Comma-separated file keys', (v) => v.split(','))
104
+ .option('--json', 'Force JSON output')
105
+ .action(async (options) => {
106
+ try {
107
+ const config = requireCookie();
108
+ const result = await restoreFiles(config, { file_keys: options.fileKeys });
109
+ output(result, options);
110
+ }
111
+ catch (e) {
112
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
113
+ process.exit(1);
114
+ }
115
+ });
116
+ files
117
+ .command('favorite <file-key>')
118
+ .description('Add or remove a file from favorites')
119
+ .option('--unfavorite', 'Remove from favorites')
120
+ .option('--json', 'Force JSON output')
121
+ .action(async (fileKey, options) => {
122
+ try {
123
+ const config = requireCookie();
124
+ const result = await favoriteFile(config, {
125
+ file_key: fileKey,
126
+ favorited: !options.unfavorite,
127
+ });
128
+ output(result, options);
129
+ }
130
+ catch (e) {
131
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
132
+ process.exit(1);
133
+ }
134
+ });
135
+ files
136
+ .command('link-access <file-key>')
137
+ .description('Set link access on a file')
138
+ .option('--level <level>', 'Access level: inherit, view, edit, org_view, org_edit', 'inherit')
139
+ .option('--json', 'Force JSON output')
140
+ .action(async (fileKey, options) => {
141
+ try {
142
+ const config = requireCookie();
143
+ const result = await setLinkAccess(config, {
144
+ file_key: fileKey,
145
+ link_access: options.level,
146
+ });
147
+ output(result, options);
148
+ }
149
+ catch (e) {
150
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
151
+ process.exit(1);
152
+ }
153
+ });
154
+ return files;
155
+ }
156
+ //# sourceMappingURL=files.js.map