highspot-cli 0.1.1 → 0.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 +18 -4
- package/dist/commands/get.js +263 -0
- package/dist/lib/api.js +4 -4
- package/dist/lib/command.js +3 -0
- package/dist/lib/flags.js +16 -0
- package/dist/lib/help.js +2 -2
- package/package.json +2 -2
- package/dist/commands/content.js +0 -70
- package/dist/commands/item.js +0 -66
package/README.md
CHANGED
|
@@ -72,8 +72,7 @@ Example `.highspot-cli.json`:
|
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
highspot search <query>
|
|
75
|
-
highspot
|
|
76
|
-
highspot content <item-id>
|
|
75
|
+
highspot get <item-id>
|
|
77
76
|
highspot me
|
|
78
77
|
```
|
|
79
78
|
|
|
@@ -94,6 +93,15 @@ Global flags:
|
|
|
94
93
|
- `--no-input`
|
|
95
94
|
- `--no-color`
|
|
96
95
|
|
|
96
|
+
`get` command flags:
|
|
97
|
+
|
|
98
|
+
- `--format <value>`
|
|
99
|
+
- `--start <value>`
|
|
100
|
+
- `--meta-only` (skip content download)
|
|
101
|
+
- `-o, --output <path>` (explicit file path)
|
|
102
|
+
- `--output-dir <path>` (directory for auto-saved binary files)
|
|
103
|
+
- `-f, --force` (overwrite existing output file)
|
|
104
|
+
|
|
97
105
|
Exit codes:
|
|
98
106
|
|
|
99
107
|
- `0` success
|
|
@@ -105,8 +113,11 @@ Exit codes:
|
|
|
105
113
|
```bash
|
|
106
114
|
highspot search "GoGuardian Teacher" --limit 10
|
|
107
115
|
highspot search "Beacon" --sort-by date_added --plain
|
|
108
|
-
highspot
|
|
109
|
-
highspot
|
|
116
|
+
highspot get it_abc123 --meta-only
|
|
117
|
+
highspot get it_abc123 --format text/plain --plain
|
|
118
|
+
highspot get it_abc123
|
|
119
|
+
highspot get it_abc123 --output ./custom-filename.pdf
|
|
120
|
+
highspot get it_abc123 --output-dir ./downloads
|
|
110
121
|
highspot me --json
|
|
111
122
|
highspot search "Fleet" --dry-run
|
|
112
123
|
```
|
|
@@ -115,6 +126,9 @@ Behavior notes:
|
|
|
115
126
|
|
|
116
127
|
- Prompts are not used; `--no-input` is accepted for automation consistency.
|
|
117
128
|
- Primary data goes to stdout, errors go to stderr.
|
|
129
|
+
- `get` always fetches `/items/{id}` metadata first, then fetches `/items/{id}/content` unless `--meta-only` is set.
|
|
130
|
+
- Binary content is automatically saved to disk using Highspot `content_name` (canonical filename) when available.
|
|
131
|
+
- Use `--output` to force a specific filename/path, or `--output-dir` to control where auto-saved binaries are written.
|
|
118
132
|
|
|
119
133
|
## Development
|
|
120
134
|
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, extname, join, resolve } from "node:path";
|
|
5
|
+
import { Args } from "@oclif/core";
|
|
6
|
+
import { BaseCommand } from "../lib/command.js";
|
|
7
|
+
import { contentFlags, globalFlags } from "../lib/flags.js";
|
|
8
|
+
export default class Get extends BaseCommand {
|
|
9
|
+
static description = "Fetch item metadata and content in one command";
|
|
10
|
+
static examples = [
|
|
11
|
+
"highspot get it_abc123",
|
|
12
|
+
"highspot get it_abc123 --meta-only",
|
|
13
|
+
"highspot get it_abc123 --output ./discover-guide.pdf",
|
|
14
|
+
"highspot get it_abc123 --output-dir ./downloads",
|
|
15
|
+
"highspot get it_abc123 --format text/plain --plain",
|
|
16
|
+
];
|
|
17
|
+
static args = {
|
|
18
|
+
itemId: Args.string({
|
|
19
|
+
description: "Highspot item id",
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
static flags = {
|
|
24
|
+
...globalFlags,
|
|
25
|
+
...contentFlags,
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { args, flags } = await this.parse(Get);
|
|
29
|
+
this.ensureOutputFlags(flags);
|
|
30
|
+
this.ensureVerbosityFlags(flags);
|
|
31
|
+
if (!args.itemId) {
|
|
32
|
+
this.fail("itemId is required", 2, flags);
|
|
33
|
+
}
|
|
34
|
+
const payload = {
|
|
35
|
+
operations: [
|
|
36
|
+
{ endpoint: `/items/${encodeURIComponent(args.itemId)}` },
|
|
37
|
+
...(flags["meta-only"]
|
|
38
|
+
? []
|
|
39
|
+
: [
|
|
40
|
+
{
|
|
41
|
+
endpoint: `/items/${encodeURIComponent(args.itemId)}/content`,
|
|
42
|
+
query: {
|
|
43
|
+
...(flags.format ? { format: flags.format } : {}),
|
|
44
|
+
...(flags.start ? { start: flags.start } : {}),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
]),
|
|
48
|
+
],
|
|
49
|
+
output: {
|
|
50
|
+
...(flags.output ? { output: flags.output } : {}),
|
|
51
|
+
...(flags["output-dir"] ? { outputDir: flags["output-dir"] } : {}),
|
|
52
|
+
force: flags.force,
|
|
53
|
+
},
|
|
54
|
+
headers: {
|
|
55
|
+
...(flags["hs-user"] ? { "hs-user": flags["hs-user"] } : {}),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
if (flags["dry-run"]) {
|
|
59
|
+
this.printJson(payload);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const client = this.clientFromFlags(flags);
|
|
64
|
+
const itemData = await client.getItem({
|
|
65
|
+
itemId: args.itemId,
|
|
66
|
+
hsUser: this.effectiveHsUser(flags),
|
|
67
|
+
});
|
|
68
|
+
const item = asItemRecord(itemData.item);
|
|
69
|
+
if (flags["meta-only"]) {
|
|
70
|
+
if (this.outputMode(flags) === "plain") {
|
|
71
|
+
writeItemPlain(item);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.printJson({ item });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const contentData = await client.getItemContent({
|
|
78
|
+
itemId: args.itemId,
|
|
79
|
+
format: flags.format,
|
|
80
|
+
start: flags.start,
|
|
81
|
+
hsUser: this.effectiveHsUser(flags),
|
|
82
|
+
});
|
|
83
|
+
const explicitOutputPath = flags.output
|
|
84
|
+
? resolve(process.cwd(), flags.output)
|
|
85
|
+
: undefined;
|
|
86
|
+
if (contentData.kind === "binary") {
|
|
87
|
+
const binaryOutputPath = explicitOutputPath ??
|
|
88
|
+
resolveBinaryOutputPath({
|
|
89
|
+
outputDir: flags["output-dir"],
|
|
90
|
+
item,
|
|
91
|
+
itemId: args.itemId,
|
|
92
|
+
contentType: contentData.contentType,
|
|
93
|
+
});
|
|
94
|
+
const fileResult = await writeBytesToFile({
|
|
95
|
+
bytes: contentData.bytes,
|
|
96
|
+
contentType: contentData.contentType,
|
|
97
|
+
force: flags.force,
|
|
98
|
+
item,
|
|
99
|
+
itemId: args.itemId,
|
|
100
|
+
outputPath: binaryOutputPath,
|
|
101
|
+
});
|
|
102
|
+
if (this.outputMode(flags) === "plain") {
|
|
103
|
+
writeFileResultPlain(fileResult);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.printJson(fileResult);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (explicitOutputPath) {
|
|
110
|
+
const fileResult = await writeInlineContentToFile({
|
|
111
|
+
content: contentData,
|
|
112
|
+
force: flags.force,
|
|
113
|
+
item,
|
|
114
|
+
itemId: args.itemId,
|
|
115
|
+
outputPath: explicitOutputPath,
|
|
116
|
+
});
|
|
117
|
+
if (this.outputMode(flags) === "plain") {
|
|
118
|
+
writeFileResultPlain(fileResult);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.printJson(fileResult);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (this.outputMode(flags) === "plain") {
|
|
125
|
+
writeInlineContentPlain(contentData);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.printJson({
|
|
129
|
+
item,
|
|
130
|
+
mode: "inline",
|
|
131
|
+
isBinary: false,
|
|
132
|
+
contentType: contentData.contentType,
|
|
133
|
+
content: contentData.content,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
this.handleError(error, flags);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function asItemRecord(value) {
|
|
142
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
143
|
+
return {};
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
function writeItemPlain(item) {
|
|
148
|
+
const id = asString(item.id);
|
|
149
|
+
const url = asString(item.url);
|
|
150
|
+
const title = asString(item.title);
|
|
151
|
+
const contentType = asString(item.content_type);
|
|
152
|
+
const contentName = asString(item.content_name);
|
|
153
|
+
process.stdout.write(`${id}\t${url}\t${title}\t${contentType}\t${contentName}\n`);
|
|
154
|
+
}
|
|
155
|
+
function writeInlineContentPlain(content) {
|
|
156
|
+
if (content.kind === "text") {
|
|
157
|
+
process.stdout.write(content.content);
|
|
158
|
+
if (!content.content.endsWith("\n")) {
|
|
159
|
+
process.stdout.write("\n");
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (content.kind === "json") {
|
|
164
|
+
process.stdout.write(`${JSON.stringify(content.content, null, 2)}\n`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
throw new Error("Binary content must be written to a file.");
|
|
168
|
+
}
|
|
169
|
+
function writeFileResultPlain(result) {
|
|
170
|
+
process.stdout.write(`${result.itemId}\t${result.outputPath}\t${result.contentType}\t${result.sizeBytes}\t${result.sha256}\n`);
|
|
171
|
+
}
|
|
172
|
+
function resolveBinaryOutputPath(args) {
|
|
173
|
+
const outputDir = args.outputDir
|
|
174
|
+
? resolve(process.cwd(), args.outputDir)
|
|
175
|
+
: process.cwd();
|
|
176
|
+
const fileName = preferredBinaryFileName(args.item, args.itemId, args.contentType);
|
|
177
|
+
return join(outputDir, fileName);
|
|
178
|
+
}
|
|
179
|
+
function preferredBinaryFileName(item, itemId, contentType) {
|
|
180
|
+
const candidates = [
|
|
181
|
+
item.content_name,
|
|
182
|
+
item.filename,
|
|
183
|
+
item.file_name,
|
|
184
|
+
item.name,
|
|
185
|
+
item.title,
|
|
186
|
+
]
|
|
187
|
+
.map((value) => asString(value).trim())
|
|
188
|
+
.filter((value) => value.length > 0);
|
|
189
|
+
const baseCandidate = candidates[0] ?? itemId;
|
|
190
|
+
const safeBase = sanitizeFileName(baseCandidate) || itemId;
|
|
191
|
+
if (extname(safeBase)) {
|
|
192
|
+
return safeBase;
|
|
193
|
+
}
|
|
194
|
+
const extension = extensionFromContentType(contentType) ?? "bin";
|
|
195
|
+
return `${safeBase}.${extension}`;
|
|
196
|
+
}
|
|
197
|
+
function sanitizeFileName(input) {
|
|
198
|
+
const invalidChars = new Set(["\\", "/", ":", "*", "?", '"', "<", ">", "|"]);
|
|
199
|
+
let output = "";
|
|
200
|
+
for (const char of input) {
|
|
201
|
+
const code = char.charCodeAt(0);
|
|
202
|
+
if (code >= 0 && code < 32) {
|
|
203
|
+
output += "_";
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
output += invalidChars.has(char) ? "_" : char;
|
|
207
|
+
}
|
|
208
|
+
return output.replace(/\s+/g, " ").trim();
|
|
209
|
+
}
|
|
210
|
+
function extensionFromContentType(contentType) {
|
|
211
|
+
const normalized = contentType.toLowerCase();
|
|
212
|
+
if (normalized.includes("pdf")) {
|
|
213
|
+
return "pdf";
|
|
214
|
+
}
|
|
215
|
+
if (normalized.includes("json")) {
|
|
216
|
+
return "json";
|
|
217
|
+
}
|
|
218
|
+
if (normalized.includes("csv")) {
|
|
219
|
+
return "csv";
|
|
220
|
+
}
|
|
221
|
+
if (normalized.startsWith("text/")) {
|
|
222
|
+
return "txt";
|
|
223
|
+
}
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
async function writeBytesToFile(args) {
|
|
227
|
+
await ensureWriteablePath(args.outputPath, args.force);
|
|
228
|
+
await writeFile(args.outputPath, args.bytes);
|
|
229
|
+
return {
|
|
230
|
+
contentType: args.contentType,
|
|
231
|
+
item: args.item,
|
|
232
|
+
itemId: args.itemId,
|
|
233
|
+
mode: "file",
|
|
234
|
+
outputPath: args.outputPath,
|
|
235
|
+
sha256: createHash("sha256").update(args.bytes).digest("hex"),
|
|
236
|
+
sizeBytes: args.bytes.byteLength,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async function writeInlineContentToFile(args) {
|
|
240
|
+
await ensureWriteablePath(args.outputPath, args.force);
|
|
241
|
+
const text = args.content.kind === "text"
|
|
242
|
+
? args.content.content
|
|
243
|
+
: `${JSON.stringify(args.content.content, null, 2)}\n`;
|
|
244
|
+
await writeFile(args.outputPath, text, "utf8");
|
|
245
|
+
return {
|
|
246
|
+
contentType: args.content.contentType,
|
|
247
|
+
item: args.item,
|
|
248
|
+
itemId: args.itemId,
|
|
249
|
+
mode: "file",
|
|
250
|
+
outputPath: args.outputPath,
|
|
251
|
+
sha256: createHash("sha256").update(text, "utf8").digest("hex"),
|
|
252
|
+
sizeBytes: Buffer.byteLength(text, "utf8"),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async function ensureWriteablePath(path, force) {
|
|
256
|
+
await mkdir(dirname(path), { recursive: true });
|
|
257
|
+
if (existsSync(path) && !force) {
|
|
258
|
+
throw new Error(`Output file already exists: ${path}. Use --force to overwrite.`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function asString(value) {
|
|
262
|
+
return typeof value === "string" ? value : "";
|
|
263
|
+
}
|
package/dist/lib/api.js
CHANGED
|
@@ -160,8 +160,8 @@ export class HighspotClient {
|
|
|
160
160
|
if (contentType.includes("json")) {
|
|
161
161
|
const payload = (await response.json());
|
|
162
162
|
return {
|
|
163
|
+
kind: "json",
|
|
163
164
|
content: payload,
|
|
164
|
-
contentEncoding: "json",
|
|
165
165
|
contentType,
|
|
166
166
|
isBinary: false,
|
|
167
167
|
isJson: true,
|
|
@@ -171,8 +171,8 @@ export class HighspotClient {
|
|
|
171
171
|
if (!looksTextual(contentType)) {
|
|
172
172
|
const binary = await response.arrayBuffer();
|
|
173
173
|
return {
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
kind: "binary",
|
|
175
|
+
bytes: new Uint8Array(binary),
|
|
176
176
|
contentLength: binary.byteLength,
|
|
177
177
|
contentType,
|
|
178
178
|
isBinary: true,
|
|
@@ -182,8 +182,8 @@ export class HighspotClient {
|
|
|
182
182
|
}
|
|
183
183
|
const textContent = await response.text();
|
|
184
184
|
return {
|
|
185
|
+
kind: "text",
|
|
185
186
|
content: textContent,
|
|
186
|
-
contentEncoding: "utf8",
|
|
187
187
|
contentLength: textContent.length,
|
|
188
188
|
contentType,
|
|
189
189
|
isBinary: false,
|
package/dist/lib/command.js
CHANGED
|
@@ -43,6 +43,9 @@ export class BaseCommand extends Command {
|
|
|
43
43
|
this.exit(exitCode);
|
|
44
44
|
}
|
|
45
45
|
handleError(error, flags) {
|
|
46
|
+
if (error instanceof Error && /^EEXIT:\s*\d+/.test(error.message)) {
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
46
49
|
const mode = this.outputMode(flags);
|
|
47
50
|
if (error instanceof ApiError) {
|
|
48
51
|
writeError(mode, formatApiError(error));
|
package/dist/lib/flags.js
CHANGED
|
@@ -72,4 +72,20 @@ export const contentFlags = {
|
|
|
72
72
|
start: Flags.string({
|
|
73
73
|
description: "Optional cursor/start token for paginated content",
|
|
74
74
|
}),
|
|
75
|
+
output: Flags.string({
|
|
76
|
+
char: "o",
|
|
77
|
+
description: "Write content body to a specific file path",
|
|
78
|
+
}),
|
|
79
|
+
"output-dir": Flags.string({
|
|
80
|
+
description: "Directory for auto-saved binary content (default: current working directory)",
|
|
81
|
+
}),
|
|
82
|
+
"meta-only": Flags.boolean({
|
|
83
|
+
description: "Return item metadata only (skip content download)",
|
|
84
|
+
default: false,
|
|
85
|
+
}),
|
|
86
|
+
force: Flags.boolean({
|
|
87
|
+
char: "f",
|
|
88
|
+
description: "Allow overwriting an existing output file",
|
|
89
|
+
default: false,
|
|
90
|
+
}),
|
|
75
91
|
};
|
package/dist/lib/help.js
CHANGED
|
@@ -9,8 +9,8 @@ export default class Help extends OclifHelp {
|
|
|
9
9
|
const examples = this.section("EXAMPLES", this.renderList([
|
|
10
10
|
["highspot --help"],
|
|
11
11
|
['highspot search "GoGuardian Teacher" --limit 5'],
|
|
12
|
-
["highspot
|
|
13
|
-
["highspot
|
|
12
|
+
["highspot get it_abc123 --meta-only"],
|
|
13
|
+
["highspot get it_abc123 --output ./discover-guide.pdf"],
|
|
14
14
|
["highspot me --json"],
|
|
15
15
|
], { indentation: 2, spacer: "\n", stripAnsi: this.opts.stripAnsi }));
|
|
16
16
|
return `${base}\n\n${auth}\n\n${config}\n\n${examples}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "highspot-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Agent-first CLI for the Highspot API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Advait Shinde",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"highspot-cli": "dist/bin/highspot.js"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsc -p tsconfig.build.json",
|
|
21
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
|
|
22
22
|
"dev": "npm run build && node dist/bin/highspot.js",
|
|
23
23
|
"lint": "biome check .",
|
|
24
24
|
"format": "biome format --write .",
|
package/dist/commands/content.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Args } from "@oclif/core";
|
|
2
|
-
import { BaseCommand } from "../lib/command.js";
|
|
3
|
-
import { contentFlags, globalFlags } from "../lib/flags.js";
|
|
4
|
-
export default class Content extends BaseCommand {
|
|
5
|
-
static description = "Fetch Highspot item content";
|
|
6
|
-
static examples = [
|
|
7
|
-
"highspot content it_abc123",
|
|
8
|
-
"highspot content it_abc123 --format text/plain --plain",
|
|
9
|
-
"highspot content it_abc123 --start cursor-2",
|
|
10
|
-
];
|
|
11
|
-
static args = {
|
|
12
|
-
itemId: Args.string({
|
|
13
|
-
description: "Highspot item id",
|
|
14
|
-
required: false,
|
|
15
|
-
}),
|
|
16
|
-
};
|
|
17
|
-
static flags = {
|
|
18
|
-
...globalFlags,
|
|
19
|
-
...contentFlags,
|
|
20
|
-
};
|
|
21
|
-
async run() {
|
|
22
|
-
const { args, flags } = await this.parse(Content);
|
|
23
|
-
this.ensureOutputFlags(flags);
|
|
24
|
-
this.ensureVerbosityFlags(flags);
|
|
25
|
-
if (!args.itemId) {
|
|
26
|
-
this.fail("itemId is required", 2, flags);
|
|
27
|
-
}
|
|
28
|
-
const payload = {
|
|
29
|
-
endpoint: `/items/${encodeURIComponent(args.itemId)}/content`,
|
|
30
|
-
query: {
|
|
31
|
-
...(flags.format ? { format: flags.format } : {}),
|
|
32
|
-
...(flags.start ? { start: flags.start } : {}),
|
|
33
|
-
},
|
|
34
|
-
headers: {
|
|
35
|
-
...(flags["hs-user"] ? { "hs-user": flags["hs-user"] } : {}),
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
if (flags["dry-run"]) {
|
|
39
|
-
this.printJson(payload);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
const client = this.clientFromFlags(flags);
|
|
44
|
-
const data = await client.getItemContent({
|
|
45
|
-
itemId: args.itemId,
|
|
46
|
-
format: flags.format,
|
|
47
|
-
start: flags.start,
|
|
48
|
-
hsUser: this.effectiveHsUser(flags),
|
|
49
|
-
});
|
|
50
|
-
if (this.outputMode(flags) === "plain") {
|
|
51
|
-
writeContentPlain(data.content);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.printJson(data);
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
this.handleError(error, flags);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function writeContentPlain(content) {
|
|
62
|
-
if (typeof content === "string") {
|
|
63
|
-
process.stdout.write(content);
|
|
64
|
-
if (!content.endsWith("\n")) {
|
|
65
|
-
process.stdout.write("\n");
|
|
66
|
-
}
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
process.stdout.write(`${JSON.stringify(content, null, 2)}\n`);
|
|
70
|
-
}
|
package/dist/commands/item.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { Args } from "@oclif/core";
|
|
2
|
-
import { BaseCommand } from "../lib/command.js";
|
|
3
|
-
import { globalFlags } from "../lib/flags.js";
|
|
4
|
-
export default class Item extends BaseCommand {
|
|
5
|
-
static description = "Fetch metadata for a Highspot item";
|
|
6
|
-
static examples = [
|
|
7
|
-
"highspot item it_abc123",
|
|
8
|
-
"highspot item it_abc123 --hs-user user@example.com",
|
|
9
|
-
"highspot item it_abc123 --plain",
|
|
10
|
-
];
|
|
11
|
-
static args = {
|
|
12
|
-
itemId: Args.string({
|
|
13
|
-
description: "Highspot item id",
|
|
14
|
-
required: false,
|
|
15
|
-
}),
|
|
16
|
-
};
|
|
17
|
-
static flags = {
|
|
18
|
-
...globalFlags,
|
|
19
|
-
};
|
|
20
|
-
async run() {
|
|
21
|
-
const { args, flags } = await this.parse(Item);
|
|
22
|
-
this.ensureOutputFlags(flags);
|
|
23
|
-
this.ensureVerbosityFlags(flags);
|
|
24
|
-
if (!args.itemId) {
|
|
25
|
-
this.fail("itemId is required", 2, flags);
|
|
26
|
-
}
|
|
27
|
-
const payload = {
|
|
28
|
-
endpoint: `/items/${encodeURIComponent(args.itemId)}`,
|
|
29
|
-
headers: {
|
|
30
|
-
...(flags["hs-user"] ? { "hs-user": flags["hs-user"] } : {}),
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
if (flags["dry-run"]) {
|
|
34
|
-
this.printJson(payload);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
const client = this.clientFromFlags(flags);
|
|
39
|
-
const data = await client.getItem({
|
|
40
|
-
itemId: args.itemId,
|
|
41
|
-
hsUser: this.effectiveHsUser(flags),
|
|
42
|
-
});
|
|
43
|
-
if (this.outputMode(flags) === "plain") {
|
|
44
|
-
writeItemPlain(data.item);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
this.printJson(data);
|
|
48
|
-
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
this.handleError(error, flags);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function writeItemPlain(item) {
|
|
55
|
-
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
56
|
-
process.stdout.write(`${JSON.stringify(item)}\n`);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const record = item;
|
|
60
|
-
const id = typeof record.id === "string" ? record.id : "";
|
|
61
|
-
const title = typeof record.title === "string" ? record.title : "";
|
|
62
|
-
const url = typeof record.url === "string" ? record.url : "";
|
|
63
|
-
const contentType = typeof record.content_type === "string" ? record.content_type : "";
|
|
64
|
-
const description = typeof record.description === "string" ? record.description : "";
|
|
65
|
-
process.stdout.write(`${id}\t${url}\t${title}\t${contentType}\t${description}\n`);
|
|
66
|
-
}
|