linear-cli-agents 0.5.1 → 0.7.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 +87 -1
- package/dist/commands/cycles/current.d.ts +11 -0
- package/dist/commands/cycles/current.js +104 -0
- package/dist/commands/cycles/get.d.ts +12 -0
- package/dist/commands/cycles/get.js +86 -0
- package/dist/commands/cycles/list.d.ts +16 -0
- package/dist/commands/cycles/list.js +147 -0
- package/dist/commands/documents/create.d.ts +13 -0
- package/dist/commands/documents/create.js +68 -0
- package/dist/commands/documents/delete.d.ts +9 -0
- package/dist/commands/documents/delete.js +32 -0
- package/dist/commands/documents/get.d.ts +12 -0
- package/dist/commands/documents/get.js +79 -0
- package/dist/commands/documents/list.d.ts +12 -0
- package/dist/commands/documents/list.js +105 -0
- package/dist/commands/documents/update.d.ts +16 -0
- package/dist/commands/documents/update.js +75 -0
- package/dist/commands/info.js +209 -3
- package/dist/commands/initiatives/archive.d.ts +12 -0
- package/dist/commands/initiatives/archive.js +44 -0
- package/dist/commands/initiatives/create.d.ts +15 -0
- package/dist/commands/initiatives/create.js +84 -0
- package/dist/commands/initiatives/delete.d.ts +9 -0
- package/dist/commands/initiatives/delete.js +32 -0
- package/dist/commands/initiatives/get.d.ts +12 -0
- package/dist/commands/initiatives/get.js +90 -0
- package/dist/commands/initiatives/list.d.ts +11 -0
- package/dist/commands/initiatives/list.js +135 -0
- package/dist/commands/initiatives/update.d.ts +18 -0
- package/dist/commands/initiatives/update.js +90 -0
- package/dist/commands/issues/bulk-update.d.ts +2 -0
- package/dist/commands/issues/bulk-update.js +10 -0
- package/dist/commands/issues/create.d.ts +2 -0
- package/dist/commands/issues/create.js +10 -0
- package/dist/commands/issues/get.d.ts +1 -0
- package/dist/commands/issues/get.js +19 -1
- package/dist/commands/issues/update.d.ts +2 -0
- package/dist/commands/issues/update.js +12 -0
- package/dist/commands/upload.d.ts +13 -0
- package/dist/commands/upload.js +117 -0
- package/dist/lib/formatter.d.ts +4 -0
- package/dist/lib/formatter.js +15 -0
- package/oclif.manifest.json +1323 -405
- package/package.json +10 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Upload extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
file: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
'content-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
markdown: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { readFileSync, statSync, existsSync } from 'node:fs';
|
|
3
|
+
import { basename, extname } from 'node:path';
|
|
4
|
+
import { getClient } from '../lib/client.js';
|
|
5
|
+
import { success, print } from '../lib/output.js';
|
|
6
|
+
import { handleError, CliError, ErrorCodes } from '../lib/errors.js';
|
|
7
|
+
const MIME_TYPES = {
|
|
8
|
+
'.png': 'image/png',
|
|
9
|
+
'.jpg': 'image/jpeg',
|
|
10
|
+
'.jpeg': 'image/jpeg',
|
|
11
|
+
'.gif': 'image/gif',
|
|
12
|
+
'.webp': 'image/webp',
|
|
13
|
+
'.svg': 'image/svg+xml',
|
|
14
|
+
'.pdf': 'application/pdf',
|
|
15
|
+
'.doc': 'application/msword',
|
|
16
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
17
|
+
'.xls': 'application/vnd.ms-excel',
|
|
18
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
19
|
+
'.ppt': 'application/vnd.ms-powerpoint',
|
|
20
|
+
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
21
|
+
'.txt': 'text/plain',
|
|
22
|
+
'.md': 'text/markdown',
|
|
23
|
+
'.json': 'application/json',
|
|
24
|
+
'.csv': 'text/csv',
|
|
25
|
+
'.zip': 'application/zip',
|
|
26
|
+
'.mp4': 'video/mp4',
|
|
27
|
+
'.webm': 'video/webm',
|
|
28
|
+
'.mp3': 'audio/mpeg',
|
|
29
|
+
'.wav': 'audio/wav',
|
|
30
|
+
};
|
|
31
|
+
function getMimeType(filePath) {
|
|
32
|
+
const ext = extname(filePath).toLowerCase();
|
|
33
|
+
return MIME_TYPES[ext] ?? 'application/octet-stream';
|
|
34
|
+
}
|
|
35
|
+
export default class Upload extends Command {
|
|
36
|
+
static description = 'Upload a file to Linear and get the asset URL';
|
|
37
|
+
static examples = [
|
|
38
|
+
'<%= config.bin %> upload ./screenshot.png',
|
|
39
|
+
'<%= config.bin %> upload ./document.pdf --content-type application/pdf',
|
|
40
|
+
'<%= config.bin %> upload ./image.png --markdown',
|
|
41
|
+
];
|
|
42
|
+
static args = {
|
|
43
|
+
file: Args.string({
|
|
44
|
+
description: 'Path to the file to upload',
|
|
45
|
+
required: true,
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
static flags = {
|
|
49
|
+
'content-type': Flags.string({
|
|
50
|
+
description: 'Override the content type (MIME type)',
|
|
51
|
+
}),
|
|
52
|
+
markdown: Flags.boolean({
|
|
53
|
+
char: 'm',
|
|
54
|
+
description: 'Output as markdown link/image',
|
|
55
|
+
default: false,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
async run() {
|
|
59
|
+
try {
|
|
60
|
+
const { args, flags } = await this.parse(Upload);
|
|
61
|
+
const client = getClient();
|
|
62
|
+
const filePath = args.file;
|
|
63
|
+
if (!existsSync(filePath)) {
|
|
64
|
+
throw new CliError(ErrorCodes.NOT_FOUND, `File not found: ${filePath}`);
|
|
65
|
+
}
|
|
66
|
+
const stats = statSync(filePath);
|
|
67
|
+
if (!stats.isFile()) {
|
|
68
|
+
throw new CliError(ErrorCodes.INVALID_INPUT, `Not a file: ${filePath}`);
|
|
69
|
+
}
|
|
70
|
+
const fileName = basename(filePath);
|
|
71
|
+
const contentType = flags['content-type'] ?? getMimeType(filePath);
|
|
72
|
+
const fileSize = stats.size;
|
|
73
|
+
const uploadPayload = await client.fileUpload(contentType, fileName, fileSize);
|
|
74
|
+
if (!uploadPayload.success || !uploadPayload.uploadFile) {
|
|
75
|
+
throw new CliError(ErrorCodes.API_ERROR, 'Failed to request upload URL');
|
|
76
|
+
}
|
|
77
|
+
const { uploadUrl, assetUrl } = uploadPayload.uploadFile;
|
|
78
|
+
const uploadHeaders = uploadPayload.uploadFile.headers;
|
|
79
|
+
const fileContent = readFileSync(filePath);
|
|
80
|
+
const headers = {
|
|
81
|
+
'Content-Type': contentType,
|
|
82
|
+
'Cache-Control': 'public, max-age=31536000',
|
|
83
|
+
};
|
|
84
|
+
for (const { key, value } of uploadHeaders) {
|
|
85
|
+
headers[key] = value;
|
|
86
|
+
}
|
|
87
|
+
const response = await fetch(uploadUrl, {
|
|
88
|
+
method: 'PUT',
|
|
89
|
+
headers,
|
|
90
|
+
body: fileContent,
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new CliError(ErrorCodes.API_ERROR, `Upload failed: ${response.status} ${response.statusText}`);
|
|
94
|
+
}
|
|
95
|
+
if (flags.markdown) {
|
|
96
|
+
const isImage = contentType.startsWith('image/');
|
|
97
|
+
const markdown = isImage ? `` : `[${fileName}](${assetUrl})`;
|
|
98
|
+
print(success({
|
|
99
|
+
assetUrl,
|
|
100
|
+
markdown,
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
print(success({
|
|
105
|
+
fileName,
|
|
106
|
+
contentType,
|
|
107
|
+
size: fileSize,
|
|
108
|
+
assetUrl,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
handleError(err);
|
|
114
|
+
this.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
package/dist/lib/formatter.d.ts
CHANGED
|
@@ -49,6 +49,10 @@ export declare const formatPriority: (priority: number) => string;
|
|
|
49
49
|
* Truncate string to max length with ellipsis.
|
|
50
50
|
*/
|
|
51
51
|
export declare const truncate: (str: string | undefined | null, maxLength: number) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Format progress as a percentage with color.
|
|
54
|
+
*/
|
|
55
|
+
export declare const formatProgress: (progress: number) => string;
|
|
52
56
|
/**
|
|
53
57
|
* Generic formatter that outputs data in the specified format.
|
|
54
58
|
*/
|
package/dist/lib/formatter.js
CHANGED
|
@@ -166,6 +166,21 @@ export const truncate = (str, maxLength) => {
|
|
|
166
166
|
return str;
|
|
167
167
|
return str.slice(0, maxLength - 1) + '\u2026';
|
|
168
168
|
};
|
|
169
|
+
/**
|
|
170
|
+
* Format progress as a percentage with color.
|
|
171
|
+
*/
|
|
172
|
+
export const formatProgress = (progress) => {
|
|
173
|
+
const percent = Math.round(progress * 100);
|
|
174
|
+
if (percent >= 100)
|
|
175
|
+
return colors.green(`${percent}%`);
|
|
176
|
+
if (percent >= 75)
|
|
177
|
+
return colors.cyan(`${percent}%`);
|
|
178
|
+
if (percent >= 50)
|
|
179
|
+
return colors.blue(`${percent}%`);
|
|
180
|
+
if (percent >= 25)
|
|
181
|
+
return colors.yellow(`${percent}%`);
|
|
182
|
+
return colors.gray(`${percent}%`);
|
|
183
|
+
};
|
|
169
184
|
/**
|
|
170
185
|
* Generic formatter that outputs data in the specified format.
|
|
171
186
|
*/
|