vercel 59.1.4 → 59.4.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.
Files changed (96) hide show
  1. package/dist/chunks/{add-PP3PJPJV.js → add-73X2SKBH.js} +5 -5
  2. package/dist/chunks/{add-CUGPQYFW.js → add-FQMB3XPM.js} +5 -5
  3. package/dist/chunks/{add-PRG4KKYH.js → add-QJ3WT4FW.js} +8 -8
  4. package/dist/chunks/{build-T22GMLY6.js → build-YUYCLCXD.js} +5 -5
  5. package/dist/chunks/{chunk-LNVZ3T7X.js → chunk-2PX6N4FE.js} +5 -5
  6. package/dist/chunks/{chunk-BCZFZETZ.js → chunk-BLYBHFIE.js} +5 -5
  7. package/dist/chunks/{chunk-57G6HBJ4.js → chunk-CHEZBD7H.js} +3 -3
  8. package/dist/chunks/{chunk-NM43FFV6.js → chunk-CV4S27SS.js} +0 -1
  9. package/dist/chunks/{chunk-ECCWJHC6.js → chunk-CYNB6LL4.js} +43 -36
  10. package/dist/chunks/{chunk-5DVMXOFT.js → chunk-DDIZGOCK.js} +32 -30
  11. package/dist/chunks/{chunk-4JKZ7SRX.js → chunk-EB5NBVTV.js} +4 -4
  12. package/dist/chunks/{chunk-M34ZRNDQ.js → chunk-EB7NJKPL.js} +2 -2
  13. package/dist/chunks/{chunk-CSJBZKC5.js → chunk-EG5BSAXD.js} +69 -57
  14. package/dist/chunks/{chunk-ZUVJISHS.js → chunk-HJVTLJHO.js} +2 -2
  15. package/dist/chunks/{chunk-VE545BR3.js → chunk-HMJVUXE6.js} +13555 -13747
  16. package/dist/chunks/{chunk-SOKQBFF7.js → chunk-HURL5EBN.js} +549 -62
  17. package/dist/chunks/{chunk-43DD2KNM.js → chunk-J5Y2QGGU.js} +1362 -938
  18. package/dist/chunks/{chunk-QCVKGY2A.js → chunk-KAYSW4CJ.js} +35 -12
  19. package/dist/chunks/{chunk-P65EEFTR.js → chunk-KQRVZWJU.js} +1 -0
  20. package/dist/chunks/{chunk-4HI7G6KG.js → chunk-KSZ4MNHO.js} +1 -1
  21. package/dist/chunks/{chunk-DOAYLTBJ.js → chunk-LKTQR5JE.js} +1 -1
  22. package/dist/chunks/{chunk-JYEO6OJS.js → chunk-MWYQ24FO.js} +4 -3
  23. package/dist/chunks/{chunk-SQGMTRZD.js → chunk-NP6BQPCN.js} +642 -462
  24. package/dist/chunks/{chunk-DAWJOQF6.js → chunk-O5DLWLT7.js} +2 -2
  25. package/dist/chunks/{chunk-IKKUCZE7.js → chunk-PD4DYNSB.js} +3 -3
  26. package/dist/chunks/{chunk-3BU2UCGV.js → chunk-PIMIKY4X.js} +1 -1
  27. package/dist/chunks/{chunk-QD5NX7RG.js → chunk-RI7KKKII.js} +1 -1
  28. package/dist/chunks/{chunk-QQ6PH4RY.js → chunk-STPH4Y62.js} +10 -0
  29. package/dist/chunks/{chunk-TJLBCLEX.js → chunk-TH2XUVDP.js} +11 -1
  30. package/dist/chunks/{chunk-P2QZZ6MR.js → chunk-TVXCXIRO.js} +1 -1
  31. package/dist/chunks/{chunk-KTLFN5FV.js → chunk-UV2ZMFVG.js} +1 -1
  32. package/dist/chunks/{chunk-XZLI27ES.js → chunk-VCE6QKFE.js} +3 -3
  33. package/dist/chunks/{chunk-DOMLWKKZ.js → chunk-X6O6XJEA.js} +17 -20
  34. package/dist/chunks/{chunk-SJQEGGH7.js → chunk-XI6NJLI4.js} +1 -1
  35. package/dist/chunks/{chunk-7NQLRE5V.js → chunk-Y3J4VU2H.js} +1 -1
  36. package/dist/chunks/{chunk-DEB45ND4.js → chunk-Y42SPI2H.js} +2 -2
  37. package/dist/chunks/{chunk-TM3F7PLR.js → chunk-ZFWNMVNR.js} +3 -3
  38. package/dist/chunks/{clear-Z4IKUIN7.js → clear-USQM5VW5.js} +5 -5
  39. package/dist/chunks/{compile-vercel-config-PSVXFAZW.js → compile-vercel-config-2JNYMI6W.js} +3 -3
  40. package/dist/chunks/{config-M5GMZ2X5.js → config-VTRIDLY4.js} +5 -5
  41. package/dist/chunks/{delete-P4XIBY7T.js → delete-ILLSBCVQ.js} +5 -5
  42. package/dist/chunks/{delete-5GRRDJSF.js → delete-VTPHK3EB.js} +4 -4
  43. package/dist/chunks/{disable-NT5NYVO7.js → disable-VTOMO64V.js} +4 -4
  44. package/dist/chunks/{discard-TBNIEAJZ.js → discard-ZIOZ34ZI.js} +4 -4
  45. package/dist/chunks/{edit-DJ6MT6HA.js → edit-E3AMR4KM.js} +6 -6
  46. package/dist/chunks/{edit-UF3D2CCH.js → edit-JMZ5XWVW.js} +6 -6
  47. package/dist/chunks/{enable-JTQBQMBO.js → enable-A4PMZ7QZ.js} +4 -4
  48. package/dist/chunks/{export-OKMRGRVM.js → export-Y6AJ3WRZ.js} +4 -4
  49. package/dist/chunks/{image-ARUJH4H5.js → image-26BKPAUB.js} +4 -4
  50. package/dist/chunks/{import-builders-3NTMZM64.js → import-builders-3H7J2SEK.js} +10 -9
  51. package/dist/chunks/{inspect-RI4K77NG.js → inspect-7DGKYHKW.js} +6 -6
  52. package/dist/chunks/{inspect-PTXIBSYW.js → inspect-GJFVAZIJ.js} +5 -5
  53. package/dist/chunks/{inspect-CHFKZKKP.js → inspect-N3E2PO6K.js} +5 -5
  54. package/dist/chunks/{inspect-5NETOGAI.js → inspect-OEY4DJRI.js} +5 -5
  55. package/dist/chunks/{inspect-UXP2HDES.js → inspect-ZW5N6O5P.js} +5 -5
  56. package/dist/chunks/{list-DYCZA2VX.js → list-2VTCNQEB.js} +4 -4
  57. package/dist/chunks/{list-G7LGVDAJ.js → list-DTJBW7OQ.js} +6 -6
  58. package/dist/chunks/{list-ADI55WKW.js → list-MIQ5D6PM.js} +5 -5
  59. package/dist/chunks/{login-YCSIQG6B.js → login-L34UHAU5.js} +5 -5
  60. package/dist/chunks/{ls-VIOMDUGW.js → ls-NCPQY4FV.js} +5 -5
  61. package/dist/chunks/{ls-2TKUIUK4.js → ls-OBUDC4SB.js} +5 -5
  62. package/dist/chunks/{ls-PQFDGOJL.js → ls-OKO4IHWB.js} +6 -6
  63. package/dist/chunks/{ls-RZVTIP5U.js → ls-SXJFBLUT.js} +5 -5
  64. package/dist/chunks/{ls-EOMIQLRH.js → ls-VDYUFSSC.js} +5 -5
  65. package/dist/chunks/{open-JYPWOXQD.js → open-V5JDGXUP.js} +5 -5
  66. package/dist/chunks/{permissions-SGJWGEVD.js → permissions-6CPRPPBY.js} +5 -5
  67. package/dist/chunks/{publish-ZUQHJAXL.js → publish-R27DPHFO.js} +4 -4
  68. package/dist/chunks/{push-XMVKG5A5.js → push-VLVTBS42.js} +5 -5
  69. package/dist/chunks/{query-ZLJZEGZB.js → query-IVVRYMJN.js} +218 -81
  70. package/dist/chunks/{reorder-NVHDWMRU.js → reorder-LJ2RBZM2.js} +4 -4
  71. package/dist/chunks/{reply-PUUPUQ3V.js → reply-USAISZYC.js} +6 -6
  72. package/dist/chunks/{resolve-5U2LJVE6.js → resolve-CRCJYVS5.js} +5 -5
  73. package/dist/chunks/{restore-OXIUY2UI.js → restore-6PBPEAMU.js} +4 -4
  74. package/dist/chunks/{rm-Z2KYJ7XT.js → rm-EOD7RDSO.js} +5 -5
  75. package/dist/chunks/{rm-BZNKJRXU.js → rm-HHELZB7R.js} +5 -5
  76. package/dist/chunks/{rm-3IOCBNPE.js → rm-KGOEOWVK.js} +6 -6
  77. package/dist/chunks/{rm-OUI4ZB5R.js → rm-TWU3JR6Z.js} +5 -5
  78. package/dist/chunks/{routes-JP2CNQ5J.js → routes-SZI2G4SE.js} +2 -2
  79. package/dist/chunks/{rule-inspect-ZBJJCDQV.js → rule-inspect-WFTVRK6B.js} +6 -6
  80. package/dist/chunks/{rules-HEGAXXUN.js → rules-AQYTFJI6.js} +8 -8
  81. package/dist/chunks/{schema-ZYIJYA2E.js → schema-LUVFYPWN.js} +1 -1
  82. package/dist/chunks/{schema-7GVL3BNP.js → schema-ZCDCJC7E.js} +22 -12
  83. package/dist/chunks/{tags-3SCWCMNQ.js → tags-RCNRFX7U.js} +3 -3
  84. package/dist/chunks/{update-YR2GCCJN.js → update-I7QGAOYF.js} +8 -8
  85. package/dist/commands/build/index.js +3099 -2519
  86. package/dist/commands/deploy/index.js +12 -12
  87. package/dist/commands/dev/index.js +85 -39
  88. package/dist/commands/env/index.js +149 -226
  89. package/dist/commands/link/index.js +7 -7
  90. package/dist/commands/list/index.js +5 -5
  91. package/dist/commands-bulk.js +4904 -2237
  92. package/dist/help.js +1 -1
  93. package/dist/index.js +27 -15
  94. package/dist/runtime-assets/node-preloads/next-dev-websocket.cjs +5 -1
  95. package/dist/version.mjs +1 -1
  96. package/package.json +54 -51
@@ -6,43 +6,43 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  OBSERVABILITY_METRICS_PATH,
9
- fetchCustomMetricCatalog,
9
+ fetchCatalogMetricDetailOrExit,
10
10
  fetchMetricDetailOrExit,
11
11
  getDefaultAggregation
12
- } from "./chunk-QCVKGY2A.js";
12
+ } from "./chunk-KAYSW4CJ.js";
13
13
  import {
14
14
  computeGranularity,
15
15
  formatText,
16
16
  getDefaultCustomMetricAggregation,
17
17
  isCanonicalAggregation
18
- } from "./chunk-JYEO6OJS.js";
18
+ } from "./chunk-MWYQ24FO.js";
19
19
  import {
20
20
  formatErrorJson,
21
21
  formatQueryJson,
22
22
  getRollupColumnName,
23
23
  handleApiError
24
- } from "./chunk-NM43FFV6.js";
24
+ } from "./chunk-CV4S27SS.js";
25
25
  import "./chunk-5AJPMLDV.js";
26
26
  import "./chunk-A3NYPUKZ.js";
27
27
  import {
28
28
  resolveTimeRange,
29
29
  validateAllProjectMutualExclusivity
30
- } from "./chunk-P65EEFTR.js";
30
+ } from "./chunk-KQRVZWJU.js";
31
31
  import "./chunk-VDJN4WKH.js";
32
32
  import {
33
33
  validateJsonOutput
34
34
  } from "./chunk-KXDWXXJH.js";
35
35
  import {
36
36
  metricsCommand
37
- } from "./chunk-CSJBZKC5.js";
37
+ } from "./chunk-EG5BSAXD.js";
38
38
  import "./chunk-VXYGCOKL.js";
39
39
  import {
40
40
  getLinkedProject,
41
41
  getProjectByNameOrId,
42
42
  getScope
43
- } from "./chunk-VE545BR3.js";
44
- import "./chunk-ECCWJHC6.js";
45
- import "./chunk-TJLBCLEX.js";
43
+ } from "./chunk-HMJVUXE6.js";
44
+ import "./chunk-CYNB6LL4.js";
45
+ import "./chunk-TH2XUVDP.js";
46
46
  import "./chunk-GGP5R3FU.js";
47
47
  import {
48
48
  printError
@@ -60,8 +60,15 @@ import "./chunk-52QYYTM5.js";
60
60
  import {
61
61
  output_manager_default
62
62
  } from "./chunk-OX7KI3LF.js";
63
- import "./chunk-S7KYDPEM.js";
64
- import "./chunk-TZ2YI2VH.js";
63
+ import {
64
+ require_source
65
+ } from "./chunk-S7KYDPEM.js";
66
+ import {
67
+ __toESM
68
+ } from "./chunk-TZ2YI2VH.js";
69
+
70
+ // src/commands/metrics/query.ts
71
+ var import_chalk = __toESM(require_source(), 1);
65
72
 
66
73
  // src/commands/metrics/validation.ts
67
74
  function validateRequiredMetric(metric) {
@@ -104,7 +111,8 @@ function validateOrderBy(orderBy) {
104
111
  }
105
112
 
106
113
  // src/commands/metrics/query.ts
107
- function handleValidationError(result, jsonOutput, client) {
114
+ function handleValidationError(result, jsonOutput, client, telemetry) {
115
+ telemetry.trackCliError(result.code);
108
116
  if (jsonOutput) {
109
117
  client.stdout.write(
110
118
  formatErrorJson(result.code, result.message, result.allowedValues)
@@ -120,12 +128,17 @@ Available values: ${result.allowedValues.join(", ")}
120
128
  return 1;
121
129
  }
122
130
  var PRODUCTION_ENVIRONMENT_FILTER = "environment eq 'production'";
131
+ var PRODUCTION_ENVIRONMENT_KQL_FILTER = "environment:production";
123
132
  var CUSTOM_METRIC_VALUE_ALIAS = "value";
124
133
  var CUSTOM_METRIC_COUNT_ALIAS = "__seriesCount";
125
- function combineFilters(filters, prod) {
134
+ var SUM_DEFAULT_METRIC_UNITS = /* @__PURE__ */ new Set(["bytes", "count", "usd", "units"]);
135
+ var FILTER_DEPRECATION_WARNING = "OData support in --filter is deprecated and will be removed soon. KQL will be the only supported filter syntax.";
136
+ function combineFilters(filters, prod, syntax = "odata") {
126
137
  const nonEmptyFilters = [
127
138
  ...filters?.filter((filter) => filter.length > 0) ?? [],
128
- ...prod ? [PRODUCTION_ENVIRONMENT_FILTER] : []
139
+ ...prod ? [
140
+ syntax === "kql" ? PRODUCTION_ENVIRONMENT_KQL_FILTER : PRODUCTION_ENVIRONMENT_FILTER
141
+ ] : []
129
142
  ];
130
143
  if (nonEmptyFilters.length === 0) {
131
144
  return void 0;
@@ -133,7 +146,14 @@ function combineFilters(filters, prod) {
133
146
  if (nonEmptyFilters.length === 1) {
134
147
  return nonEmptyFilters[0];
135
148
  }
136
- return nonEmptyFilters.map((filter) => `(${filter})`).join(" and ");
149
+ const conjunction = syntax === "kql" ? " AND " : " and ";
150
+ return nonEmptyFilters.map((filter) => `(${filter})`).join(conjunction);
151
+ }
152
+ function usesODataSyntax(filters) {
153
+ return filters?.some((filter) => {
154
+ const unquoted = filter.replace(/"(?:\\.|[^"\\])*"|'(?:''|[^'])*'/g, "");
155
+ return /\s(?:eq|ne|gt|ge|lt|le|in)\s/i.test(unquoted) || /\b(?:contains|startswith|endswith)\s*\(/i.test(unquoted);
156
+ }) ?? false;
137
157
  }
138
158
  function getRequestOrderBy(metric, aggregation, orderBy) {
139
159
  return orderBy === "value" ? getRollupColumnName(metric, aggregation) : void 0;
@@ -152,18 +172,38 @@ function alignTimeRangeToGranularity(startTime, endTime, granularity) {
152
172
  endTime: new Date(Math.ceil(endTime.getTime() / bucketMs) * bucketMs)
153
173
  };
154
174
  }
155
- function toCanonicalMetricSelection(metric, aggregation) {
175
+ function getCatalogDefaultAggregation(metric, isPlatformMetric) {
176
+ if (!isPlatformMetric) {
177
+ return getDefaultCustomMetricAggregation(metric.unit, metric.aggregations);
178
+ }
179
+ const defaultAggregation = SUM_DEFAULT_METRIC_UNITS.has(metric.unit) ? "sum" : "avg";
180
+ if (metric.aggregations.includes(defaultAggregation)) {
181
+ return defaultAggregation;
182
+ }
183
+ if (defaultAggregation === "sum" && metric.aggregations.includes("count")) {
184
+ return "count";
185
+ }
186
+ return metric.aggregations.includes("sum") ? "sum" : metric.aggregations[0];
187
+ }
188
+ function toCanonicalMetricSelection(metric, aggregation, supportedAggregations) {
189
+ const [aggregationName, ...dimensionParts] = aggregation.split("/");
190
+ const dimension = dimensionParts.join("/") || void 0;
191
+ const countOnlyMetric = supportedAggregations?.includes("count") === true && !supportedAggregations.includes("sum");
192
+ const additiveAggregation = supportedAggregations?.includes("sum") ? "sum" : countOnlyMetric || supportedAggregations === void 0 && metric.endsWith(".count") ? "count" : "sum";
156
193
  if (aggregation === "persecond") {
157
- return { metric, aggregation: "sum", per: "second" };
194
+ return { metric, aggregation: additiveAggregation, per: "second" };
158
195
  }
159
196
  if (aggregation === "percent") {
160
- return { metric, aggregation: "sum", normalize: "percent" };
197
+ return { metric, aggregation: additiveAggregation, normalize: "percent" };
161
198
  }
162
- if (aggregation === "unique") {
199
+ if (aggregationName === "unique") {
200
+ if (dimension) {
201
+ return { metric, aggregation: "unique", dimensions: [dimension] };
202
+ }
163
203
  return {
164
204
  valid: false,
165
205
  code: "UNSUPPORTED_AGGREGATION",
166
- message: "The unique aggregation for custom metrics requires an explicit distinct dimension, which vc metrics does not support yet."
206
+ message: 'The unique aggregation requires a dimension, for example "unique/visitorId".'
167
207
  };
168
208
  }
169
209
  if (isCanonicalAggregation(aggregation)) {
@@ -172,15 +212,33 @@ function toCanonicalMetricSelection(metric, aggregation) {
172
212
  return {
173
213
  valid: false,
174
214
  code: "INVALID_AGGREGATION",
175
- message: `Aggregation "${aggregation}" is not supported for custom metrics.`
215
+ message: `Aggregation "${aggregation}" is not supported by the Observability query API.`
176
216
  };
177
217
  }
218
+ function getCanonicalOrderBy(orderBy, selection, supportedAggregations) {
219
+ if (orderBy === "value") {
220
+ return "value";
221
+ }
222
+ const supportsCount = supportedAggregations === void 0 || supportedAggregations.includes("count");
223
+ if (selection.aggregation === "count" || supportsCount) {
224
+ return "count";
225
+ }
226
+ if (orderBy === "count") {
227
+ return {
228
+ valid: false,
229
+ code: "INVALID_ORDER_BY",
230
+ message: "--order-by count is not available because this metric does not support the count aggregation. Use --order-by value.",
231
+ allowedValues: ["value"]
232
+ };
233
+ }
234
+ return "value";
235
+ }
178
236
  function createCanonicalMetricsRequest(options) {
179
237
  const metrics = {
180
238
  [CUSTOM_METRIC_VALUE_ALIAS]: options.selection
181
239
  };
182
240
  let rankMetric = CUSTOM_METRIC_VALUE_ALIAS;
183
- if (options.groupBy.length > 0 && options.orderBy !== "value" && options.selection.aggregation !== "count") {
241
+ if (options.groupBy.length > 0 && options.orderBy === "count" && options.selection.aggregation !== "count") {
184
242
  metrics[CUSTOM_METRIC_COUNT_ALIAS] = {
185
243
  metric: options.metric,
186
244
  aggregation: "count"
@@ -239,17 +297,17 @@ function canonicalResponseToMetricsResponse(response, rollupColumn, orderBy, ord
239
297
  ...orderDirection ? { orderDirection } : {}
240
298
  };
241
299
  }
242
- async function resolveQueryScope(client, opts) {
300
+ async function resolveQueryScope(client, telemetry, opts) {
243
301
  if (opts.project || opts.all) {
244
302
  const { team } = await getScope(client);
245
303
  if (!team) {
246
304
  const errMsg = "No team context found. Run `vercel switch` to select a team, or use `vercel link` in a project directory.";
247
- if (opts.jsonOutput) {
248
- client.stdout.write(formatErrorJson("NO_TEAM", errMsg));
249
- } else {
250
- output_manager_default.error(errMsg);
251
- }
252
- return 1;
305
+ return handleValidationError(
306
+ { valid: false, code: "NO_TEAM", message: errMsg },
307
+ opts.jsonOutput,
308
+ client,
309
+ telemetry
310
+ );
253
311
  }
254
312
  if (opts.all) {
255
313
  return {
@@ -261,12 +319,12 @@ async function resolveQueryScope(client, opts) {
261
319
  const project = await getProjectByNameOrId(client, opts.project, team.id);
262
320
  if (project instanceof ProjectNotFound) {
263
321
  const errMsg = `Project "${opts.project}" was not found in team "${team.slug}".`;
264
- if (opts.jsonOutput) {
265
- client.stdout.write(formatErrorJson("PROJECT_NOT_FOUND", errMsg));
266
- } else {
267
- output_manager_default.error(errMsg);
268
- }
269
- return 1;
322
+ return handleValidationError(
323
+ { valid: false, code: "PROJECT_NOT_FOUND", message: errMsg },
324
+ opts.jsonOutput,
325
+ client,
326
+ telemetry
327
+ );
270
328
  }
271
329
  return {
272
330
  scope: {
@@ -281,16 +339,17 @@ async function resolveQueryScope(client, opts) {
281
339
  }
282
340
  const linkedProject = await getLinkedProject(client);
283
341
  if (linkedProject.status === "error") {
342
+ telemetry.trackCliError("LINK_ERROR");
284
343
  return linkedProject.exitCode;
285
344
  }
286
345
  if (linkedProject.status === "not_linked") {
287
346
  const errMsg = "No linked project found. Run `vercel link` to link a project, or use --project <name-or-id> or --all.";
288
- if (opts.jsonOutput) {
289
- client.stdout.write(formatErrorJson("NOT_LINKED", errMsg));
290
- } else {
291
- output_manager_default.error(errMsg);
292
- }
293
- return 1;
347
+ return handleValidationError(
348
+ { valid: false, code: "NOT_LINKED", message: errMsg },
349
+ opts.jsonOutput,
350
+ client,
351
+ telemetry
352
+ );
294
353
  }
295
354
  return {
296
355
  scope: {
@@ -309,6 +368,7 @@ async function query(client, telemetry) {
309
368
  try {
310
369
  parsedArgs = parseArguments(client.argv.slice(2), flagsSpecification);
311
370
  } catch (err) {
371
+ telemetry.trackCliError("INVALID_ARGUMENTS");
312
372
  printError(err);
313
373
  return 1;
314
374
  }
@@ -317,6 +377,7 @@ async function query(client, telemetry) {
317
377
  const positionalMetric = positionalArgs[0] === "query" ? positionalArgs[1] : positionalArgs[0];
318
378
  const formatResult = validateJsonOutput(flags);
319
379
  if (!formatResult.valid) {
380
+ telemetry.trackCliError("INVALID_OUTPUT_FORMAT");
320
381
  output_manager_default.error(formatResult.error);
321
382
  return 1;
322
383
  }
@@ -329,7 +390,6 @@ async function query(client, telemetry) {
329
390
  const orderInput = typeof flags["--order"] === "string" ? flags["--order"].trim().toLowerCase() : void 0;
330
391
  const filters = flags["--filter"];
331
392
  const prod = flags["--prod"];
332
- const filter = combineFilters(filters, prod);
333
393
  const since = flags["--since"];
334
394
  const until = flags["--until"];
335
395
  const granularity = flags["--granularity"];
@@ -353,24 +413,29 @@ async function query(client, telemetry) {
353
413
  telemetry.trackCliOptionFormat(flags["--format"]);
354
414
  const orderByResult = validateOrderBy(orderByInput);
355
415
  if (!orderByResult.valid) {
356
- return handleValidationError(orderByResult, jsonOutput, client);
416
+ return handleValidationError(orderByResult, jsonOutput, client, telemetry);
357
417
  }
358
418
  const orderByMode = orderByResult.value;
359
419
  const requiredMetric = validateRequiredMetric(metricFlag);
360
420
  if (!requiredMetric.valid) {
361
- return handleValidationError(requiredMetric, jsonOutput, client);
421
+ return handleValidationError(requiredMetric, jsonOutput, client, telemetry);
362
422
  }
363
423
  const metric = requiredMetric.value;
364
424
  const mutualResult = validateAllProjectMutualExclusivity(all, project);
365
425
  if (!mutualResult.valid) {
366
- return handleValidationError(mutualResult, jsonOutput, client);
426
+ return handleValidationError(mutualResult, jsonOutput, client, telemetry);
367
427
  }
368
428
  const orderDirectionResult = validateOrderDirection(orderInput);
369
429
  if (!orderDirectionResult.valid) {
370
- return handleValidationError(orderDirectionResult, jsonOutput, client);
430
+ return handleValidationError(
431
+ orderDirectionResult,
432
+ jsonOutput,
433
+ client,
434
+ telemetry
435
+ );
371
436
  }
372
437
  const orderDirection = orderDirectionResult.value;
373
- const scopeResult = await resolveQueryScope(client, {
438
+ const scopeResult = await resolveQueryScope(client, telemetry, {
374
439
  project,
375
440
  all,
376
441
  jsonOutput
@@ -379,24 +444,85 @@ async function query(client, telemetry) {
379
444
  return scopeResult;
380
445
  }
381
446
  const { scope, accountId, teamName, projectName } = scopeResult;
447
+ const isPlatformMetric = metric.startsWith("vercel.");
448
+ const useCanonicalQuery = !isPlatformMetric || Boolean(process.env.FF_METRICS);
449
+ const filterUsesOData = usesODataSyntax(filters);
450
+ if (useCanonicalQuery && filterUsesOData) {
451
+ output_manager_default.print(`${import_chalk.default.yellow("!")} ${FILTER_DEPRECATION_WARNING}
452
+ `);
453
+ }
454
+ const filter = combineFilters(
455
+ filters,
456
+ prod,
457
+ useCanonicalQuery && !filterUsesOData ? "kql" : "odata"
458
+ );
382
459
  let startTime;
383
460
  let endTime;
384
461
  try {
385
462
  ({ startTime, endTime } = resolveTimeRange(since, until));
386
463
  } catch (err) {
387
464
  const errMsg = err instanceof Error ? err.message : String(err);
388
- if (jsonOutput) {
389
- client.stdout.write(formatErrorJson("INVALID_TIME", errMsg));
390
- } else {
391
- output_manager_default.error(errMsg);
392
- }
393
- return 1;
465
+ return handleValidationError(
466
+ { valid: false, code: "INVALID_TIME", message: errMsg },
467
+ jsonOutput,
468
+ client,
469
+ telemetry
470
+ );
394
471
  }
395
- const isPlatformMetric = metric.startsWith("vercel.");
396
472
  let metricUnit;
397
473
  let aggregationInput;
398
- let customMetricAggregations;
399
- if (isPlatformMetric) {
474
+ let canonicalAggregations;
475
+ if (useCanonicalQuery) {
476
+ const catalogOrExitCode = await fetchCatalogMetricDetailOrExit(
477
+ client,
478
+ accountId,
479
+ jsonOutput,
480
+ metric,
481
+ isPlatformMetric ? "system" : "custom",
482
+ startTime.toISOString()
483
+ );
484
+ if (typeof catalogOrExitCode === "number") {
485
+ telemetry.trackCliError("SCHEMA_FETCH_FAILED");
486
+ return catalogOrExitCode;
487
+ }
488
+ const catalogMetric = catalogOrExitCode.find((item) => item.id === metric);
489
+ if (!catalogMetric) {
490
+ return handleValidationError(
491
+ {
492
+ valid: false,
493
+ code: "UNKNOWN_METRIC",
494
+ message: `Unknown metric "${metric}".`,
495
+ allowedValues: catalogOrExitCode.map((item) => item.id)
496
+ },
497
+ jsonOutput,
498
+ client,
499
+ telemetry
500
+ );
501
+ }
502
+ metricUnit = catalogMetric.unit;
503
+ canonicalAggregations = catalogMetric.aggregations;
504
+ if (aggregationFlag) {
505
+ aggregationInput = aggregationFlag;
506
+ } else {
507
+ const defaultAggregation = getCatalogDefaultAggregation(
508
+ catalogMetric,
509
+ isPlatformMetric
510
+ );
511
+ if (!defaultAggregation) {
512
+ return handleValidationError(
513
+ {
514
+ valid: false,
515
+ code: "INVALID_AGGREGATION",
516
+ message: `Metric "${metric}" does not support any query aggregations.`
517
+ },
518
+ jsonOutput,
519
+ client,
520
+ telemetry
521
+ );
522
+ }
523
+ aggregationInput = defaultAggregation;
524
+ }
525
+ } else {
400
526
  const detailOrExitCode = await fetchMetricDetailOrExit(
401
527
  client,
402
528
  accountId,
@@ -404,31 +530,23 @@ async function query(client, telemetry) {
404
530
  jsonOutput
405
531
  );
406
532
  if (typeof detailOrExitCode === "number") {
533
+ telemetry.trackCliError("SCHEMA_FETCH_FAILED");
407
534
  return detailOrExitCode;
408
535
  }
409
536
  aggregationInput = aggregationFlag ?? getDefaultAggregation(detailOrExitCode, metric) ?? "sum";
410
537
  metricUnit = detailOrExitCode.find((item) => item.id === metric)?.unit ?? "count";
411
- } else {
412
- const customMetric = await fetchCustomMetricCatalog(
413
- client,
414
- accountId,
415
- metric,
416
- startTime.toISOString()
417
- ).then((metrics) => metrics.find((item) => item.id === metric)).catch(() => void 0);
418
- metricUnit = customMetric?.unit ?? "units";
419
- customMetricAggregations = customMetric?.aggregations;
420
- aggregationInput = aggregationFlag ?? getDefaultCustomMetricAggregation(metricUnit, customMetricAggregations);
421
538
  }
422
539
  const aggregation = aggregationInput;
423
540
  const orderBy = getRequestOrderBy(metric, aggregation, orderByMode);
424
541
  const rangeMs = endTime.getTime() - startTime.getTime();
425
542
  const granResult = computeGranularity(rangeMs, granularity);
426
- const queryTimeRange = isPlatformMetric ? { startTime, endTime } : alignTimeRangeToGranularity(startTime, endTime, granResult.duration);
543
+ const queryTimeRange = useCanonicalQuery ? alignTimeRangeToGranularity(startTime, endTime, granResult.duration) : { startTime, endTime };
427
544
  if (!jsonOutput && granResult.adjusted && granResult.notice) {
428
545
  output_manager_default.log(`Notice: ${granResult.notice}`);
429
546
  }
430
547
  let body;
431
- if (isPlatformMetric) {
548
+ let canonicalOrderBy;
549
+ if (!useCanonicalQuery) {
432
550
  body = {
433
551
  scope,
434
552
  metric,
@@ -449,29 +567,45 @@ async function query(client, telemetry) {
449
567
  {
450
568
  valid: false,
451
569
  code: "UNSUPPORTED_BUCKET_TIMEZONE",
452
- message: "--bucket-timezone is not supported for custom metrics yet."
570
+ message: "--bucket-timezone is not supported by the new Observability query API yet."
453
571
  },
454
572
  jsonOutput,
455
- client
573
+ client,
574
+ telemetry
456
575
  );
457
576
  }
458
- const selection = toCanonicalMetricSelection(metric, aggregation);
577
+ const selection = toCanonicalMetricSelection(
578
+ metric,
579
+ aggregation,
580
+ canonicalAggregations
581
+ );
459
582
  if ("valid" in selection) {
460
- return handleValidationError(selection, jsonOutput, client);
583
+ return handleValidationError(selection, jsonOutput, client, telemetry);
461
584
  }
462
585
  const supportedAggregation = selection.aggregation;
463
- if (customMetricAggregations && !customMetricAggregations.includes(supportedAggregation)) {
586
+ if (canonicalAggregations && !canonicalAggregations.includes(supportedAggregation)) {
464
587
  return handleValidationError(
465
588
  {
466
589
  valid: false,
467
590
  code: "INVALID_AGGREGATION",
468
- message: `Aggregation "${aggregation}" is not valid for custom metric "${metric}".`,
469
- allowedValues: [...customMetricAggregations]
591
+ message: `Aggregation "${aggregation}" is not valid for metric "${metric}".`,
592
+ allowedValues: [...canonicalAggregations]
470
593
  },
471
594
  jsonOutput,
472
- client
595
+ client,
596
+ telemetry
597
+ );
598
+ }
599
+ const canonicalOrderByResult = groupBy.length > 0 ? getCanonicalOrderBy(orderByMode, selection, canonicalAggregations) : void 0;
600
+ if (canonicalOrderByResult && typeof canonicalOrderByResult !== "string") {
601
+ return handleValidationError(
602
+ canonicalOrderByResult,
603
+ jsonOutput,
604
+ client,
605
+ telemetry
473
606
  );
474
607
  }
608
+ canonicalOrderBy = canonicalOrderByResult;
475
609
  body = createCanonicalMetricsRequest({
476
610
  scope,
477
611
  metric,
@@ -482,16 +616,17 @@ async function query(client, telemetry) {
482
616
  groupBy,
483
617
  filter,
484
618
  limit: limit ?? 10,
485
- orderBy: orderByMode,
619
+ orderBy: canonicalOrderBy,
486
620
  orderDirection
487
621
  });
488
622
  }
623
+ const resolvedOrderBy = canonicalOrderBy ?? orderByMode;
489
624
  if (!jsonOutput) {
490
625
  output_manager_default.spinner("Querying metrics...");
491
626
  }
492
627
  let response;
493
628
  try {
494
- if (isPlatformMetric) {
629
+ if (!useCanonicalQuery) {
495
630
  response = await client.fetch(
496
631
  "/v2/observability/query",
497
632
  {
@@ -516,15 +651,17 @@ async function query(client, telemetry) {
516
651
  response = canonicalResponseToMetricsResponse(
517
652
  canonicalResponse,
518
653
  getRollupColumnName(metric, aggregation),
519
- groupBy.length > 0 ? orderByMode ?? "count" : void 0,
654
+ canonicalOrderBy,
520
655
  groupBy.length > 0 ? orderDirection ?? "desc" : void 0
521
656
  );
522
657
  }
523
658
  } catch (err) {
524
659
  if (isAPIError(err)) {
660
+ telemetry.trackCliError(err.code ?? "API_ERROR", err.status);
525
661
  return handleApiError(err, jsonOutput, client);
526
662
  }
527
663
  const errMsg = err instanceof Error ? err.message : String(err);
664
+ telemetry.trackCliError("NETWORK_ERROR");
528
665
  if (jsonOutput) {
529
666
  client.stdout.write(formatErrorJson("NETWORK_ERROR", errMsg));
530
667
  } else {
@@ -548,7 +685,7 @@ async function query(client, telemetry) {
548
685
  endTime: queryTimeRange.endTime.toISOString(),
549
686
  granularity: granResult.duration,
550
687
  ...bucketTimezone ? { bucketTimezone } : {},
551
- ...orderByMode ? { orderBy: orderByMode } : {},
688
+ ...resolvedOrderBy ? { orderBy: resolvedOrderBy } : {},
552
689
  ...orderDirection ? { orderDirection } : {}
553
690
  },
554
691
  response
@@ -569,7 +706,7 @@ async function query(client, telemetry) {
569
706
  periodEnd: queryTimeRange.endTime.toISOString(),
570
707
  granularity: granResult.duration,
571
708
  bucketTimezone,
572
- orderBy: orderByMode,
709
+ orderBy: resolvedOrderBy,
573
710
  orderDirection
574
711
  })
575
712
  );
@@ -16,7 +16,7 @@ import {
16
16
  resolveRoute,
17
17
  shellQuoteRouteIdentifierForSuggestion,
18
18
  withGlobalFlags
19
- } from "./chunk-ZUVJISHS.js";
19
+ } from "./chunk-HJVTLJHO.js";
20
20
  import {
21
21
  reorderSubcommand
22
22
  } from "./chunk-M22O6CYY.js";
@@ -24,11 +24,11 @@ import {
24
24
  stamp_default
25
25
  } from "./chunk-64IF634X.js";
26
26
  import "./chunk-VXYGCOKL.js";
27
- import "./chunk-VE545BR3.js";
28
- import "./chunk-ECCWJHC6.js";
27
+ import "./chunk-HMJVUXE6.js";
28
+ import "./chunk-CYNB6LL4.js";
29
29
  import {
30
30
  outputAgentError
31
- } from "./chunk-TJLBCLEX.js";
31
+ } from "./chunk-TH2XUVDP.js";
32
32
  import "./chunk-GGP5R3FU.js";
33
33
  import "./chunk-VAFU7DXZ.js";
34
34
  import "./chunk-XLKFJPMT.js";
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  resolveMessageContent
9
- } from "./chunk-3BU2UCGV.js";
9
+ } from "./chunk-PIMIKY4X.js";
10
10
  import {
11
11
  parseThreadArg
12
12
  } from "./chunk-E336ZXPP.js";
@@ -16,20 +16,20 @@ import {
16
16
  resolveCommentsScope,
17
17
  threadNotFoundMessage,
18
18
  toApiErrorParts
19
- } from "./chunk-5DVMXOFT.js";
19
+ } from "./chunk-DDIZGOCK.js";
20
20
  import "./chunk-2473DUBR.js";
21
21
  import {
22
22
  outputError
23
- } from "./chunk-P65EEFTR.js";
23
+ } from "./chunk-KQRVZWJU.js";
24
24
  import {
25
25
  validateJsonOutput
26
26
  } from "./chunk-KXDWXXJH.js";
27
27
  import {
28
28
  replySubcommand
29
29
  } from "./chunk-GMWRTZVZ.js";
30
- import "./chunk-VE545BR3.js";
31
- import "./chunk-ECCWJHC6.js";
32
- import "./chunk-TJLBCLEX.js";
30
+ import "./chunk-HMJVUXE6.js";
31
+ import "./chunk-CYNB6LL4.js";
32
+ import "./chunk-TH2XUVDP.js";
33
33
  import "./chunk-GGP5R3FU.js";
34
34
  import "./chunk-VAFU7DXZ.js";
35
35
  import {
@@ -14,13 +14,13 @@ import {
14
14
  threadNotFoundMessage,
15
15
  toApiErrorParts,
16
16
  updateThread
17
- } from "./chunk-5DVMXOFT.js";
17
+ } from "./chunk-DDIZGOCK.js";
18
18
  import {
19
19
  canPrompt
20
20
  } from "./chunk-2473DUBR.js";
21
21
  import {
22
22
  outputError
23
- } from "./chunk-P65EEFTR.js";
23
+ } from "./chunk-KQRVZWJU.js";
24
24
  import {
25
25
  validateJsonOutput
26
26
  } from "./chunk-KXDWXXJH.js";
@@ -28,9 +28,9 @@ import {
28
28
  reopenSubcommand,
29
29
  resolveSubcommand
30
30
  } from "./chunk-GMWRTZVZ.js";
31
- import "./chunk-VE545BR3.js";
32
- import "./chunk-ECCWJHC6.js";
33
- import "./chunk-TJLBCLEX.js";
31
+ import "./chunk-HMJVUXE6.js";
32
+ import "./chunk-CYNB6LL4.js";
33
+ import "./chunk-TH2XUVDP.js";
34
34
  import "./chunk-GGP5R3FU.js";
35
35
  import "./chunk-VAFU7DXZ.js";
36
36
  import {
@@ -19,7 +19,7 @@ import {
19
19
  requireProjectContext,
20
20
  validateRequiredArguments,
21
21
  withGlobalFlags
22
- } from "./chunk-ZUVJISHS.js";
22
+ } from "./chunk-HJVTLJHO.js";
23
23
  import {
24
24
  restoreSubcommand
25
25
  } from "./chunk-M22O6CYY.js";
@@ -27,11 +27,11 @@ import {
27
27
  stamp_default
28
28
  } from "./chunk-64IF634X.js";
29
29
  import "./chunk-VXYGCOKL.js";
30
- import "./chunk-VE545BR3.js";
31
- import "./chunk-ECCWJHC6.js";
30
+ import "./chunk-HMJVUXE6.js";
31
+ import "./chunk-CYNB6LL4.js";
32
32
  import {
33
33
  outputAgentError
34
- } from "./chunk-TJLBCLEX.js";
34
+ } from "./chunk-TH2XUVDP.js";
35
35
  import "./chunk-GGP5R3FU.js";
36
36
  import "./chunk-VAFU7DXZ.js";
37
37
  import "./chunk-XLKFJPMT.js";