@bigcommerce/catalyst 1.1.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/dist/cli.js +127 -35
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ import { randomBytes, randomUUID } from "crypto";
|
|
|
25
25
|
// package.json
|
|
26
26
|
var package_default = {
|
|
27
27
|
name: "@bigcommerce/catalyst",
|
|
28
|
-
version: "1.
|
|
28
|
+
version: "1.2.0",
|
|
29
29
|
type: "module",
|
|
30
30
|
repository: {
|
|
31
31
|
type: "git",
|
|
@@ -119,6 +119,8 @@ function getUserConfig() {
|
|
|
119
119
|
// src/cli/lib/telemetry.ts
|
|
120
120
|
var TELEMETRY_KEY_ENABLED = "telemetry.enabled";
|
|
121
121
|
var TELEMETRY_KEY_ID = `telemetry.anonymousId`;
|
|
122
|
+
var TELEMETRY_FLUSH_INTERVAL_MS = 200;
|
|
123
|
+
var TELEMETRY_HTTP_REQUEST_TIMEOUT_MS = 200;
|
|
122
124
|
var Telemetry = class {
|
|
123
125
|
constructor() {
|
|
124
126
|
this.commandName = "unknown";
|
|
@@ -133,7 +135,10 @@ var Telemetry = class {
|
|
|
133
135
|
this.correlationId = randomUUID();
|
|
134
136
|
this.startTime = Date.now();
|
|
135
137
|
this.analytics = new Analytics({
|
|
136
|
-
writeKey: "OCkxLj3KTc1N3ebEbnFBqbhxfE3tVb3Z"
|
|
138
|
+
writeKey: "OCkxLj3KTc1N3ebEbnFBqbhxfE3tVb3Z",
|
|
139
|
+
flushInterval: TELEMETRY_FLUSH_INTERVAL_MS,
|
|
140
|
+
httpRequestTimeout: TELEMETRY_HTTP_REQUEST_TIMEOUT_MS,
|
|
141
|
+
maxRetries: 0
|
|
137
142
|
});
|
|
138
143
|
}
|
|
139
144
|
durationMs() {
|
|
@@ -2712,7 +2717,7 @@ function collectDiagnostics({
|
|
|
2712
2717
|
env: env2 = process.env
|
|
2713
2718
|
} = {}) {
|
|
2714
2719
|
const state = getProjectState(cwd);
|
|
2715
|
-
const
|
|
2720
|
+
const telemetry2 = getTelemetry();
|
|
2716
2721
|
const projectJson = readProjectJson(cwd);
|
|
2717
2722
|
const storefront = readStorefrontInfo(cwd);
|
|
2718
2723
|
const cliEnv = [{ source: "process.env", values: env2 }];
|
|
@@ -2764,8 +2769,8 @@ function collectDiagnostics({
|
|
|
2764
2769
|
buildEnvVars: resolveEnvVars(buildEnv, BUILD_ENV_VARS)
|
|
2765
2770
|
},
|
|
2766
2771
|
telemetry: {
|
|
2767
|
-
enabled:
|
|
2768
|
-
correlationId:
|
|
2772
|
+
enabled: telemetry2.isEnabled(),
|
|
2773
|
+
correlationId: telemetry2.correlationId
|
|
2769
2774
|
},
|
|
2770
2775
|
files: {
|
|
2771
2776
|
".env.local": existsSync5(join11(cwd, ".env.local")),
|
|
@@ -3147,8 +3152,8 @@ Example:
|
|
|
3147
3152
|
const config2 = getProjectConfig();
|
|
3148
3153
|
const apiHost = resolveApiHost(options, config2);
|
|
3149
3154
|
const { storeHash, accessToken } = resolveCredentials(options, config2);
|
|
3150
|
-
const
|
|
3151
|
-
await
|
|
3155
|
+
const telemetry2 = getTelemetry();
|
|
3156
|
+
await telemetry2.identify(storeHash);
|
|
3152
3157
|
const linkedProjectUuid = options.projectUuid ?? config2.get("projectUuid");
|
|
3153
3158
|
let projectUuid;
|
|
3154
3159
|
const promptForProject = async () => {
|
|
@@ -3301,7 +3306,22 @@ var logEntrySchema = z14.object({
|
|
|
3301
3306
|
}).nullable().optional()
|
|
3302
3307
|
});
|
|
3303
3308
|
var queryLogsSchema = z14.object({
|
|
3304
|
-
data: z14.array(logEntrySchema)
|
|
3309
|
+
data: z14.array(logEntrySchema),
|
|
3310
|
+
meta: z14.object({
|
|
3311
|
+
cursor_pagination: z14.object({
|
|
3312
|
+
// The REST proxy exposes page availability via links, while the
|
|
3313
|
+
// gRPC response uses has_next_page/has_prev_page. Accept both while
|
|
3314
|
+
// the API contract is transitioning.
|
|
3315
|
+
has_next_page: z14.boolean().optional(),
|
|
3316
|
+
has_prev_page: z14.boolean().optional(),
|
|
3317
|
+
start_cursor: z14.string().nullable().optional(),
|
|
3318
|
+
end_cursor: z14.string().nullable().optional(),
|
|
3319
|
+
links: z14.object({
|
|
3320
|
+
next: z14.string().optional(),
|
|
3321
|
+
previous: z14.string().optional()
|
|
3322
|
+
}).optional()
|
|
3323
|
+
}).optional()
|
|
3324
|
+
}).optional()
|
|
3305
3325
|
});
|
|
3306
3326
|
var v3ErrorSchema = z14.object({
|
|
3307
3327
|
title: z14.string().optional(),
|
|
@@ -3416,6 +3436,8 @@ async function queryLogs(projectUuid, storeHash, accessToken, apiHost, params) {
|
|
|
3416
3436
|
if (params.urlLike) search.set("url:like", params.urlLike);
|
|
3417
3437
|
if (params.levelMin) search.set("level:min", params.levelMin);
|
|
3418
3438
|
if (params.limit != null) search.set("limit", String(params.limit));
|
|
3439
|
+
if (params.after) search.set("after", params.after);
|
|
3440
|
+
if (params.before) search.set("before", params.before);
|
|
3419
3441
|
const response = await fetch(
|
|
3420
3442
|
`https://${apiHost}/stores/${storeHash}/v3/infrastructure/logs/${projectUuid}?${search.toString()}`,
|
|
3421
3443
|
{
|
|
@@ -3434,7 +3456,9 @@ async function queryLogs(projectUuid, storeHash, accessToken, apiHost, params) {
|
|
|
3434
3456
|
);
|
|
3435
3457
|
}
|
|
3436
3458
|
if (response.status === 404) {
|
|
3437
|
-
throw new UserActionableError(
|
|
3459
|
+
throw new UserActionableError(
|
|
3460
|
+
"Project not found. Check the project UUID, and that --store-hash and --access-token belong to the store that owns the project."
|
|
3461
|
+
);
|
|
3438
3462
|
}
|
|
3439
3463
|
if (response.status === 400 || response.status === 422) {
|
|
3440
3464
|
const body = await response.json().catch(() => null);
|
|
@@ -4083,7 +4107,6 @@ var env = new Command8("env").configureHelp({ showGlobalOptions: true }).descrip
|
|
|
4083
4107
|
import { Command as Command9, InvalidArgumentError as InvalidArgumentError4, Option as Option8 } from "commander";
|
|
4084
4108
|
import { colorize as colorize10 } from "consola/utils";
|
|
4085
4109
|
import { z as z16 } from "zod";
|
|
4086
|
-
var telemetry = new Telemetry();
|
|
4087
4110
|
var DEFAULT_CONNECTION_TTL_MS = 1 * 60 * 1e3;
|
|
4088
4111
|
var MAX_RETRIES = 5;
|
|
4089
4112
|
var isFatalStatusCode = (status) => status >= 400 && status < 500;
|
|
@@ -4282,7 +4305,7 @@ Examples:
|
|
|
4282
4305
|
const config2 = getProjectConfig();
|
|
4283
4306
|
const apiHost = resolveApiHost(options, config2);
|
|
4284
4307
|
const { storeHash, accessToken } = resolveCredentials(options, config2);
|
|
4285
|
-
await
|
|
4308
|
+
await getTelemetry().identify(storeHash);
|
|
4286
4309
|
const projectUuid = resolveProjectUuid(options);
|
|
4287
4310
|
await tailLogs(projectUuid, storeHash, accessToken, apiHost, options.format);
|
|
4288
4311
|
} catch (error) {
|
|
@@ -4297,17 +4320,68 @@ var parseIntInRange = (flag, min, max) => (value) => {
|
|
|
4297
4320
|
}
|
|
4298
4321
|
return parsed;
|
|
4299
4322
|
};
|
|
4323
|
+
function invocationPrefix() {
|
|
4324
|
+
const packageManager = process.env.npm_config_user_agent?.split("/")[0];
|
|
4325
|
+
switch (packageManager) {
|
|
4326
|
+
case "pnpm":
|
|
4327
|
+
case "yarn":
|
|
4328
|
+
return `${packageManager} catalyst`;
|
|
4329
|
+
case "bun":
|
|
4330
|
+
return "bunx catalyst";
|
|
4331
|
+
case "npm":
|
|
4332
|
+
return "npx catalyst";
|
|
4333
|
+
default:
|
|
4334
|
+
return "catalyst";
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
function printPaginationHints(pagination, start2, end, options) {
|
|
4338
|
+
const hasNextPage = Boolean(pagination?.links?.next) || pagination?.has_next_page === true;
|
|
4339
|
+
const hasPrevPage = Boolean(pagination?.links?.previous) || pagination?.has_prev_page === true;
|
|
4340
|
+
const endCursor = pagination?.end_cursor;
|
|
4341
|
+
const startCursor = pagination?.start_cursor;
|
|
4342
|
+
if (!(hasNextPage && endCursor) && !(hasPrevPage && startCursor)) return;
|
|
4343
|
+
const quoteArg = (value) => /\s/.test(value) ? `'${value}'` : value;
|
|
4344
|
+
const baseFlags = [
|
|
4345
|
+
`--start ${quoteArg(start2)}`,
|
|
4346
|
+
`--end ${quoteArg(end)}`,
|
|
4347
|
+
...options.method ? [`--method ${quoteArg(options.method)}`] : [],
|
|
4348
|
+
...options.statusCode != null ? [`--status-code ${options.statusCode}`] : [],
|
|
4349
|
+
...options.urlLike ? [`--url-like ${quoteArg(options.urlLike)}`] : [],
|
|
4350
|
+
...options.levelMin ? [`--level-min ${options.levelMin}`] : [],
|
|
4351
|
+
...options.limit != null ? [`--limit ${options.limit}`] : [],
|
|
4352
|
+
...options.format !== "default" ? [`--format ${options.format}`] : []
|
|
4353
|
+
];
|
|
4354
|
+
const command = `${invocationPrefix()} logs query ${baseFlags.join(" ")}`;
|
|
4355
|
+
if (hasNextPage && endCursor) {
|
|
4356
|
+
consola.info(`More results available. Next page:
|
|
4357
|
+
${command} --after ${quoteArg(endCursor)}`);
|
|
4358
|
+
}
|
|
4359
|
+
if (hasPrevPage && startCursor) {
|
|
4360
|
+
consola.info(
|
|
4361
|
+
`Newer results available. Previous page:
|
|
4362
|
+
${command} --before ${quoteArg(startCursor)}`
|
|
4363
|
+
);
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4300
4366
|
var query = new Command9("query").configureHelp({ showGlobalOptions: true }).description("Query historical logs from your deployed application.").addHelpText(
|
|
4301
4367
|
"after",
|
|
4302
4368
|
`
|
|
4303
4369
|
Specify a time window with \`--since\` (relative to now) or \`--start\`/\`--end\`
|
|
4304
4370
|
(ISO-8601 timestamps or Unix epoch seconds, UTC). The window may not exceed
|
|
4305
|
-
7 days. Entries print oldest-first; timestamps are UTC.
|
|
4371
|
+
7 days. Entries print oldest-first; timestamps are UTC. Page toward older
|
|
4372
|
+
entries by passing a previous page's end cursor to \`--after\` (the CLI prints
|
|
4373
|
+
a ready-to-run command when more entries are available), or toward newer
|
|
4374
|
+
entries with \`--before\`. Cursors are only valid with the same window and
|
|
4375
|
+
filters they came from. With \`--format json\`, the pagination cursors are
|
|
4376
|
+
emitted as a final \`{"meta": ...}\` line after the entries.
|
|
4306
4377
|
|
|
4307
4378
|
Examples:
|
|
4308
4379
|
# Last hour of logs
|
|
4309
4380
|
$ catalyst logs query --since 1h
|
|
4310
4381
|
|
|
4382
|
+
# Newest 20 errors in the window (follow the printed --after hint for more)
|
|
4383
|
+
$ catalyst logs query --since 24h --level-min error --limit 20
|
|
4384
|
+
|
|
4311
4385
|
# Everything from today (UTC)
|
|
4312
4386
|
$ catalyst logs query --start 2026-06-11T00:00:00Z
|
|
4313
4387
|
|
|
@@ -4334,7 +4408,20 @@ Examples:
|
|
|
4334
4408
|
).option("--url-like <substring>", "Filter by URL substring (case-sensitive).").addOption(
|
|
4335
4409
|
new Option8("--level-min <level>", "Minimum log level.").choices(Array.from(LOG_LEVELS))
|
|
4336
4410
|
).addOption(
|
|
4337
|
-
new Option8(
|
|
4411
|
+
new Option8(
|
|
4412
|
+
"--limit <count>",
|
|
4413
|
+
"Maximum entries per page (1-500). Defaults to the API default (100)."
|
|
4414
|
+
).argParser(parseIntInRange("--limit", 1, 500))
|
|
4415
|
+
).addOption(
|
|
4416
|
+
new Option8(
|
|
4417
|
+
"--after <cursor>",
|
|
4418
|
+
"Return the page after (older than) this cursor, from a previous page's end_cursor."
|
|
4419
|
+
).conflicts("before")
|
|
4420
|
+
).addOption(
|
|
4421
|
+
new Option8(
|
|
4422
|
+
"--before <cursor>",
|
|
4423
|
+
"Return the page before (newer than) this cursor, from a previous page's start_cursor."
|
|
4424
|
+
)
|
|
4338
4425
|
).addOption(
|
|
4339
4426
|
new Option8("--format <format>", "Output format for log entries.").choices(["json", "pretty", "default", "short", "request"]).default("default")
|
|
4340
4427
|
).action(async (options) => {
|
|
@@ -4342,7 +4429,7 @@ Examples:
|
|
|
4342
4429
|
const config2 = getProjectConfig();
|
|
4343
4430
|
const apiHost = resolveApiHost(options, config2);
|
|
4344
4431
|
const { storeHash, accessToken } = resolveCredentials(options, config2);
|
|
4345
|
-
await
|
|
4432
|
+
await getTelemetry().identify(storeHash);
|
|
4346
4433
|
const projectUuid = resolveProjectUuid(options);
|
|
4347
4434
|
const { start: start2, end } = resolveTimeWindow(options);
|
|
4348
4435
|
const result = await queryLogs(projectUuid, storeHash, accessToken, apiHost, {
|
|
@@ -4352,13 +4439,22 @@ Examples:
|
|
|
4352
4439
|
statusCode: options.statusCode,
|
|
4353
4440
|
urlLike: options.urlLike,
|
|
4354
4441
|
levelMin: options.levelMin,
|
|
4355
|
-
limit: options.limit
|
|
4442
|
+
limit: options.limit,
|
|
4443
|
+
after: options.after,
|
|
4444
|
+
before: options.before
|
|
4356
4445
|
});
|
|
4357
4446
|
const entries = result.data;
|
|
4358
4447
|
const ordered = [...entries].reverse();
|
|
4359
4448
|
if (options.format === "json") {
|
|
4360
4449
|
ordered.forEach((entry) => process.stdout.write(`${JSON.stringify(entry)}
|
|
4361
4450
|
`));
|
|
4451
|
+
const cursorPagination = result.meta?.cursor_pagination;
|
|
4452
|
+
if (cursorPagination) {
|
|
4453
|
+
process.stdout.write(
|
|
4454
|
+
`${JSON.stringify({ meta: { cursor_pagination: cursorPagination } })}
|
|
4455
|
+
`
|
|
4456
|
+
);
|
|
4457
|
+
}
|
|
4362
4458
|
return;
|
|
4363
4459
|
}
|
|
4364
4460
|
if (options.format === "pretty") {
|
|
@@ -4374,11 +4470,7 @@ Examples:
|
|
|
4374
4470
|
consola.info(
|
|
4375
4471
|
`${entries.length} ${entries.length === 1 ? "entry" : "entries"} shown (oldest first, times in UTC).`
|
|
4376
4472
|
);
|
|
4377
|
-
|
|
4378
|
-
consola.info(
|
|
4379
|
-
`Limit of ${options.limit} reached; older entries may exist. Narrow the time window or raise --limit (max 500) to see more.`
|
|
4380
|
-
);
|
|
4381
|
-
}
|
|
4473
|
+
printPaginationHints(result.meta?.cursor_pagination, start2, end, options);
|
|
4382
4474
|
} catch (error) {
|
|
4383
4475
|
consola.error(error instanceof Error ? error.message : error);
|
|
4384
4476
|
process.exit(1);
|
|
@@ -4673,7 +4765,7 @@ import { Argument, Command as Command12, Option as Option9 } from "commander";
|
|
|
4673
4765
|
import { colorize as colorize12 } from "consola/utils";
|
|
4674
4766
|
var telemetryService = getTelemetry();
|
|
4675
4767
|
var isEnabled = telemetryService.isEnabled();
|
|
4676
|
-
var
|
|
4768
|
+
var telemetry = new Command12("telemetry").configureHelp({ showGlobalOptions: true }).description(
|
|
4677
4769
|
"View or change CLI telemetry collection status. Enabling telemetry helps BigCommerce support diagnose and troubleshoot errors you encounter when using the CLI."
|
|
4678
4770
|
).addHelpText(
|
|
4679
4771
|
"after",
|
|
@@ -5402,17 +5494,17 @@ function getCommandPath(cmd) {
|
|
|
5402
5494
|
return parts.join(" ");
|
|
5403
5495
|
}
|
|
5404
5496
|
var telemetryPreHook = async (thisCommand, actionCommand) => {
|
|
5405
|
-
const
|
|
5497
|
+
const telemetry2 = getTelemetry();
|
|
5406
5498
|
const commandName = getCommandPath(actionCommand);
|
|
5407
|
-
|
|
5408
|
-
return await
|
|
5499
|
+
telemetry2.commandName = commandName;
|
|
5500
|
+
return await telemetry2.track(commandName, {
|
|
5409
5501
|
...parseArguments(thisCommand.args)
|
|
5410
5502
|
});
|
|
5411
5503
|
};
|
|
5412
5504
|
var telemetryPostHook = async () => {
|
|
5413
|
-
const
|
|
5414
|
-
await
|
|
5415
|
-
await
|
|
5505
|
+
const telemetry2 = getTelemetry();
|
|
5506
|
+
await telemetry2.track("command_completed", { durationMs: telemetry2.durationMs() });
|
|
5507
|
+
await telemetry2.analytics.closeAndFlush();
|
|
5416
5508
|
};
|
|
5417
5509
|
|
|
5418
5510
|
// src/cli/program.ts
|
|
@@ -5424,21 +5516,21 @@ consola.log(colorize13("cyanBright", `\u25E2 ${package_default.name} v${package_
|
|
|
5424
5516
|
`));
|
|
5425
5517
|
program.name(package_default.name).version(package_default.version).summary("CLI tool for Catalyst development").description(
|
|
5426
5518
|
"CLI tool for Catalyst development.\n\nConfiguration priority: flags > process.env > .bigcommerce/project.json. `build` and `deploy` additionally load env files (--env-path, or an auto-loaded .env.local/.env) for the build.\n\nCATALYST_STORE_HASH falls back to BIGCOMMERCE_STORE_HASH if unset.\n\nRun `catalyst <command> --help` for details on a specific command."
|
|
5427
|
-
).configureHelp({ showGlobalOptions: true }).addCommand(version).addCommand(create2).addCommand(start).addCommand(build).addCommand(deploy).addCommand(domains).addCommand(logs).addCommand(project).addCommand(env).addCommand(channel).addCommand(auth).addCommand(upgrade).addCommand(
|
|
5519
|
+
).configureHelp({ showGlobalOptions: true }).addCommand(version).addCommand(create2).addCommand(start).addCommand(build).addCommand(deploy).addCommand(domains).addCommand(logs).addCommand(project).addCommand(env).addCommand(channel).addCommand(auth).addCommand(upgrade).addCommand(telemetry).addCommand(debug).hook("preAction", telemetryPreHook).hook("postAction", telemetryPostHook);
|
|
5428
5520
|
|
|
5429
5521
|
// src/cli/index.ts
|
|
5430
5522
|
var handleFatalError = async (error) => {
|
|
5431
|
-
const
|
|
5523
|
+
const telemetry2 = getTelemetry();
|
|
5432
5524
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5433
5525
|
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
5434
5526
|
try {
|
|
5435
|
-
await
|
|
5436
|
-
commandName:
|
|
5527
|
+
await telemetry2.track("error", {
|
|
5528
|
+
commandName: telemetry2.commandName,
|
|
5437
5529
|
errorMessage,
|
|
5438
5530
|
errorStack,
|
|
5439
|
-
durationMs:
|
|
5531
|
+
durationMs: telemetry2.durationMs()
|
|
5440
5532
|
});
|
|
5441
|
-
await
|
|
5533
|
+
await telemetry2.analytics.closeAndFlush();
|
|
5442
5534
|
} catch {
|
|
5443
5535
|
}
|
|
5444
5536
|
if (error instanceof UserActionableError) {
|
|
@@ -5446,9 +5538,9 @@ var handleFatalError = async (error) => {
|
|
|
5446
5538
|
process.exit(1);
|
|
5447
5539
|
}
|
|
5448
5540
|
consola.error(errorMessage);
|
|
5449
|
-
if (
|
|
5541
|
+
if (telemetry2.isEnabled()) {
|
|
5450
5542
|
consola.info(
|
|
5451
|
-
`Correlation ID: ${
|
|
5543
|
+
`Correlation ID: ${telemetry2.correlationId}
|
|
5452
5544
|
Share this Correlation ID with BigCommerce support.`
|
|
5453
5545
|
);
|
|
5454
5546
|
} else {
|