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
@@ -2,13 +2,158 @@
2
2
  export function isTTY() {
3
3
  return process.stdout.isTTY === true;
4
4
  }
5
+ /** Get terminal width, defaulting to 80 if unavailable */
6
+ function termWidth() {
7
+ return process.stdout.columns || 80;
8
+ }
9
+ /** Format a value for display in a table cell */
10
+ function formatCell(value) {
11
+ if (value === null || value === undefined)
12
+ return '';
13
+ if (typeof value === 'string')
14
+ return value;
15
+ if (typeof value === 'number' || typeof value === 'boolean')
16
+ return String(value);
17
+ if (Array.isArray(value))
18
+ return `[${value.length} items]`;
19
+ if (typeof value === 'object')
20
+ return '{...}';
21
+ return String(value);
22
+ }
23
+ /** Truncate a string to maxLen, appending ... if truncated */
24
+ function truncate(str, maxLen) {
25
+ if (maxLen < 4)
26
+ return str.slice(0, maxLen);
27
+ if (str.length <= maxLen)
28
+ return str;
29
+ return str.slice(0, maxLen - 3) + '...';
30
+ }
31
+ /** Pad a string to the right with spaces */
32
+ function padRight(str, width) {
33
+ if (str.length >= width)
34
+ return str;
35
+ return str + ' '.repeat(width - str.length);
36
+ }
37
+ /**
38
+ * Render an array of objects as an aligned table.
39
+ * Columns are auto-sized to content, then shrunk proportionally if they
40
+ * exceed terminal width. A minimum gap of 2 spaces separates columns.
41
+ */
42
+ function formatTable(rows) {
43
+ if (rows.length === 0)
44
+ return '';
45
+ // Collect all keys across all rows (preserving insertion order)
46
+ const keySet = new Set();
47
+ for (const row of rows) {
48
+ for (const key of Object.keys(row)) {
49
+ keySet.add(key);
50
+ }
51
+ }
52
+ const keys = Array.from(keySet);
53
+ // Build string grid: headers + data
54
+ const headers = keys.map((k) => k.toUpperCase());
55
+ const grid = rows.map((row) => keys.map((k) => formatCell(row[k])));
56
+ // Compute natural column widths (max of header and all data cells)
57
+ const colWidths = keys.map((_, i) => {
58
+ let max = headers[i].length;
59
+ for (const row of grid) {
60
+ if (row[i].length > max)
61
+ max = row[i].length;
62
+ }
63
+ return max;
64
+ });
65
+ const gap = 2;
66
+ const maxWidth = termWidth();
67
+ const totalGap = gap * (keys.length - 1);
68
+ const totalNatural = colWidths.reduce((a, b) => a + b, 0) + totalGap;
69
+ // If columns exceed terminal width, shrink the widest columns first
70
+ if (totalNatural > maxWidth && keys.length > 0) {
71
+ const budget = maxWidth - totalGap;
72
+ if (budget > 0) {
73
+ // Give each column at least 4 chars, distribute remaining proportionally
74
+ const minCol = 4;
75
+ const guaranteed = Math.min(minCol, Math.floor(budget / keys.length));
76
+ let remaining = budget;
77
+ // First pass: cap each column to its natural width or proportional share
78
+ const totalContent = colWidths.reduce((a, b) => a + b, 0);
79
+ for (let i = 0; i < colWidths.length; i++) {
80
+ const share = Math.max(guaranteed, Math.floor((colWidths[i] / totalContent) * budget));
81
+ colWidths[i] = Math.min(colWidths[i], share);
82
+ remaining -= colWidths[i];
83
+ }
84
+ // Distribute leftover to columns that were truncated
85
+ if (remaining > 0) {
86
+ for (let i = 0; i < colWidths.length && remaining > 0; i++) {
87
+ const natural = headers[i].length;
88
+ const canGrow = Math.max(0, natural - colWidths[i]);
89
+ const give = Math.min(canGrow, remaining);
90
+ colWidths[i] += give;
91
+ remaining -= give;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ // Render rows
97
+ const lines = [];
98
+ // Header row
99
+ const headerLine = keys
100
+ .map((_, i) => padRight(truncate(headers[i], colWidths[i]), colWidths[i]))
101
+ .join(' '.repeat(gap));
102
+ lines.push(headerLine.trimEnd());
103
+ // Data rows
104
+ for (const row of grid) {
105
+ const line = keys
106
+ .map((_, i) => padRight(truncate(row[i], colWidths[i]), colWidths[i]))
107
+ .join(' '.repeat(gap));
108
+ lines.push(line.trimEnd());
109
+ }
110
+ return lines.join('\n');
111
+ }
112
+ /**
113
+ * Render a single object as key-value pairs.
114
+ * Falls back to JSON for deeply nested objects.
115
+ */
116
+ function formatKeyValue(obj) {
117
+ // If every value is a nested object/array, this won't be readable as k/v.
118
+ // Check if the majority of values are complex -- if so, fall back to JSON.
119
+ const values = Object.values(obj);
120
+ const complexCount = values.filter((v) => v !== null && typeof v === 'object').length;
121
+ if (complexCount > values.length / 2) {
122
+ return JSON.stringify(obj, null, 2);
123
+ }
124
+ const entries = Object.entries(obj);
125
+ if (entries.length === 0)
126
+ return '{}';
127
+ return entries.map(([key, val]) => `${key}: ${formatCell(val)}`).join('\n');
128
+ }
5
129
  /** Format output: JSON if piped or --json flag, human-readable if TTY */
6
130
  export function formatOutput(data, options) {
7
131
  if (options.json || !isTTY()) {
8
132
  return JSON.stringify(data, null, 2);
9
133
  }
10
- // Table formatting will be added later; fall back to JSON for now
11
- return JSON.stringify(data, null, 2);
134
+ // Primitives: render as-is
135
+ if (data === null || data === undefined)
136
+ return '';
137
+ if (typeof data === 'string')
138
+ return data;
139
+ if (typeof data === 'number' || typeof data === 'boolean')
140
+ return String(data);
141
+ // Array of objects: table
142
+ if (Array.isArray(data)) {
143
+ if (data.length === 0)
144
+ return '';
145
+ // If every element is a plain object, render as table
146
+ if (data.every((item) => item !== null && typeof item === 'object' && !Array.isArray(item))) {
147
+ return formatTable(data);
148
+ }
149
+ // Array of primitives or mixed: one per line
150
+ return data.map((item) => formatCell(item)).join('\n');
151
+ }
152
+ // Single object
153
+ if (typeof data === 'object') {
154
+ return formatKeyValue(data);
155
+ }
156
+ return String(data);
12
157
  }
13
158
  /** Print formatted output to stdout */
14
159
  export function output(data, options = {}) {
@@ -0,0 +1,7 @@
1
+ import { type AuthConfig } from '../auth/client.js';
2
+ export declare function validateId(value: string, label: string): string;
3
+ export declare function parsePositiveInt(value: string, label: string, fallback: number): number;
4
+ export declare function requireAuth(): AuthConfig;
5
+ export declare function requirePat(): AuthConfig;
6
+ export declare function requireCookie(): AuthConfig;
7
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { loadAuthConfig, hasPat, hasCookie } from '../auth/client.js';
2
+ import { error } from './format.js';
3
+ const ID_PATTERN = /^[\w.:-]+$/;
4
+ export function validateId(value, label) {
5
+ if (!ID_PATTERN.test(value)) {
6
+ error(`Invalid ${label}: must contain only letters, numbers, hyphens, underscores, dots, or colons.`);
7
+ process.exit(1);
8
+ }
9
+ return value;
10
+ }
11
+ export function parsePositiveInt(value, label, fallback) {
12
+ const n = parseInt(value, 10);
13
+ if (isNaN(n) || n < 1) {
14
+ error(`${label} must be a positive number.`);
15
+ process.exit(1);
16
+ }
17
+ return n;
18
+ }
19
+ export function requireAuth() {
20
+ const config = loadAuthConfig();
21
+ if (!hasPat(config) && !hasCookie(config)) {
22
+ error('Not authenticated. Run `figmanage login` first.');
23
+ process.exit(1);
24
+ }
25
+ return config;
26
+ }
27
+ export function requirePat() {
28
+ const config = loadAuthConfig();
29
+ if (!hasPat(config)) {
30
+ error('This command requires a Personal Access Token. Run `figmanage login` first.');
31
+ process.exit(1);
32
+ }
33
+ return config;
34
+ }
35
+ export function requireCookie() {
36
+ const config = loadAuthConfig();
37
+ if (!hasCookie(config)) {
38
+ error('This command requires cookie auth. Run `figmanage login` (not --pat-only).');
39
+ process.exit(1);
40
+ }
41
+ return config;
42
+ }
43
+ //# sourceMappingURL=helpers.js.map
package/dist/cli/index.js CHANGED
@@ -1,5 +1,23 @@
1
+ import { navigateCommand } from './navigate.js';
2
+ import { filesCommand } from './files.js';
3
+ import { projectsCommand } from './projects.js';
4
+ import { permissionsCommand } from './permissions.js';
5
+ import { versionsCommand } from './versions.js';
6
+ import { branchingCommand } from './branching.js';
7
+ import { commentsCommand } from './comments.js';
8
+ import { exportCommand } from './export.js';
9
+ import { readingCommand } from './reading.js';
10
+ import { componentsCommand } from './components.js';
11
+ import { webhooksCommand } from './webhooks.js';
12
+ import { variablesCommand } from './variables.js';
13
+ import { analyticsCommand } from './analytics.js';
14
+ import { orgCommand } from './org.js';
15
+ import { librariesCommand } from './libraries.js';
16
+ import { teamsCommand } from './teams.js';
17
+ import { completionCommand } from './completion.js';
18
+ import { fileSummaryCommand, workspaceOverviewCommand, openCommentsCommand, cleanupStaleFilesCommand, organizeProjectCommand, setupProjectStructureCommand, seatOptimizationCommand, permissionAuditCommand, branchCleanupCommand, offboardUserCommand, onboardUserCommand, quarterlyReportCommand, } from './compound-commands.js';
1
19
  export function registerCliCommands(program) {
2
- // Auth commands -- handlers live in cli/login.ts (built by another agent)
20
+ // Auth commands (flat -- not resource-scoped)
3
21
  program
4
22
  .command('login')
5
23
  .description('Authenticate with Figma')
@@ -23,93 +41,54 @@ export function registerCliCommands(program) {
23
41
  const { handleLogout } = await import('./login.js');
24
42
  await handleLogout();
25
43
  });
26
- // Workspace management commands
27
- program
28
- .command('seat-optimization')
29
- .description('Identify inactive paid seats and calculate savings')
30
- .option('--days-inactive <days>', 'Days threshold (default: 90)', '90')
31
- .option('--no-cost', 'Skip cost analysis')
32
- .option('--json', 'Force JSON output')
33
- .action(async (options) => {
34
- const { runSeatOptimization } = await import('./commands.js');
35
- await runSeatOptimization(options);
36
- });
37
- program
38
- .command('offboard <user>')
39
- .description('Audit or execute user offboarding')
40
- .option('--execute', 'Execute the offboarding (default: audit only)')
41
- .option('--transfer-to <user>', 'Transfer file ownership to this user')
42
- .option('--json', 'Force JSON output')
43
- .action(async (user, options) => {
44
- const { runOffboard } = await import('./commands.js');
45
- await runOffboard(user, options);
46
- });
47
- program
48
- .command('onboard <email>')
49
- .description('Invite user to teams and set up access')
50
- .option('--teams <ids>', 'Comma-separated team IDs', (v) => v.split(','))
51
- .option('--role <role>', 'Role: editor or viewer (default: editor)', 'editor')
52
- .option('--share-files <keys>', 'Comma-separated file keys to share (viewer access)', (v) => v.split(','))
53
- .option('--seat <type>', 'Seat type: full, dev, collab, view')
54
- .option('--confirm', 'Confirm seat change')
55
- .option('--json', 'Force JSON output')
56
- .action(async (email, options) => {
57
- const { runOnboard } = await import('./commands.js');
58
- await runOnboard(email, options);
59
- });
60
- program
61
- .command('quarterly-report')
62
- .description('Org-wide design ops snapshot')
63
- .option('--days <days>', 'Lookback period (default: 90)', '90')
64
- .option('--json', 'Force JSON output')
65
- .action(async (options) => {
66
- const { runQuarterlyReport } = await import('./commands.js');
67
- await runQuarterlyReport(options);
68
- });
69
- program
70
- .command('members')
71
- .description('List org members')
72
- .option('--search <query>', 'Filter by name or email')
73
- .option('--json', 'Force JSON output')
74
- .action(async (options) => {
75
- const { runMembers } = await import('./commands.js');
76
- await runMembers(options);
77
- });
78
- program
79
- .command('teams')
80
- .description('List org teams')
81
- .option('--json', 'Force JSON output')
82
- .action(async (options) => {
83
- const { runTeams } = await import('./commands.js');
84
- await runTeams(options);
85
- });
86
- program
87
- .command('permissions <type> <id>')
88
- .description('Show who has access to a file, project, or team')
89
- .option('--json', 'Force JSON output')
90
- .action(async (type, id, options) => {
91
- const { runPermissions } = await import('./commands.js');
92
- await runPermissions(type, id, options);
93
- });
94
- program
95
- .command('permission-audit')
96
- .description('Audit permissions across a team or project')
97
- .option('--scope <type>', 'Scope: team or project', 'team')
98
- .option('--id <id>', 'Team or project ID')
99
- .option('--json', 'Force JSON output')
100
- .action(async (options) => {
101
- const { runPermissionAudit } = await import('./commands.js');
102
- await runPermissionAudit(options);
103
- });
104
- program
105
- .command('branch-cleanup <project-id>')
106
- .description('Find and optionally archive stale branches')
107
- .option('--days-stale <days>', 'Days threshold (default: 60)', '60')
108
- .option('--execute', 'Archive stale branches (default: dry run)')
109
- .option('--json', 'Force JSON output')
110
- .action(async (projectId, options) => {
111
- const { runBranchCleanup } = await import('./commands.js');
112
- await runBranchCleanup(projectId, options);
113
- });
44
+ // Noun-verb subcommand groups
45
+ const navigate = navigateCommand();
46
+ const files = filesCommand();
47
+ const projects = projectsCommand();
48
+ const permissions = permissionsCommand();
49
+ const versions = versionsCommand();
50
+ const branches = branchingCommand();
51
+ const comments = commentsCommand();
52
+ const exp = exportCommand();
53
+ const reading = readingCommand();
54
+ const components = componentsCommand();
55
+ const webhooks = webhooksCommand();
56
+ const variables = variablesCommand();
57
+ const analytics = analyticsCommand();
58
+ const org = orgCommand();
59
+ const libraries = librariesCommand();
60
+ const teams = teamsCommand();
61
+ // Route compound commands into noun groups
62
+ files.addCommand(fileSummaryCommand());
63
+ files.addCommand(cleanupStaleFilesCommand());
64
+ projects.addCommand(organizeProjectCommand());
65
+ projects.addCommand(setupProjectStructureCommand());
66
+ comments.addCommand(openCommentsCommand());
67
+ permissions.addCommand(permissionAuditCommand());
68
+ branches.addCommand(branchCleanupCommand());
69
+ org.addCommand(workspaceOverviewCommand());
70
+ org.addCommand(seatOptimizationCommand());
71
+ org.addCommand(offboardUserCommand());
72
+ org.addCommand(onboardUserCommand());
73
+ org.addCommand(quarterlyReportCommand());
74
+ // Register all groups
75
+ program.addCommand(navigate);
76
+ program.addCommand(files);
77
+ program.addCommand(projects);
78
+ program.addCommand(permissions);
79
+ program.addCommand(versions);
80
+ program.addCommand(branches);
81
+ program.addCommand(comments);
82
+ program.addCommand(exp);
83
+ program.addCommand(reading);
84
+ program.addCommand(components);
85
+ program.addCommand(webhooks);
86
+ program.addCommand(variables);
87
+ program.addCommand(analytics);
88
+ program.addCommand(org);
89
+ program.addCommand(libraries);
90
+ program.addCommand(teams);
91
+ // Completion must be registered last so it can introspect all commands above
92
+ program.addCommand(completionCommand(program));
114
93
  }
115
94
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function librariesCommand(): Command;
3
+ //# sourceMappingURL=libraries.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { Command } from 'commander';
2
+ import { listOrgLibraries } from '../operations/libraries.js';
3
+ import { output, error } from './format.js';
4
+ import { requireCookie } from './helpers.js';
5
+ export function librariesCommand() {
6
+ const libraries = new Command('libraries')
7
+ .description('Manage org design system libraries');
8
+ libraries
9
+ .command('list')
10
+ .description('List all design system libraries in the org')
11
+ .option('--org-id <id>', 'Org ID override (defaults to current workspace)')
12
+ .option('--json', 'Force JSON output')
13
+ .action(async (options) => {
14
+ try {
15
+ const config = requireCookie();
16
+ const result = await listOrgLibraries(config, { org_id: options.orgId });
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
+ return libraries;
25
+ }
26
+ //# sourceMappingURL=libraries.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function navigateCommand(): Command;
3
+ //# sourceMappingURL=navigate.d.ts.map
@@ -0,0 +1,192 @@
1
+ import { Command } from 'commander';
2
+ import { checkAuthStatus, listOrgs, switchOrg, listTeams, listProjects, listFiles, listRecentFiles, search, getFileInfo, listFavorites, } from '../operations/navigate.js';
3
+ import { output, error } from './format.js';
4
+ import { requireAuth, requireCookie } from './helpers.js';
5
+ export function navigateCommand() {
6
+ const nav = new Command('navigate')
7
+ .description('Browse workspaces, teams, projects, and files');
8
+ nav
9
+ .command('check-auth')
10
+ .description('Check authentication status for PAT and session cookie')
11
+ .option('--json', 'Force JSON output')
12
+ .action(async (options) => {
13
+ try {
14
+ const config = requireAuth();
15
+ const result = await checkAuthStatus(config);
16
+ if (options.json) {
17
+ output(result.status, options);
18
+ }
19
+ else {
20
+ console.log(result.formatted);
21
+ }
22
+ }
23
+ catch (e) {
24
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
25
+ process.exit(1);
26
+ }
27
+ });
28
+ nav
29
+ .command('list-orgs')
30
+ .description('List all workspaces you belong to')
31
+ .option('--json', 'Force JSON output')
32
+ .action(async (options) => {
33
+ try {
34
+ const config = requireCookie();
35
+ const orgs = await listOrgs(config);
36
+ if (orgs.length === 0) {
37
+ console.log('No workspaces found. You may be on a free/starter plan.');
38
+ return;
39
+ }
40
+ output(orgs, options);
41
+ }
42
+ catch (e) {
43
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
44
+ process.exit(1);
45
+ }
46
+ });
47
+ nav
48
+ .command('switch-org <org>')
49
+ .description('Switch active workspace (name or ID)')
50
+ .option('--json', 'Force JSON output')
51
+ .action(async (org, options) => {
52
+ try {
53
+ const config = requireCookie();
54
+ const result = await switchOrg(config, { org });
55
+ output({
56
+ previous: result.previous,
57
+ current: result.current,
58
+ }, options);
59
+ }
60
+ catch (e) {
61
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ nav
66
+ .command('list-teams')
67
+ .description('List all teams you belong to')
68
+ .option('--json', 'Force JSON output')
69
+ .action(async (options) => {
70
+ try {
71
+ const config = requireCookie();
72
+ const teams = await listTeams(config);
73
+ output(teams, options);
74
+ }
75
+ catch (e) {
76
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
77
+ process.exit(1);
78
+ }
79
+ });
80
+ nav
81
+ .command('list-projects <team-id>')
82
+ .description('List projects (folders) in a team')
83
+ .option('--json', 'Force JSON output')
84
+ .action(async (teamId, options) => {
85
+ try {
86
+ const config = requireAuth();
87
+ const projects = await listProjects(config, { team_id: teamId });
88
+ output(projects, options);
89
+ }
90
+ catch (e) {
91
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
92
+ process.exit(1);
93
+ }
94
+ });
95
+ nav
96
+ .command('list-files <project-id>')
97
+ .description('List files in a project')
98
+ .option('--page-size <n>', 'Results per page (default 25, max 100)')
99
+ .option('--page-token <token>', 'Pagination token from previous response')
100
+ .option('--json', 'Force JSON output')
101
+ .action(async (projectId, options) => {
102
+ try {
103
+ const config = requireAuth();
104
+ const result = await listFiles(config, {
105
+ project_id: projectId,
106
+ page_size: options.pageSize ? parseInt(options.pageSize, 10) : undefined,
107
+ page_token: options.pageToken,
108
+ });
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
+ nav
117
+ .command('list-recent-files')
118
+ .description('List recently viewed/edited files')
119
+ .option('--json', 'Force JSON output')
120
+ .action(async (options) => {
121
+ try {
122
+ const config = requireCookie();
123
+ const files = await listRecentFiles(config);
124
+ output(files, options);
125
+ }
126
+ catch (e) {
127
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
128
+ process.exit(1);
129
+ }
130
+ });
131
+ nav
132
+ .command('search <query>')
133
+ .description('Search for files across the workspace')
134
+ .option('--sort <order>', 'Sort order: relevancy or last_modified')
135
+ .option('--org-id <id>', 'Org ID override')
136
+ .option('--json', 'Force JSON output')
137
+ .action(async (query, options) => {
138
+ try {
139
+ const config = requireCookie();
140
+ const results = await search(config, {
141
+ query,
142
+ sort: options.sort,
143
+ org_id: options.orgId,
144
+ });
145
+ if (results.length === 0) {
146
+ console.log('No results found.');
147
+ return;
148
+ }
149
+ output(results, options);
150
+ }
151
+ catch (e) {
152
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
153
+ process.exit(1);
154
+ }
155
+ });
156
+ nav
157
+ .command('file-info <file-key>')
158
+ .description('Get metadata for a file')
159
+ .option('--json', 'Force JSON output')
160
+ .action(async (fileKey, options) => {
161
+ try {
162
+ const config = requireAuth();
163
+ const info = await getFileInfo(config, { file_key: fileKey });
164
+ output(info, options);
165
+ }
166
+ catch (e) {
167
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
168
+ process.exit(1);
169
+ }
170
+ });
171
+ nav
172
+ .command('list-favorites')
173
+ .description('List starred/favorited files')
174
+ .option('--json', 'Force JSON output')
175
+ .action(async (options) => {
176
+ try {
177
+ const config = requireCookie();
178
+ const favorites = await listFavorites(config);
179
+ if (favorites.length === 0) {
180
+ console.log('No favorites found.');
181
+ return;
182
+ }
183
+ output(favorites, options);
184
+ }
185
+ catch (e) {
186
+ error(e.response?.status ? `API error: ${e.response.status}` : e.message);
187
+ process.exit(1);
188
+ }
189
+ });
190
+ return nav;
191
+ }
192
+ //# sourceMappingURL=navigate.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function orgCommand(): Command;
3
+ //# sourceMappingURL=org.d.ts.map