@contextium/cli 0.3.2 → 0.6.7

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 (77) hide show
  1. package/README.md +227 -227
  2. package/dist/commands/agents.d.ts +3 -0
  3. package/dist/commands/agents.d.ts.map +1 -0
  4. package/dist/commands/agents.js +243 -0
  5. package/dist/commands/agents.js.map +1 -0
  6. package/dist/commands/cat.d.ts.map +1 -1
  7. package/dist/commands/cat.js +13 -9
  8. package/dist/commands/cat.js.map +1 -1
  9. package/dist/commands/create-library.d.ts +3 -0
  10. package/dist/commands/create-library.d.ts.map +1 -0
  11. package/dist/commands/create-library.js +49 -0
  12. package/dist/commands/create-library.js.map +1 -0
  13. package/dist/commands/delete-file.d.ts +3 -0
  14. package/dist/commands/delete-file.d.ts.map +1 -0
  15. package/dist/commands/delete-file.js +39 -0
  16. package/dist/commands/delete-file.js.map +1 -0
  17. package/dist/commands/edit-file.d.ts +3 -0
  18. package/dist/commands/edit-file.d.ts.map +1 -0
  19. package/dist/commands/edit-file.js +64 -0
  20. package/dist/commands/edit-file.js.map +1 -0
  21. package/dist/commands/files.d.ts.map +1 -1
  22. package/dist/commands/files.js +5 -4
  23. package/dist/commands/files.js.map +1 -1
  24. package/dist/commands/find.d.ts.map +1 -1
  25. package/dist/commands/find.js +2 -1
  26. package/dist/commands/find.js.map +1 -1
  27. package/dist/commands/init.js +2 -2
  28. package/dist/commands/init.js.map +1 -1
  29. package/dist/commands/new-file.d.ts +3 -0
  30. package/dist/commands/new-file.d.ts.map +1 -0
  31. package/dist/commands/new-file.js +73 -0
  32. package/dist/commands/new-file.js.map +1 -0
  33. package/dist/commands/projects.js +6 -6
  34. package/dist/commands/projects.js.map +1 -1
  35. package/dist/commands/search.d.ts.map +1 -1
  36. package/dist/commands/search.js +5 -4
  37. package/dist/commands/search.js.map +1 -1
  38. package/dist/commands/setup-claude.js +3 -3
  39. package/dist/commands/skills.d.ts +3 -0
  40. package/dist/commands/skills.d.ts.map +1 -0
  41. package/dist/commands/skills.js +98 -0
  42. package/dist/commands/skills.js.map +1 -0
  43. package/dist/commands/status.js +1 -1
  44. package/dist/commands/status.js.map +1 -1
  45. package/dist/commands/structure.d.ts +3 -0
  46. package/dist/commands/structure.d.ts.map +1 -0
  47. package/dist/commands/structure.js +96 -0
  48. package/dist/commands/structure.js.map +1 -0
  49. package/dist/commands/sync.d.ts.map +1 -1
  50. package/dist/commands/sync.js +7 -5
  51. package/dist/commands/sync.js.map +1 -1
  52. package/dist/commands/tags.d.ts.map +1 -1
  53. package/dist/commands/tags.js +381 -22
  54. package/dist/commands/tags.js.map +1 -1
  55. package/dist/commands/update-library.d.ts +3 -0
  56. package/dist/commands/update-library.d.ts.map +1 -0
  57. package/dist/commands/update-library.js +69 -0
  58. package/dist/commands/update-library.js.map +1 -0
  59. package/dist/commands/versions.d.ts +3 -0
  60. package/dist/commands/versions.d.ts.map +1 -0
  61. package/dist/commands/versions.js +48 -0
  62. package/dist/commands/versions.js.map +1 -0
  63. package/dist/commands/workflow.js +2 -2
  64. package/dist/commands/workflow.js.map +1 -1
  65. package/dist/commands/workflows.d.ts.map +1 -1
  66. package/dist/commands/workflows.js +400 -17
  67. package/dist/commands/workflows.js.map +1 -1
  68. package/dist/commands/workspaces.js +1 -1
  69. package/dist/commands/workspaces.js.map +1 -1
  70. package/dist/index.js +59 -17
  71. package/dist/index.js.map +1 -1
  72. package/dist/lib/api-client.d.ts +1 -0
  73. package/dist/lib/api-client.d.ts.map +1 -1
  74. package/dist/lib/api-client.js +9 -5
  75. package/dist/lib/api-client.js.map +1 -1
  76. package/dist/lib/msal.js +18 -18
  77. package/package.json +58 -58
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAOnC,eAAO,MAAM,WAAW,SA2IpB,CAAA"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAOnC,eAAO,MAAM,WAAW,SA6IpB,CAAA"}
@@ -6,7 +6,7 @@ import { chalk, ora } from '../lib/output.js';
6
6
  export const syncCommand = new Command('sync')
7
7
  .description('Sync workspace files to local cache')
8
8
  .argument('[files...]', 'Specific files to sync')
9
- .option('--workspace <slug>', 'Specify workspace')
9
+ .option('-w, --workspace <slug>', 'Specify workspace')
10
10
  .option('--force', 'Force re-download all files')
11
11
  .option('--tag <tags...>', 'Sync only files with these tags')
12
12
  .option('--dry-run', 'Show what would be synced')
@@ -51,8 +51,9 @@ export const syncCommand = new Command('sync')
51
51
  for (const fileName of files) {
52
52
  let found = false;
53
53
  for (const project of projects) {
54
- const { data } = await client.get(`/projects/${project.id}/files`, { params: { search: fileName } });
55
- const file = data.find((f) => f.title === fileName || f.path === fileName);
54
+ const { data: filesData } = await client.get(`/projects/${project.id}/files`, { params: { search: fileName } });
55
+ const files = filesData.data || filesData;
56
+ const file = files.find((f) => f.title === fileName || f.path === fileName);
56
57
  if (file) {
57
58
  filesToSync.push(file);
58
59
  found = true;
@@ -74,8 +75,9 @@ export const syncCommand = new Command('sync')
74
75
  params.tags = config.files.tags.join(',');
75
76
  }
76
77
  for (const project of projects) {
77
- const { data } = await client.get(`/projects/${project.id}/files`, { params });
78
- filesToSync.push(...data);
78
+ const { data: filesData } = await client.get(`/projects/${project.id}/files`, { params });
79
+ const files = filesData.data || filesData;
80
+ filesToSync.push(...files);
79
81
  }
80
82
  }
81
83
  if (filesToSync.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/commands/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,WAAW,SACmB,CAAC"}
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/commands/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,eAAO,MAAM,WAAW,SACmB,CAAC"}
@@ -2,25 +2,36 @@ import { Command } from 'commander';
2
2
  import { ApiClient } from '../lib/api-client.js';
3
3
  import { loadConfig } from '../lib/config.js';
4
4
  import { chalk, ora } from '../lib/output.js';
5
+ async function resolveWorkspace(client, workspaceName) {
6
+ const { data: workspacesData } = await client.get('/workspaces');
7
+ const workspaces = workspacesData.data || workspacesData;
8
+ const workspace = workspaces.find((w) => w.slug.toLowerCase().trim() === workspaceName.toLowerCase().trim() ||
9
+ w.name.toLowerCase().trim() === workspaceName.toLowerCase().trim());
10
+ if (!workspace) {
11
+ console.log(chalk.dim('Available workspaces:'));
12
+ workspaces.forEach((w) => console.log(chalk.dim(` - ${w.name} (${w.slug})`)));
13
+ throw new Error(`Workspace '${workspaceName}' not found`);
14
+ }
15
+ return workspace;
16
+ }
5
17
  export const tagsCommand = new Command('tags')
6
18
  .description('Manage tags and tag types');
7
19
  // List tag types
8
20
  tagsCommand
9
21
  .command('types')
10
22
  .description('List tag types in a workspace')
11
- .option('-w, --workspace <id>', 'Workspace ID (uses workspace from .contextiumrc if not provided)')
23
+ .option('-w, --workspace <id>', 'Workspace name, slug, or ID')
12
24
  .action(async (options) => {
13
25
  const spinner = ora('Loading tag types...').start();
14
26
  try {
15
27
  const config = await loadConfig();
16
28
  const client = new ApiClient(config.api_key, config.api_url);
17
- // Get workspace ID from config if not provided
18
- const workspaceId = options.workspace;
19
- if (!workspaceId) {
20
- spinner.fail('Error: Workspace ID is required. Use -w flag.');
29
+ if (!options.workspace) {
30
+ spinner.fail('Error: Workspace is required. Use -w flag.');
21
31
  process.exit(1);
22
32
  }
23
- const response = await client.get(`/workspaces/${workspaceId}/tag-types`);
33
+ const workspace = await resolveWorkspace(client, options.workspace);
34
+ const response = await client.get(`/workspaces/${workspace.id}/tag-types`);
24
35
  const tagTypesData = response.data;
25
36
  const tagTypes = tagTypesData.data || tagTypesData || [];
26
37
  if (tagTypes.length === 0) {
@@ -54,9 +65,9 @@ tagsCommand
54
65
  tagsCommand
55
66
  .command('create-type')
56
67
  .description('Create a new tag type')
57
- .requiredOption('-w, --workspace <id>', 'Workspace ID')
68
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
58
69
  .requiredOption('-n, --name <name>', 'Type name')
59
- .requiredOption('-s, --slug <slug>', 'Type slug (lowercase, hyphen-separated)')
70
+ .option('-s, --slug <slug>', 'Type slug (auto-generated from name if not provided)')
60
71
  .option('-c, --color <hex>', 'Hex color code')
61
72
  .option('-i, --icon <icon>', 'Icon name')
62
73
  .option('-d, --description <text>', 'Description')
@@ -65,14 +76,16 @@ tagsCommand
65
76
  try {
66
77
  const config = await loadConfig();
67
78
  const client = new ApiClient(config.api_key, config.api_url);
79
+ const workspace = await resolveWorkspace(client, options.workspace);
80
+ const slug = options.slug || options.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '').replace(/-+/g, '-').replace(/^-|-$/g, '');
68
81
  // Validate slug format
69
- if (!/^[a-z0-9-]+$/.test(options.slug)) {
82
+ if (!/^[a-z0-9-]+$/.test(slug)) {
70
83
  spinner.fail('Error: Slug must contain only lowercase letters, numbers, and hyphens');
71
84
  process.exit(1);
72
85
  }
73
86
  const data = {
74
87
  name: options.name,
75
- slug: options.slug,
88
+ slug,
76
89
  };
77
90
  if (options.color)
78
91
  data.color = options.color;
@@ -80,7 +93,7 @@ tagsCommand
80
93
  data.icon = options.icon;
81
94
  if (options.description)
82
95
  data.description = options.description;
83
- const response = await client.post(`/workspaces/${options.workspace}/tag-types`, data);
96
+ const response = await client.post(`/workspaces/${workspace.id}/tag-types`, data);
84
97
  const tagTypeData = response.data;
85
98
  const tagType = tagTypeData.data || tagTypeData;
86
99
  spinner.stop();
@@ -99,19 +112,19 @@ tagsCommand
99
112
  tagsCommand
100
113
  .command('list')
101
114
  .description('List tags in a workspace')
102
- .option('-w, --workspace <id>', 'Workspace ID')
115
+ .option('-w, --workspace <id>', 'Workspace name, slug, or ID')
103
116
  .option('-t, --type <typeId>', 'Filter by tag type ID')
104
117
  .action(async (options) => {
105
118
  const spinner = ora('Loading tags...').start();
106
119
  try {
107
120
  const config = await loadConfig();
108
121
  const client = new ApiClient(config.api_key, config.api_url);
109
- const workspaceId = options.workspace;
110
- if (!workspaceId) {
111
- spinner.fail('Error: Workspace ID is required. Use -w flag.');
122
+ if (!options.workspace) {
123
+ spinner.fail('Error: Workspace is required. Use -w flag.');
112
124
  process.exit(1);
113
125
  }
114
- let url = `/workspaces/${workspaceId}/tags`;
126
+ const workspace = await resolveWorkspace(client, options.workspace);
127
+ let url = `/workspaces/${workspace.id}/tags`;
115
128
  if (options.type) {
116
129
  url += `?typeId=${options.type}`;
117
130
  }
@@ -155,8 +168,8 @@ tagsCommand
155
168
  tagsCommand
156
169
  .command('create')
157
170
  .description('Create a new tag')
158
- .requiredOption('-w, --workspace <id>', 'Workspace ID')
159
- .requiredOption('-t, --type <typeId>', 'Tag type ID')
171
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
172
+ .requiredOption('-t, --type <typeId>', 'Tag type ID or slug')
160
173
  .requiredOption('-v, --value <value>', 'Tag value (lowercase, hyphen-separated)')
161
174
  .option('-c, --color <hex>', 'Hex color code')
162
175
  .action(async (options) => {
@@ -169,13 +182,28 @@ tagsCommand
169
182
  spinner.fail('Error: Tag value must contain only lowercase letters, numbers, and hyphens');
170
183
  process.exit(1);
171
184
  }
185
+ const workspace = await resolveWorkspace(client, options.workspace);
186
+ // Resolve type by slug if not a UUID
187
+ let typeId = options.type;
188
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
189
+ if (!uuidRegex.test(typeId)) {
190
+ const typesResponse = await client.get(`/workspaces/${workspace.id}/tag-types`);
191
+ const typesData = typesResponse.data;
192
+ const types = typesData.data || typesData || [];
193
+ const matchingType = types.find((t) => t.slug === typeId || t.name.toLowerCase() === typeId.toLowerCase());
194
+ if (!matchingType) {
195
+ spinner.fail(`Tag type '${typeId}' not found. Use 'contextium tags types -w ${options.workspace}' to list types.`);
196
+ process.exit(1);
197
+ }
198
+ typeId = matchingType.id;
199
+ }
172
200
  const data = {
173
- typeId: options.type,
201
+ typeId,
174
202
  value: options.value,
175
203
  };
176
204
  if (options.color)
177
205
  data.color = options.color;
178
- const response = await client.post(`/workspaces/${options.workspace}/tags`, data);
206
+ const response = await client.post(`/workspaces/${workspace.id}/tags`, data);
179
207
  const tagData = response.data;
180
208
  const tag = tagData.data || tagData;
181
209
  spinner.stop();
@@ -190,11 +218,132 @@ tagsCommand
190
218
  process.exit(1);
191
219
  }
192
220
  });
221
+ // Apply tag to a file
222
+ tagsCommand
223
+ .command('apply')
224
+ .description('Apply a tag to a file')
225
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
226
+ .requiredOption('-t, --tag <tagId>', 'Tag ID or slug:value (e.g., "topic:authentication")')
227
+ .requiredOption('-f, --file <fileId>', 'File ID')
228
+ .action(async (options) => {
229
+ const spinner = ora('Applying tag...').start();
230
+ try {
231
+ const config = await loadConfig();
232
+ const client = new ApiClient(config.api_key, config.api_url);
233
+ const workspace = await resolveWorkspace(client, options.workspace);
234
+ // Resolve tag by slug:value if not a UUID
235
+ let tagId = options.tag;
236
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
237
+ if (!uuidRegex.test(tagId)) {
238
+ const tagsResponse = await client.get(`/workspaces/${workspace.id}/tags`);
239
+ const allTags = tagsResponse.data.data || tagsResponse.data || [];
240
+ const [typeSlug, value] = tagId.includes(':') ? tagId.split(':') : [null, tagId];
241
+ const matchingTag = allTags.find((tag) => {
242
+ if (typeSlug)
243
+ return tag.typeSlug === typeSlug && tag.value === value;
244
+ return tag.value === value;
245
+ });
246
+ if (!matchingTag) {
247
+ spinner.fail(`Tag '${tagId}' not found. Use 'contextium tags list -w ${options.workspace}' to see available tags.`);
248
+ process.exit(1);
249
+ }
250
+ tagId = matchingTag.id;
251
+ }
252
+ await client.post(`/tags/${tagId}/apply?workspaceId=${workspace.id}`, { fileId: options.file });
253
+ spinner.stop();
254
+ console.log(chalk.green('\n✓ Tag applied successfully!'));
255
+ }
256
+ catch (error) {
257
+ spinner.fail(`Failed to apply tag: ${error.message}`);
258
+ process.exit(1);
259
+ }
260
+ });
261
+ // Apply tag to multiple files
262
+ tagsCommand
263
+ .command('apply-bulk')
264
+ .description('Apply a tag to multiple files')
265
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
266
+ .requiredOption('-t, --tag <tagId>', 'Tag ID or slug:value (e.g., "topic:authentication")')
267
+ .requiredOption('-f, --files <fileIds>', 'Comma-separated file IDs')
268
+ .action(async (options) => {
269
+ const fileIds = options.files.split(',').map((f) => f.trim());
270
+ const spinner = ora(`Applying tag to ${fileIds.length} file(s)...`).start();
271
+ try {
272
+ const config = await loadConfig();
273
+ const client = new ApiClient(config.api_key, config.api_url);
274
+ const workspace = await resolveWorkspace(client, options.workspace);
275
+ // Resolve tag by slug:value if not a UUID
276
+ let tagId = options.tag;
277
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
278
+ if (!uuidRegex.test(tagId)) {
279
+ const tagsResponse = await client.get(`/workspaces/${workspace.id}/tags`);
280
+ const allTags = tagsResponse.data.data || tagsResponse.data || [];
281
+ const [typeSlug, value] = tagId.includes(':') ? tagId.split(':') : [null, tagId];
282
+ const matchingTag = allTags.find((tag) => {
283
+ if (typeSlug)
284
+ return tag.typeSlug === typeSlug && tag.value === value;
285
+ return tag.value === value;
286
+ });
287
+ if (!matchingTag) {
288
+ spinner.fail(`Tag '${tagId}' not found.`);
289
+ process.exit(1);
290
+ }
291
+ tagId = matchingTag.id;
292
+ }
293
+ await client.post(`/tags/${tagId}/apply-bulk?workspaceId=${workspace.id}`, { fileIds });
294
+ spinner.stop();
295
+ console.log(chalk.green(`\n✓ Tag applied to ${fileIds.length} file(s) successfully!`));
296
+ }
297
+ catch (error) {
298
+ spinner.fail(`Failed to apply tag: ${error.message}`);
299
+ process.exit(1);
300
+ }
301
+ });
302
+ // Remove tag from a file
303
+ tagsCommand
304
+ .command('remove')
305
+ .description('Remove a tag from a file')
306
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
307
+ .requiredOption('-t, --tag <tagId>', 'Tag ID or slug:value (e.g., "topic:authentication")')
308
+ .requiredOption('-f, --file <fileId>', 'File ID')
309
+ .action(async (options) => {
310
+ const spinner = ora('Removing tag...').start();
311
+ try {
312
+ const config = await loadConfig();
313
+ const client = new ApiClient(config.api_key, config.api_url);
314
+ const workspace = await resolveWorkspace(client, options.workspace);
315
+ // Resolve tag by slug:value if not a UUID
316
+ let tagId = options.tag;
317
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
318
+ if (!uuidRegex.test(tagId)) {
319
+ const tagsResponse = await client.get(`/workspaces/${workspace.id}/tags`);
320
+ const allTags = tagsResponse.data.data || tagsResponse.data || [];
321
+ const [typeSlug, value] = tagId.includes(':') ? tagId.split(':') : [null, tagId];
322
+ const matchingTag = allTags.find((tag) => {
323
+ if (typeSlug)
324
+ return tag.typeSlug === typeSlug && tag.value === value;
325
+ return tag.value === value;
326
+ });
327
+ if (!matchingTag) {
328
+ spinner.fail(`Tag '${tagId}' not found.`);
329
+ process.exit(1);
330
+ }
331
+ tagId = matchingTag.id;
332
+ }
333
+ await client.post(`/tags/${tagId}/remove?workspaceId=${workspace.id}`, { fileId: options.file });
334
+ spinner.stop();
335
+ console.log(chalk.green('\n✓ Tag removed successfully!'));
336
+ }
337
+ catch (error) {
338
+ spinner.fail(`Failed to remove tag: ${error.message}`);
339
+ process.exit(1);
340
+ }
341
+ });
193
342
  // Search files by tags
194
343
  tagsCommand
195
344
  .command('search')
196
345
  .description('Search files by tags')
197
- .requiredOption('-w, --workspace <id>', 'Workspace ID')
346
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
198
347
  .requiredOption('-t, --tags <tagIds>', 'Comma-separated tag IDs or tag values (e.g., "md" or "file-type:md")')
199
348
  .option('-p, --library <libraryId>', 'Filter by context library ID')
200
349
  .action(async (options) => {
@@ -202,7 +351,8 @@ tagsCommand
202
351
  try {
203
352
  const config = await loadConfig();
204
353
  const client = new ApiClient(config.api_key, config.api_url);
205
- const workspaceId = options.workspace;
354
+ const workspace = await resolveWorkspace(client, options.workspace);
355
+ const workspaceId = workspace.id;
206
356
  // Parse tag input - support both IDs and slug:value format
207
357
  let tagIds = [];
208
358
  const tagInput = options.tags.split(',').map((t) => t.trim());
@@ -295,6 +445,7 @@ tagsCommand
295
445
  projectFiles.forEach((file) => {
296
446
  const sizeKB = file.fileSize ? (file.fileSize / 1024).toFixed(2) : '0';
297
447
  console.log(` - ${chalk.white(file.title)}`);
448
+ console.log(` ID: ${chalk.dim(file.id)}`);
298
449
  console.log(` Path: ${chalk.dim(file.path || 'N/A')}`);
299
450
  console.log(` Size: ${chalk.dim(sizeKB + ' KB')}`);
300
451
  console.log('');
@@ -309,4 +460,212 @@ tagsCommand
309
460
  process.exit(1);
310
461
  }
311
462
  });
463
+ // List tags on a file
464
+ tagsCommand
465
+ .command('file-tags')
466
+ .description('List tags applied to a specific file')
467
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
468
+ .requiredOption('-f, --file <fileId>', 'File ID')
469
+ .action(async (options) => {
470
+ const spinner = ora('Loading file tags...').start();
471
+ try {
472
+ const config = await loadConfig();
473
+ const client = new ApiClient(config.api_key, config.api_url);
474
+ const workspace = await resolveWorkspace(client, options.workspace);
475
+ const response = await client.get(`/files/${options.file}/tags`, {
476
+ params: { workspaceId: workspace.id }
477
+ });
478
+ const tagsData = response.data;
479
+ const tags = tagsData.data || tagsData || [];
480
+ if (tags.length === 0) {
481
+ spinner.stop();
482
+ console.log(chalk.yellow('No tags on this file.'));
483
+ return;
484
+ }
485
+ spinner.stop();
486
+ console.log(chalk.bold(`\n${tags.length} tag(s) on file:\n`));
487
+ tags.forEach((entry) => {
488
+ const tag = entry.tag || entry;
489
+ console.log(` ${chalk.cyan(tag.typeSlug || tag.typeName || 'unknown')}:${tag.value}`);
490
+ console.log(chalk.dim(` ID: ${tag.id} Color: ${tag.color || 'default'}`));
491
+ });
492
+ console.log('');
493
+ }
494
+ catch (error) {
495
+ spinner.fail(`Failed to load file tags: ${error.message}`);
496
+ process.exit(1);
497
+ }
498
+ });
499
+ // Update a tag
500
+ tagsCommand
501
+ .command('update')
502
+ .description('Update an existing tag')
503
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
504
+ .requiredOption('-t, --tag <tagId>', 'Tag ID or slug:value')
505
+ .option('-v, --value <value>', 'New tag value (lowercase, hyphens)')
506
+ .option('--type <typeId>', 'New tag type ID')
507
+ .option('-c, --color <hex>', 'New hex color code')
508
+ .action(async (options) => {
509
+ const spinner = ora('Updating tag...').start();
510
+ try {
511
+ const config = await loadConfig();
512
+ const client = new ApiClient(config.api_key, config.api_url);
513
+ const workspace = await resolveWorkspace(client, options.workspace);
514
+ // Resolve tag by slug:value if not a UUID
515
+ let tagId = options.tag;
516
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
517
+ if (!uuidRegex.test(tagId)) {
518
+ const tagsResponse = await client.get(`/workspaces/${workspace.id}/tags`);
519
+ const allTags = tagsResponse.data.data || tagsResponse.data || [];
520
+ const [typeSlug, value] = tagId.includes(':') ? tagId.split(':') : [null, tagId];
521
+ const matchingTag = allTags.find((tag) => {
522
+ if (typeSlug)
523
+ return tag.typeSlug === typeSlug && tag.value === value;
524
+ return tag.value === value;
525
+ });
526
+ if (!matchingTag) {
527
+ spinner.fail(`Tag '${tagId}' not found.`);
528
+ process.exit(1);
529
+ }
530
+ tagId = matchingTag.id;
531
+ }
532
+ const data = {};
533
+ if (options.value)
534
+ data.value = options.value;
535
+ if (options.type)
536
+ data.typeId = options.type;
537
+ if (options.color)
538
+ data.color = options.color;
539
+ if (Object.keys(data).length === 0) {
540
+ spinner.fail('No fields to update. Use --value, --type, or --color.');
541
+ process.exit(1);
542
+ }
543
+ const response = await client.put(`/tags/${tagId}?workspaceId=${workspace.id}`, data);
544
+ const tag = response.data.data || response.data;
545
+ spinner.stop();
546
+ console.log(chalk.green('\n✓ Tag updated successfully!'));
547
+ console.log(` Tag: ${tag.typeSlug || ''}:${tag.value}`);
548
+ console.log(` ID: ${tag.id}`);
549
+ if (tag.color)
550
+ console.log(` Color: ${tag.color}`);
551
+ console.log('');
552
+ }
553
+ catch (error) {
554
+ spinner.fail(`Failed to update tag: ${error.message}`);
555
+ process.exit(1);
556
+ }
557
+ });
558
+ // Get tag type by ID
559
+ tagsCommand
560
+ .command('type-get')
561
+ .description('Get a tag type by ID')
562
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
563
+ .requiredOption('-t, --type <typeId>', 'Tag type ID or slug')
564
+ .action(async (options) => {
565
+ const spinner = ora('Loading tag type...').start();
566
+ try {
567
+ const config = await loadConfig();
568
+ const client = new ApiClient(config.api_key, config.api_url);
569
+ const workspace = await resolveWorkspace(client, options.workspace);
570
+ // Resolve type by slug if not a UUID
571
+ let typeId = options.type;
572
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
573
+ if (!uuidRegex.test(typeId)) {
574
+ const typesResponse = await client.get(`/workspaces/${workspace.id}/tag-types`);
575
+ const types = typesResponse.data.data || typesResponse.data || [];
576
+ const match = types.find((t) => t.slug === typeId || t.name.toLowerCase() === typeId.toLowerCase());
577
+ if (!match) {
578
+ spinner.fail(`Tag type '${typeId}' not found.`);
579
+ process.exit(1);
580
+ }
581
+ typeId = match.id;
582
+ }
583
+ const response = await client.get(`/tag-types/${typeId}`, {
584
+ params: { workspaceId: workspace.id }
585
+ });
586
+ const tagType = response.data.data || response.data;
587
+ spinner.stop();
588
+ console.log(chalk.bold(`\nTag Type: ${tagType.name}\n`));
589
+ console.log(` ID: ${tagType.id}`);
590
+ console.log(` Slug: ${tagType.slug}`);
591
+ console.log(` Color: ${tagType.color || 'default'}`);
592
+ if (tagType.icon)
593
+ console.log(` Icon: ${tagType.icon}`);
594
+ if (tagType.description)
595
+ console.log(` Description: ${tagType.description}`);
596
+ console.log(` System: ${tagType.isSystem ? 'Yes' : 'No'}`);
597
+ console.log(` Display Order: ${tagType.displayOrder}`);
598
+ if (tagType.tagCount !== undefined)
599
+ console.log(` Tag Count: ${tagType.tagCount}`);
600
+ console.log('');
601
+ }
602
+ catch (error) {
603
+ spinner.fail(`Failed to load tag type: ${error.message}`);
604
+ process.exit(1);
605
+ }
606
+ });
607
+ // Update tag type
608
+ tagsCommand
609
+ .command('type-update')
610
+ .description('Update an existing tag type')
611
+ .requiredOption('-w, --workspace <id>', 'Workspace name, slug, or ID')
612
+ .requiredOption('-t, --type <typeId>', 'Tag type ID or slug')
613
+ .option('-n, --name <name>', 'New name')
614
+ .option('-s, --slug <slug>', 'New slug')
615
+ .option('-c, --color <hex>', 'New hex color code')
616
+ .option('-i, --icon <icon>', 'New icon name')
617
+ .option('-d, --description <text>', 'New description')
618
+ .option('--order <number>', 'New display order')
619
+ .action(async (options) => {
620
+ const spinner = ora('Updating tag type...').start();
621
+ try {
622
+ const config = await loadConfig();
623
+ const client = new ApiClient(config.api_key, config.api_url);
624
+ const workspace = await resolveWorkspace(client, options.workspace);
625
+ // Resolve type by slug if not a UUID
626
+ let typeId = options.type;
627
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
628
+ if (!uuidRegex.test(typeId)) {
629
+ const typesResponse = await client.get(`/workspaces/${workspace.id}/tag-types`);
630
+ const types = typesResponse.data.data || typesResponse.data || [];
631
+ const match = types.find((t) => t.slug === typeId || t.name.toLowerCase() === typeId.toLowerCase());
632
+ if (!match) {
633
+ spinner.fail(`Tag type '${typeId}' not found.`);
634
+ process.exit(1);
635
+ }
636
+ typeId = match.id;
637
+ }
638
+ const data = {};
639
+ if (options.name)
640
+ data.name = options.name;
641
+ if (options.slug)
642
+ data.slug = options.slug;
643
+ if (options.color)
644
+ data.color = options.color;
645
+ if (options.icon)
646
+ data.icon = options.icon;
647
+ if (options.description)
648
+ data.description = options.description;
649
+ if (options.order !== undefined)
650
+ data.displayOrder = parseInt(options.order, 10);
651
+ if (Object.keys(data).length === 0) {
652
+ spinner.fail('No fields to update. Use --name, --slug, --color, --icon, --description, or --order.');
653
+ process.exit(1);
654
+ }
655
+ const response = await client.put(`/tag-types/${typeId}?workspaceId=${workspace.id}`, data);
656
+ const tagType = response.data.data || response.data;
657
+ spinner.stop();
658
+ console.log(chalk.green('\n✓ Tag type updated successfully!'));
659
+ console.log(` Name: ${tagType.name}`);
660
+ console.log(` Slug: ${tagType.slug}`);
661
+ console.log(` ID: ${tagType.id}`);
662
+ if (tagType.color)
663
+ console.log(` Color: ${tagType.color}`);
664
+ console.log('');
665
+ }
666
+ catch (error) {
667
+ spinner.fail(`Failed to update tag type: ${error.message}`);
668
+ process.exit(1);
669
+ }
670
+ });
312
671
  //# sourceMappingURL=tags.js.map