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.
- package/README.md +74 -59
- package/dist/cli/analytics.d.ts +3 -0
- package/dist/cli/analytics.js +48 -0
- package/dist/cli/branching.d.ts +3 -0
- package/dist/cli/branching.js +56 -0
- package/dist/cli/comments.d.ts +3 -0
- package/dist/cli/comments.js +86 -0
- package/dist/cli/completion.d.ts +7 -0
- package/dist/cli/completion.js +160 -0
- package/dist/cli/components.d.ts +3 -0
- package/dist/cli/components.js +82 -0
- package/dist/cli/compound-commands.d.ts +14 -0
- package/dist/cli/compound-commands.js +291 -0
- package/dist/cli/export.d.ts +3 -0
- package/dist/cli/export.js +51 -0
- package/dist/cli/files.d.ts +3 -0
- package/dist/cli/files.js +156 -0
- package/dist/cli/format.js +147 -2
- package/dist/cli/helpers.d.ts +7 -0
- package/dist/cli/helpers.js +43 -0
- package/dist/cli/index.js +68 -89
- package/dist/cli/libraries.d.ts +3 -0
- package/dist/cli/libraries.js +26 -0
- package/dist/cli/navigate.d.ts +3 -0
- package/dist/cli/navigate.js +192 -0
- package/dist/cli/org.d.ts +3 -0
- package/dist/cli/org.js +227 -0
- package/dist/cli/permissions.d.ts +3 -0
- package/dist/cli/permissions.js +133 -0
- package/dist/cli/projects.d.ts +3 -0
- package/dist/cli/projects.js +110 -0
- package/dist/cli/reading.d.ts +3 -0
- package/dist/cli/reading.js +51 -0
- package/dist/cli/teams.d.ts +3 -0
- package/dist/cli/teams.js +56 -0
- package/dist/cli/variables.d.ts +3 -0
- package/dist/cli/variables.js +80 -0
- package/dist/cli/versions.d.ts +3 -0
- package/dist/cli/versions.js +46 -0
- package/dist/cli/webhooks.d.ts +3 -0
- package/dist/cli/webhooks.js +100 -0
- package/dist/operations/analytics.d.ts +10 -0
- package/dist/operations/analytics.js +15 -0
- package/dist/operations/branching.d.ts +24 -0
- package/dist/operations/branching.js +41 -0
- package/dist/operations/comments.d.ts +43 -0
- package/dist/operations/comments.js +65 -0
- package/dist/operations/components.d.ts +24 -0
- package/dist/operations/components.js +30 -0
- package/dist/operations/compound-manager.d.ts +101 -0
- package/dist/operations/compound-manager.js +629 -0
- package/dist/operations/compound.d.ts +102 -0
- package/dist/operations/compound.js +595 -0
- package/dist/operations/export.d.ts +19 -0
- package/dist/operations/export.js +27 -0
- package/dist/operations/files.d.ts +55 -0
- package/dist/operations/files.js +89 -0
- package/dist/operations/libraries.d.ts +5 -0
- package/dist/operations/libraries.js +10 -0
- package/dist/operations/navigate.d.ts +99 -0
- package/dist/operations/navigate.js +266 -0
- package/dist/operations/org.d.ts +95 -0
- package/dist/operations/org.js +205 -0
- package/dist/operations/permissions.d.ts +59 -0
- package/dist/operations/permissions.js +112 -0
- package/dist/operations/projects.d.ts +29 -0
- package/dist/operations/projects.js +40 -0
- package/dist/operations/reading.d.ts +12 -0
- package/dist/operations/reading.js +20 -0
- package/dist/operations/teams.d.ts +17 -0
- package/dist/operations/teams.js +17 -0
- package/dist/operations/variables.d.ts +17 -0
- package/dist/operations/variables.js +39 -0
- package/dist/operations/versions.d.ts +23 -0
- package/dist/operations/versions.js +27 -0
- package/dist/operations/webhooks.d.ts +25 -0
- package/dist/operations/webhooks.js +38 -0
- package/dist/tools/analytics.js +6 -16
- package/dist/tools/branching.js +7 -36
- package/dist/tools/comments.js +9 -56
- package/dist/tools/components.js +7 -19
- package/dist/tools/compound-manager.js +21 -644
- package/dist/tools/compound.js +32 -566
- package/dist/tools/export.js +4 -23
- package/dist/tools/files.js +21 -68
- package/dist/tools/libraries.js +4 -11
- package/dist/tools/navigate.js +23 -246
- package/dist/tools/org.js +29 -245
- package/dist/tools/permissions.js +18 -97
- package/dist/tools/projects.js +8 -27
- package/dist/tools/reading.js +5 -15
- package/dist/tools/teams.js +8 -16
- package/dist/tools/variables.js +13 -30
- package/dist/tools/versions.js +6 -24
- package/dist/tools/webhooks.js +7 -24
- package/package.json +1 -1
- package/dist/cli/commands.d.ts +0 -47
- package/dist/cli/commands.js +0 -1204
package/dist/cli/format.js
CHANGED
|
@@ -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
|
-
//
|
|
11
|
-
|
|
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
|
|
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
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
program
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
program
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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,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,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
|