@gscdump/cli 2.1.0 → 2.1.1
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 +1 -1
- package/dist/analysis-local.mjs +2 -1
- package/dist/auth.mjs +1 -1
- package/dist/cli.mjs +2 -1
- package/dist/commands/analyze.mjs +19 -18
- package/dist/commands/config.mjs +172 -166
- package/dist/commands/doctor.mjs +1 -1
- package/dist/commands/dump.mjs +2 -1
- package/dist/commands/entities.mjs +241 -237
- package/dist/commands/indexing.mjs +159 -154
- package/dist/commands/inspect.mjs +0 -7
- package/dist/commands/profile.mjs +146 -140
- package/dist/commands/report.mjs +35 -32
- package/dist/commands/rollups.mjs +91 -90
- package/dist/commands/sitemaps.mjs +392 -382
- package/dist/commands/sites.mjs +23 -17
- package/dist/commands/stats.mjs +2 -2
- package/dist/mcp/handlers/diagnostics.mjs +1 -1
- package/dist/mcp/handlers/reports.mjs +12 -10
- package/dist/mcp/server/index.mjs +14 -7
- package/dist/package.mjs +1 -1
- package/package.json +6 -6
|
@@ -43,10 +43,11 @@ const submitCommand = defineCommand({
|
|
|
43
43
|
},
|
|
44
44
|
async run({ args }) {
|
|
45
45
|
applyOutputMode(args);
|
|
46
|
-
const
|
|
46
|
+
const ctx = await createCommandContext({
|
|
47
47
|
needsAuth: true,
|
|
48
48
|
fetchOptions: { retry: parseRetries(args.retries) }
|
|
49
|
-
})
|
|
49
|
+
});
|
|
50
|
+
const result = await requestIndexing(ctx.client, args.url, { type: "URL_UPDATED" }).catch(gscErrorHandler);
|
|
50
51
|
if (args.json) {
|
|
51
52
|
console.log(JSON.stringify(result, null, 2));
|
|
52
53
|
return;
|
|
@@ -71,10 +72,11 @@ const removeCommand = defineCommand({
|
|
|
71
72
|
},
|
|
72
73
|
async run({ args }) {
|
|
73
74
|
applyOutputMode(args);
|
|
74
|
-
const
|
|
75
|
+
const ctx = await createCommandContext({
|
|
75
76
|
needsAuth: true,
|
|
76
77
|
fetchOptions: { retry: parseRetries(args.retries) }
|
|
77
|
-
})
|
|
78
|
+
});
|
|
79
|
+
const result = await requestIndexing(ctx.client, args.url, { type: "URL_DELETED" }).catch(gscErrorHandler);
|
|
78
80
|
if (args.json) {
|
|
79
81
|
console.log(JSON.stringify(result, null, 2));
|
|
80
82
|
return;
|
|
@@ -108,7 +110,8 @@ const statusCommand = defineCommand({
|
|
|
108
110
|
},
|
|
109
111
|
async run({ args }) {
|
|
110
112
|
applyOutputMode(args);
|
|
111
|
-
const
|
|
113
|
+
const ctx = await createCommandContext({ needsAuth: true });
|
|
114
|
+
const meta = await getIndexingMetadata(ctx.client, args.url).catch(gscErrorHandler);
|
|
112
115
|
if (args.json) {
|
|
113
116
|
console.log(JSON.stringify(meta, null, 2));
|
|
114
117
|
return;
|
|
@@ -156,6 +159,155 @@ const quotaCommand = defineCommand({
|
|
|
156
159
|
console.log();
|
|
157
160
|
}
|
|
158
161
|
});
|
|
162
|
+
const batchCommand = defineCommand({
|
|
163
|
+
meta: {
|
|
164
|
+
name: "batch",
|
|
165
|
+
description: "Submit many URLs from a file or stdin (one URL per line)"
|
|
166
|
+
},
|
|
167
|
+
args: {
|
|
168
|
+
...OUTPUT_ARGS,
|
|
169
|
+
"urls": {
|
|
170
|
+
type: "positional",
|
|
171
|
+
required: false,
|
|
172
|
+
description: "URLs (or use --file/--from-sitemap/stdin)"
|
|
173
|
+
},
|
|
174
|
+
"file": {
|
|
175
|
+
type: "string",
|
|
176
|
+
alias: "f",
|
|
177
|
+
description: "File with URLs (one per line)"
|
|
178
|
+
},
|
|
179
|
+
"from-sitemap": {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "Sitemap URL (or sitemap index) to pull URLs from"
|
|
182
|
+
},
|
|
183
|
+
"type": {
|
|
184
|
+
type: "string",
|
|
185
|
+
default: "URL_UPDATED",
|
|
186
|
+
description: "URL_UPDATED or URL_DELETED"
|
|
187
|
+
},
|
|
188
|
+
"delay-ms": {
|
|
189
|
+
type: "string",
|
|
190
|
+
default: "100",
|
|
191
|
+
description: "Delay between requests"
|
|
192
|
+
},
|
|
193
|
+
"concurrency": {
|
|
194
|
+
type: "string",
|
|
195
|
+
alias: "c",
|
|
196
|
+
default: "1",
|
|
197
|
+
description: "Concurrent in-flight requests"
|
|
198
|
+
},
|
|
199
|
+
"yes": {
|
|
200
|
+
type: "boolean",
|
|
201
|
+
alias: "y",
|
|
202
|
+
default: false,
|
|
203
|
+
description: "Skip the over-quota confirmation prompt"
|
|
204
|
+
},
|
|
205
|
+
"retries": {
|
|
206
|
+
type: "string",
|
|
207
|
+
description: "Override per-call retry count (default: 3)"
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
async run({ args }) {
|
|
211
|
+
applyOutputMode(args);
|
|
212
|
+
const urls = await resolveUrlSource(args);
|
|
213
|
+
if (urls.length === 0) {
|
|
214
|
+
logger.error("No URLs provided. Pass URLs as args, --file, --from-sitemap, or stdin.");
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
const type = String(args.type);
|
|
218
|
+
if (type !== "URL_UPDATED" && type !== "URL_DELETED") {
|
|
219
|
+
logger.error(`Invalid --type: ${type}. Use URL_UPDATED or URL_DELETED.`);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
if (urls.length > INDEXING_DAILY_QUOTA && !args.yes && !args.json) {
|
|
223
|
+
logger.warn(`Submitting ${urls.length} URLs but the Indexing API daily quota is ${INDEXING_DAILY_QUOTA}/day.`);
|
|
224
|
+
logger.warn(`Excess submissions will fail with quota errors. Pass --yes to proceed anyway.`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
if (urls.length > INDEXING_DAILY_QUOTA && !args.json && !args.quiet) logger.warn(`Proceeding with ${urls.length} URLs (over the ${INDEXING_DAILY_QUOTA}/day quota). Excess will fail.`);
|
|
228
|
+
const ctx = await createCommandContext({
|
|
229
|
+
needsAuth: true,
|
|
230
|
+
fetchOptions: { retry: parseRetries(args.retries) }
|
|
231
|
+
});
|
|
232
|
+
const delayMs = Number.parseInt(String(args["delay-ms"]), 10);
|
|
233
|
+
const concurrency = Math.max(1, Number.parseInt(String(args.concurrency), 10) || 1);
|
|
234
|
+
if (!args.json && !args.quiet) logger.info(`Submitting ${urls.length} URLs (${type}) ...`);
|
|
235
|
+
const results = await batchRequestIndexing(ctx.client, urls, {
|
|
236
|
+
type,
|
|
237
|
+
delayMs,
|
|
238
|
+
concurrency,
|
|
239
|
+
onProgress: args.json || args.quiet ? void 0 : (r, i, total) => logger.info(`[${i + 1}/${total}] ${r.url}`)
|
|
240
|
+
}).catch(gscErrorHandler);
|
|
241
|
+
if (args.json) {
|
|
242
|
+
console.log(JSON.stringify(results, null, 2));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!args.quiet) logger.success(`Submitted ${results.length}/${urls.length} URLs`);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const batchStatusCommand = defineCommand({
|
|
249
|
+
meta: {
|
|
250
|
+
name: "batch-status",
|
|
251
|
+
description: "Get indexing notification metadata for many URLs"
|
|
252
|
+
},
|
|
253
|
+
args: {
|
|
254
|
+
...OUTPUT_ARGS,
|
|
255
|
+
"urls": {
|
|
256
|
+
type: "positional",
|
|
257
|
+
required: false,
|
|
258
|
+
description: "URLs (or use --file/--from-sitemap/stdin)"
|
|
259
|
+
},
|
|
260
|
+
"file": {
|
|
261
|
+
type: "string",
|
|
262
|
+
alias: "f",
|
|
263
|
+
description: "File with URLs (one per line)"
|
|
264
|
+
},
|
|
265
|
+
"from-sitemap": {
|
|
266
|
+
type: "string",
|
|
267
|
+
description: "Sitemap URL (or sitemap index) to pull URLs from"
|
|
268
|
+
},
|
|
269
|
+
"delay-ms": {
|
|
270
|
+
type: "string",
|
|
271
|
+
default: "100",
|
|
272
|
+
description: "Delay between requests"
|
|
273
|
+
},
|
|
274
|
+
"concurrency": {
|
|
275
|
+
type: "string",
|
|
276
|
+
alias: "c",
|
|
277
|
+
default: "1",
|
|
278
|
+
description: "Concurrent in-flight requests"
|
|
279
|
+
},
|
|
280
|
+
"retries": {
|
|
281
|
+
type: "string",
|
|
282
|
+
description: "Override per-call retry count (default: 3)"
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
async run({ args }) {
|
|
286
|
+
applyOutputMode(args);
|
|
287
|
+
const urls = await resolveUrlSource(args);
|
|
288
|
+
if (urls.length === 0) {
|
|
289
|
+
logger.error("No URLs provided. Pass URLs as args, --file, --from-sitemap, or stdin.");
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
const ctx = await createCommandContext({
|
|
293
|
+
needsAuth: true,
|
|
294
|
+
fetchOptions: { retry: parseRetries(args.retries) }
|
|
295
|
+
});
|
|
296
|
+
const delayMs = Number.parseInt(String(args["delay-ms"]), 10);
|
|
297
|
+
const concurrency = Math.max(1, Number.parseInt(String(args.concurrency), 10) || 1);
|
|
298
|
+
if (!args.json && !args.quiet) logger.info(`Fetching status for ${urls.length} URLs ...`);
|
|
299
|
+
const results = await runSequentialBatch(urls, (url) => getIndexingMetadata(ctx.client, url), {
|
|
300
|
+
delayMs,
|
|
301
|
+
concurrency,
|
|
302
|
+
onProgress: args.json || args.quiet ? void 0 : (r, i, total) => logger.info(`[${i + 1}/${total}] ${r.url}`)
|
|
303
|
+
}).catch(gscErrorHandler);
|
|
304
|
+
if (args.json) {
|
|
305
|
+
console.log(JSON.stringify(results, null, 2));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (!args.quiet) logger.success(`Fetched ${results.length}/${urls.length} URLs`);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
159
311
|
const indexingCommand = defineCommand({
|
|
160
312
|
meta: {
|
|
161
313
|
name: "indexing",
|
|
@@ -165,155 +317,8 @@ const indexingCommand = defineCommand({
|
|
|
165
317
|
"submit": submitCommand,
|
|
166
318
|
"remove": removeCommand,
|
|
167
319
|
"status": statusCommand,
|
|
168
|
-
"batch":
|
|
169
|
-
|
|
170
|
-
name: "batch",
|
|
171
|
-
description: "Submit many URLs from a file or stdin (one URL per line)"
|
|
172
|
-
},
|
|
173
|
-
args: {
|
|
174
|
-
...OUTPUT_ARGS,
|
|
175
|
-
"urls": {
|
|
176
|
-
type: "positional",
|
|
177
|
-
required: false,
|
|
178
|
-
description: "URLs (or use --file/--from-sitemap/stdin)"
|
|
179
|
-
},
|
|
180
|
-
"file": {
|
|
181
|
-
type: "string",
|
|
182
|
-
alias: "f",
|
|
183
|
-
description: "File with URLs (one per line)"
|
|
184
|
-
},
|
|
185
|
-
"from-sitemap": {
|
|
186
|
-
type: "string",
|
|
187
|
-
description: "Sitemap URL (or sitemap index) to pull URLs from"
|
|
188
|
-
},
|
|
189
|
-
"type": {
|
|
190
|
-
type: "string",
|
|
191
|
-
default: "URL_UPDATED",
|
|
192
|
-
description: "URL_UPDATED or URL_DELETED"
|
|
193
|
-
},
|
|
194
|
-
"delay-ms": {
|
|
195
|
-
type: "string",
|
|
196
|
-
default: "100",
|
|
197
|
-
description: "Delay between requests"
|
|
198
|
-
},
|
|
199
|
-
"concurrency": {
|
|
200
|
-
type: "string",
|
|
201
|
-
alias: "c",
|
|
202
|
-
default: "1",
|
|
203
|
-
description: "Concurrent in-flight requests"
|
|
204
|
-
},
|
|
205
|
-
"yes": {
|
|
206
|
-
type: "boolean",
|
|
207
|
-
alias: "y",
|
|
208
|
-
default: false,
|
|
209
|
-
description: "Skip the over-quota confirmation prompt"
|
|
210
|
-
},
|
|
211
|
-
"retries": {
|
|
212
|
-
type: "string",
|
|
213
|
-
description: "Override per-call retry count (default: 3)"
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
async run({ args }) {
|
|
217
|
-
applyOutputMode(args);
|
|
218
|
-
const urls = await resolveUrlSource(args);
|
|
219
|
-
if (urls.length === 0) {
|
|
220
|
-
logger.error("No URLs provided. Pass URLs as args, --file, --from-sitemap, or stdin.");
|
|
221
|
-
process.exit(1);
|
|
222
|
-
}
|
|
223
|
-
const type = String(args.type);
|
|
224
|
-
if (type !== "URL_UPDATED" && type !== "URL_DELETED") {
|
|
225
|
-
logger.error(`Invalid --type: ${type}. Use URL_UPDATED or URL_DELETED.`);
|
|
226
|
-
process.exit(1);
|
|
227
|
-
}
|
|
228
|
-
if (urls.length > INDEXING_DAILY_QUOTA && !args.yes && !args.json) {
|
|
229
|
-
logger.warn(`Submitting ${urls.length} URLs but the Indexing API daily quota is ${INDEXING_DAILY_QUOTA}/day.`);
|
|
230
|
-
logger.warn(`Excess submissions will fail with quota errors. Pass --yes to proceed anyway.`);
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
if (urls.length > INDEXING_DAILY_QUOTA && !args.json && !args.quiet) logger.warn(`Proceeding with ${urls.length} URLs (over the ${INDEXING_DAILY_QUOTA}/day quota). Excess will fail.`);
|
|
234
|
-
const ctx = await createCommandContext({
|
|
235
|
-
needsAuth: true,
|
|
236
|
-
fetchOptions: { retry: parseRetries(args.retries) }
|
|
237
|
-
});
|
|
238
|
-
const delayMs = Number.parseInt(String(args["delay-ms"]), 10);
|
|
239
|
-
const concurrency = Math.max(1, Number.parseInt(String(args.concurrency), 10) || 1);
|
|
240
|
-
if (!args.json && !args.quiet) logger.info(`Submitting ${urls.length} URLs (${type}) ...`);
|
|
241
|
-
const results = await batchRequestIndexing(ctx.client, urls, {
|
|
242
|
-
type,
|
|
243
|
-
delayMs,
|
|
244
|
-
concurrency,
|
|
245
|
-
onProgress: args.json || args.quiet ? void 0 : (r, i, total) => logger.info(`[${i + 1}/${total}] ${r.url}`)
|
|
246
|
-
}).catch(gscErrorHandler);
|
|
247
|
-
if (args.json) {
|
|
248
|
-
console.log(JSON.stringify(results, null, 2));
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
if (!args.quiet) logger.success(`Submitted ${results.length}/${urls.length} URLs`);
|
|
252
|
-
}
|
|
253
|
-
}),
|
|
254
|
-
"batch-status": defineCommand({
|
|
255
|
-
meta: {
|
|
256
|
-
name: "batch-status",
|
|
257
|
-
description: "Get indexing notification metadata for many URLs"
|
|
258
|
-
},
|
|
259
|
-
args: {
|
|
260
|
-
...OUTPUT_ARGS,
|
|
261
|
-
"urls": {
|
|
262
|
-
type: "positional",
|
|
263
|
-
required: false,
|
|
264
|
-
description: "URLs (or use --file/--from-sitemap/stdin)"
|
|
265
|
-
},
|
|
266
|
-
"file": {
|
|
267
|
-
type: "string",
|
|
268
|
-
alias: "f",
|
|
269
|
-
description: "File with URLs (one per line)"
|
|
270
|
-
},
|
|
271
|
-
"from-sitemap": {
|
|
272
|
-
type: "string",
|
|
273
|
-
description: "Sitemap URL (or sitemap index) to pull URLs from"
|
|
274
|
-
},
|
|
275
|
-
"delay-ms": {
|
|
276
|
-
type: "string",
|
|
277
|
-
default: "100",
|
|
278
|
-
description: "Delay between requests"
|
|
279
|
-
},
|
|
280
|
-
"concurrency": {
|
|
281
|
-
type: "string",
|
|
282
|
-
alias: "c",
|
|
283
|
-
default: "1",
|
|
284
|
-
description: "Concurrent in-flight requests"
|
|
285
|
-
},
|
|
286
|
-
"retries": {
|
|
287
|
-
type: "string",
|
|
288
|
-
description: "Override per-call retry count (default: 3)"
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
|
-
async run({ args }) {
|
|
292
|
-
applyOutputMode(args);
|
|
293
|
-
const urls = await resolveUrlSource(args);
|
|
294
|
-
if (urls.length === 0) {
|
|
295
|
-
logger.error("No URLs provided. Pass URLs as args, --file, --from-sitemap, or stdin.");
|
|
296
|
-
process.exit(1);
|
|
297
|
-
}
|
|
298
|
-
const ctx = await createCommandContext({
|
|
299
|
-
needsAuth: true,
|
|
300
|
-
fetchOptions: { retry: parseRetries(args.retries) }
|
|
301
|
-
});
|
|
302
|
-
const delayMs = Number.parseInt(String(args["delay-ms"]), 10);
|
|
303
|
-
const concurrency = Math.max(1, Number.parseInt(String(args.concurrency), 10) || 1);
|
|
304
|
-
if (!args.json && !args.quiet) logger.info(`Fetching status for ${urls.length} URLs ...`);
|
|
305
|
-
const results = await runSequentialBatch(urls, (url) => getIndexingMetadata(ctx.client, url), {
|
|
306
|
-
delayMs,
|
|
307
|
-
concurrency,
|
|
308
|
-
onProgress: args.json || args.quiet ? void 0 : (r, i, total) => logger.info(`[${i + 1}/${total}] ${r.url}`)
|
|
309
|
-
}).catch(gscErrorHandler);
|
|
310
|
-
if (args.json) {
|
|
311
|
-
console.log(JSON.stringify(results, null, 2));
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
if (!args.quiet) logger.success(`Fetched ${results.length}/${urls.length} URLs`);
|
|
315
|
-
}
|
|
316
|
-
}),
|
|
320
|
+
"batch": batchCommand,
|
|
321
|
+
"batch-status": batchStatusCommand,
|
|
317
322
|
"quota": quotaCommand
|
|
318
323
|
}
|
|
319
324
|
});
|
|
@@ -69,13 +69,6 @@ function printInspection(url, inspection) {
|
|
|
69
69
|
console.log(` ${sev}${issue.severity ?? "?"}\x1B[0m ${issue.issueMessage ?? ""}`);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
const mobile = inspection?.mobileUsabilityResult;
|
|
73
|
-
if (mobile) {
|
|
74
|
-
console.log();
|
|
75
|
-
console.log(` \x1B[1mMobile usability\x1B[0m`);
|
|
76
|
-
console.log(` Verdict: ${colorVerdict(mobile.verdict)}`);
|
|
77
|
-
if (mobile.issues?.length) for (const issue of mobile.issues) console.log(` \x1B[33m${issue.issueType ?? "?"}\x1B[0m ${issue.message ?? ""}`);
|
|
78
|
-
}
|
|
79
72
|
if (inspection?.inspectionResultLink) {
|
|
80
73
|
console.log();
|
|
81
74
|
console.log(` \x1B[90mOpen in Search Console:\x1B[0m \x1B[36m${inspection.inspectionResultLink}\x1B[0m`);
|
|
@@ -112,6 +112,146 @@ const listCmd = defineCommand({
|
|
|
112
112
|
for (const n of names) console.log(`${n === active ? "*" : " "} ${n}`);
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
|
+
const pathCmd = defineCommand({
|
|
116
|
+
meta: {
|
|
117
|
+
name: "path",
|
|
118
|
+
description: "Print the config directory for a profile"
|
|
119
|
+
},
|
|
120
|
+
args: { name: {
|
|
121
|
+
type: "positional",
|
|
122
|
+
required: false,
|
|
123
|
+
description: "Profile name (default: active)"
|
|
124
|
+
} },
|
|
125
|
+
async run({ args }) {
|
|
126
|
+
const name = args.name ? String(args.name) : resolveActiveProfile();
|
|
127
|
+
if (!name) {
|
|
128
|
+
logger.error("No profile specified and none active (set --profile, GSCDUMP_PROFILE, or run `gscdump profile use <name>`)");
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
console.log(getProfileDir(name));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
const currentCmd = defineCommand({
|
|
135
|
+
meta: {
|
|
136
|
+
name: "current",
|
|
137
|
+
description: "Print the active profile name"
|
|
138
|
+
},
|
|
139
|
+
async run() {
|
|
140
|
+
const active = resolveActiveProfile();
|
|
141
|
+
if (!active) process.exit(1);
|
|
142
|
+
console.log(active);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const useCmd = defineCommand({
|
|
146
|
+
meta: {
|
|
147
|
+
name: "use",
|
|
148
|
+
description: "Set the persisted active profile (subsequent commands no longer need --profile)"
|
|
149
|
+
},
|
|
150
|
+
args: {
|
|
151
|
+
...OUTPUT_ARGS,
|
|
152
|
+
name: {
|
|
153
|
+
type: "positional",
|
|
154
|
+
required: true,
|
|
155
|
+
description: "Profile name"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
async run({ args }) {
|
|
159
|
+
applyOutputMode(args);
|
|
160
|
+
const name = String(args.name);
|
|
161
|
+
const dir = getProfileDir(name);
|
|
162
|
+
if (!await fs$1.stat(dir).then(() => true).catch(() => false)) {
|
|
163
|
+
logger.error(`Profile not found: ${name}`);
|
|
164
|
+
logger.info(`Create it with: gscdump profile create ${name}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
await setActiveProfile(name);
|
|
168
|
+
logger.success(`Active profile: ${name}`);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const createCmd = defineCommand({
|
|
172
|
+
meta: {
|
|
173
|
+
name: "create",
|
|
174
|
+
description: "Create an empty profile directory"
|
|
175
|
+
},
|
|
176
|
+
args: {
|
|
177
|
+
...OUTPUT_ARGS,
|
|
178
|
+
"name": {
|
|
179
|
+
type: "positional",
|
|
180
|
+
required: true,
|
|
181
|
+
description: "Profile name"
|
|
182
|
+
},
|
|
183
|
+
"no-use": {
|
|
184
|
+
type: "boolean",
|
|
185
|
+
default: false,
|
|
186
|
+
description: "Do not mark the new profile as active"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
async run({ args }) {
|
|
190
|
+
applyOutputMode(args);
|
|
191
|
+
const name = String(args.name);
|
|
192
|
+
const dir = await createProfile(name);
|
|
193
|
+
if (!args["no-use"]) await setActiveProfile(name);
|
|
194
|
+
logger.success(`Created profile: ${name}${args["no-use"] ? "" : " (active)"}`);
|
|
195
|
+
logger.info(displayPath(dir));
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
const clearCmd = defineCommand({
|
|
199
|
+
meta: {
|
|
200
|
+
name: "clear",
|
|
201
|
+
description: "Clear the persisted active profile (commands fall back to root config dir)"
|
|
202
|
+
},
|
|
203
|
+
args: { ...OUTPUT_ARGS },
|
|
204
|
+
async run({ args }) {
|
|
205
|
+
applyOutputMode(args);
|
|
206
|
+
await setActiveProfile(null);
|
|
207
|
+
logger.success("Cleared active profile");
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
const deleteCmd = defineCommand({
|
|
211
|
+
meta: {
|
|
212
|
+
name: "delete",
|
|
213
|
+
description: "Remove a profile directory (tokens + config)"
|
|
214
|
+
},
|
|
215
|
+
args: {
|
|
216
|
+
...OUTPUT_ARGS,
|
|
217
|
+
name: {
|
|
218
|
+
type: "positional",
|
|
219
|
+
required: true,
|
|
220
|
+
description: "Profile name"
|
|
221
|
+
},
|
|
222
|
+
yes: {
|
|
223
|
+
type: "boolean",
|
|
224
|
+
alias: "y",
|
|
225
|
+
default: false,
|
|
226
|
+
description: "Skip confirmation"
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
async run({ args }) {
|
|
230
|
+
applyOutputMode(args);
|
|
231
|
+
const name = String(args.name);
|
|
232
|
+
const dir = getProfileDir(name);
|
|
233
|
+
if (!await fs$1.stat(dir).then(() => true).catch(() => false)) {
|
|
234
|
+
logger.error(`Profile not found: ${name}`);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
if (!args.yes) {
|
|
238
|
+
const ok = await confirm({
|
|
239
|
+
message: `Delete profile "${name}" at ${dir}? Tokens and config will be lost.`,
|
|
240
|
+
initialValue: false
|
|
241
|
+
});
|
|
242
|
+
if (isCancel(ok) || !ok) {
|
|
243
|
+
logger.info("Cancelled");
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
await fs$1.rm(dir, {
|
|
248
|
+
recursive: true,
|
|
249
|
+
force: true
|
|
250
|
+
});
|
|
251
|
+
if (readActiveMarkerSync() === name) await setActiveProfile(null);
|
|
252
|
+
logger.success(`Removed profile: ${name}`);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
115
255
|
const profileCommand = defineCommand({
|
|
116
256
|
meta: {
|
|
117
257
|
name: "profile",
|
|
@@ -119,146 +259,12 @@ const profileCommand = defineCommand({
|
|
|
119
259
|
},
|
|
120
260
|
subCommands: {
|
|
121
261
|
list: listCmd,
|
|
122
|
-
path:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
type: "positional",
|
|
129
|
-
required: false,
|
|
130
|
-
description: "Profile name (default: active)"
|
|
131
|
-
} },
|
|
132
|
-
async run({ args }) {
|
|
133
|
-
const name = args.name ? String(args.name) : resolveActiveProfile();
|
|
134
|
-
if (!name) {
|
|
135
|
-
logger.error("No profile specified and none active (set --profile, GSCDUMP_PROFILE, or run `gscdump profile use <name>`)");
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
console.log(getProfileDir(name));
|
|
139
|
-
}
|
|
140
|
-
}),
|
|
141
|
-
current: defineCommand({
|
|
142
|
-
meta: {
|
|
143
|
-
name: "current",
|
|
144
|
-
description: "Print the active profile name"
|
|
145
|
-
},
|
|
146
|
-
async run() {
|
|
147
|
-
const active = resolveActiveProfile();
|
|
148
|
-
if (!active) process.exit(1);
|
|
149
|
-
console.log(active);
|
|
150
|
-
}
|
|
151
|
-
}),
|
|
152
|
-
use: defineCommand({
|
|
153
|
-
meta: {
|
|
154
|
-
name: "use",
|
|
155
|
-
description: "Set the persisted active profile (subsequent commands no longer need --profile)"
|
|
156
|
-
},
|
|
157
|
-
args: {
|
|
158
|
-
...OUTPUT_ARGS,
|
|
159
|
-
name: {
|
|
160
|
-
type: "positional",
|
|
161
|
-
required: true,
|
|
162
|
-
description: "Profile name"
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
async run({ args }) {
|
|
166
|
-
applyOutputMode(args);
|
|
167
|
-
const name = String(args.name);
|
|
168
|
-
const dir = getProfileDir(name);
|
|
169
|
-
if (!await fs$1.stat(dir).then(() => true).catch(() => false)) {
|
|
170
|
-
logger.error(`Profile not found: ${name}`);
|
|
171
|
-
logger.info(`Create it with: gscdump profile create ${name}`);
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
await setActiveProfile(name);
|
|
175
|
-
logger.success(`Active profile: ${name}`);
|
|
176
|
-
}
|
|
177
|
-
}),
|
|
178
|
-
create: defineCommand({
|
|
179
|
-
meta: {
|
|
180
|
-
name: "create",
|
|
181
|
-
description: "Create an empty profile directory"
|
|
182
|
-
},
|
|
183
|
-
args: {
|
|
184
|
-
...OUTPUT_ARGS,
|
|
185
|
-
"name": {
|
|
186
|
-
type: "positional",
|
|
187
|
-
required: true,
|
|
188
|
-
description: "Profile name"
|
|
189
|
-
},
|
|
190
|
-
"no-use": {
|
|
191
|
-
type: "boolean",
|
|
192
|
-
default: false,
|
|
193
|
-
description: "Do not mark the new profile as active"
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
async run({ args }) {
|
|
197
|
-
applyOutputMode(args);
|
|
198
|
-
const name = String(args.name);
|
|
199
|
-
const dir = await createProfile(name);
|
|
200
|
-
if (!args["no-use"]) await setActiveProfile(name);
|
|
201
|
-
logger.success(`Created profile: ${name}${args["no-use"] ? "" : " (active)"}`);
|
|
202
|
-
logger.info(displayPath(dir));
|
|
203
|
-
}
|
|
204
|
-
}),
|
|
205
|
-
clear: defineCommand({
|
|
206
|
-
meta: {
|
|
207
|
-
name: "clear",
|
|
208
|
-
description: "Clear the persisted active profile (commands fall back to root config dir)"
|
|
209
|
-
},
|
|
210
|
-
args: { ...OUTPUT_ARGS },
|
|
211
|
-
async run({ args }) {
|
|
212
|
-
applyOutputMode(args);
|
|
213
|
-
await setActiveProfile(null);
|
|
214
|
-
logger.success("Cleared active profile");
|
|
215
|
-
}
|
|
216
|
-
}),
|
|
217
|
-
delete: defineCommand({
|
|
218
|
-
meta: {
|
|
219
|
-
name: "delete",
|
|
220
|
-
description: "Remove a profile directory (tokens + config)"
|
|
221
|
-
},
|
|
222
|
-
args: {
|
|
223
|
-
...OUTPUT_ARGS,
|
|
224
|
-
name: {
|
|
225
|
-
type: "positional",
|
|
226
|
-
required: true,
|
|
227
|
-
description: "Profile name"
|
|
228
|
-
},
|
|
229
|
-
yes: {
|
|
230
|
-
type: "boolean",
|
|
231
|
-
alias: "y",
|
|
232
|
-
default: false,
|
|
233
|
-
description: "Skip confirmation"
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
async run({ args }) {
|
|
237
|
-
applyOutputMode(args);
|
|
238
|
-
const name = String(args.name);
|
|
239
|
-
const dir = getProfileDir(name);
|
|
240
|
-
if (!await fs$1.stat(dir).then(() => true).catch(() => false)) {
|
|
241
|
-
logger.error(`Profile not found: ${name}`);
|
|
242
|
-
process.exit(1);
|
|
243
|
-
}
|
|
244
|
-
if (!args.yes) {
|
|
245
|
-
const ok = await confirm({
|
|
246
|
-
message: `Delete profile "${name}" at ${dir}? Tokens and config will be lost.`,
|
|
247
|
-
initialValue: false
|
|
248
|
-
});
|
|
249
|
-
if (isCancel(ok) || !ok) {
|
|
250
|
-
logger.info("Cancelled");
|
|
251
|
-
process.exit(0);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
await fs$1.rm(dir, {
|
|
255
|
-
recursive: true,
|
|
256
|
-
force: true
|
|
257
|
-
});
|
|
258
|
-
if (readActiveMarkerSync() === name) await setActiveProfile(null);
|
|
259
|
-
logger.success(`Removed profile: ${name}`);
|
|
260
|
-
}
|
|
261
|
-
})
|
|
262
|
+
path: pathCmd,
|
|
263
|
+
current: currentCmd,
|
|
264
|
+
use: useCmd,
|
|
265
|
+
create: createCmd,
|
|
266
|
+
clear: clearCmd,
|
|
267
|
+
delete: deleteCmd
|
|
262
268
|
},
|
|
263
269
|
async run({ args }) {
|
|
264
270
|
if (!noSubcommandSelected("profile", [
|