@koda-sl/baker-cli 0.354.0-dev.e6a354971 → 0.354.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 +3 -8
- package/dist/{chunk-B7MLH3K6.js → chunk-4HRJQGVW.js} +4 -4
- package/dist/chunk-4HRJQGVW.js.map +1 -0
- package/dist/cli.js +197 -88
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-B7MLH3K6.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
validateCanvasDeep,
|
|
69
69
|
withoutCastName,
|
|
70
70
|
ytDlpBlockSignal
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-4HRJQGVW.js";
|
|
72
72
|
import {
|
|
73
73
|
csvOrJson,
|
|
74
74
|
daysAgoIso,
|
|
@@ -10564,6 +10564,102 @@ function hintsFor(scope, days) {
|
|
|
10564
10564
|
return hints2;
|
|
10565
10565
|
}
|
|
10566
10566
|
|
|
10567
|
+
// src/commands/ads/google/list-fields.ts
|
|
10568
|
+
var LIST_FIELDS = /* @__PURE__ */ new Set([
|
|
10569
|
+
"ad.final_mobile_urls",
|
|
10570
|
+
"ad.final_urls",
|
|
10571
|
+
"ad_group.excluded_parent_asset_field_types",
|
|
10572
|
+
"ad_group.excluded_parent_asset_set_types",
|
|
10573
|
+
"ad_group.labels",
|
|
10574
|
+
"ad_group.primary_status_reasons",
|
|
10575
|
+
"ad_group_ad.ad.final_mobile_urls",
|
|
10576
|
+
"ad_group_ad.ad.final_urls",
|
|
10577
|
+
"ad_group_ad.labels",
|
|
10578
|
+
"ad_group_ad.primary_status_reasons",
|
|
10579
|
+
"ad_group_asset.primary_status_reasons",
|
|
10580
|
+
"ad_group_criterion.disapproval_reasons",
|
|
10581
|
+
"ad_group_criterion.final_mobile_urls",
|
|
10582
|
+
"ad_group_criterion.final_urls",
|
|
10583
|
+
"ad_group_criterion.labels",
|
|
10584
|
+
"ad_group_criterion.primary_status_reasons",
|
|
10585
|
+
"ad_group_criterion.topic.path",
|
|
10586
|
+
"ad_group_criterion.webpage.sample.sample_urls",
|
|
10587
|
+
"asset.dynamic_custom_asset.contextual_keywords",
|
|
10588
|
+
"asset.dynamic_custom_asset.similar_ids",
|
|
10589
|
+
"asset.dynamic_education_asset.contextual_keywords",
|
|
10590
|
+
"asset.dynamic_education_asset.similar_program_ids",
|
|
10591
|
+
"asset.dynamic_flights_asset.similar_destination_ids",
|
|
10592
|
+
"asset.dynamic_hotels_and_rentals_asset.contextual_keywords",
|
|
10593
|
+
"asset.dynamic_hotels_and_rentals_asset.similar_property_ids",
|
|
10594
|
+
"asset.dynamic_jobs_asset.contextual_keywords",
|
|
10595
|
+
"asset.dynamic_jobs_asset.similar_job_ids",
|
|
10596
|
+
"asset.dynamic_local_asset.contextual_keywords",
|
|
10597
|
+
"asset.dynamic_local_asset.similar_deal_ids",
|
|
10598
|
+
"asset.dynamic_real_estate_asset.contextual_keywords",
|
|
10599
|
+
"asset.dynamic_real_estate_asset.similar_listing_ids",
|
|
10600
|
+
"asset.dynamic_travel_asset.contextual_keywords",
|
|
10601
|
+
"asset.dynamic_travel_asset.similar_destination_ids",
|
|
10602
|
+
"asset.final_mobile_urls",
|
|
10603
|
+
"asset.final_urls",
|
|
10604
|
+
"asset.page_feed_asset.labels",
|
|
10605
|
+
"asset.structured_snippet_asset.values",
|
|
10606
|
+
"asset_group.final_mobile_urls",
|
|
10607
|
+
"asset_group.final_urls",
|
|
10608
|
+
"asset_group.primary_status_reasons",
|
|
10609
|
+
"asset_group_asset.primary_status_reasons",
|
|
10610
|
+
"asset_group_signal.disapproval_reasons",
|
|
10611
|
+
"asset_set.business_profile_location_group.dynamic_business_profile_location_group_filter.label_filters",
|
|
10612
|
+
"asset_set.business_profile_location_group.dynamic_business_profile_location_group_filter.listing_id_filters",
|
|
10613
|
+
"asset_set.location_set.business_profile_location_set.label_filters",
|
|
10614
|
+
"asset_set.location_set.business_profile_location_set.listing_id_filters",
|
|
10615
|
+
"bidding_data_exclusion.advertising_channel_types",
|
|
10616
|
+
"bidding_data_exclusion.campaigns",
|
|
10617
|
+
"bidding_data_exclusion.devices",
|
|
10618
|
+
"bidding_seasonality_adjustment.advertising_channel_types",
|
|
10619
|
+
"bidding_seasonality_adjustment.campaigns",
|
|
10620
|
+
"bidding_seasonality_adjustment.devices",
|
|
10621
|
+
"campaign.excluded_parent_asset_field_types",
|
|
10622
|
+
"campaign.excluded_parent_asset_set_types",
|
|
10623
|
+
"campaign.feed_types",
|
|
10624
|
+
"campaign.labels",
|
|
10625
|
+
"campaign.optimization_goal_setting.optimization_goal_types",
|
|
10626
|
+
"campaign.primary_status_reasons",
|
|
10627
|
+
"campaign.selective_optimization.conversion_actions",
|
|
10628
|
+
"campaign.shopping_setting.advertising_partner_ids",
|
|
10629
|
+
"campaign.text_guidelines.term_exclusions",
|
|
10630
|
+
"campaign_asset.primary_status_reasons",
|
|
10631
|
+
"campaign_criterion.location_group.geo_target_constants",
|
|
10632
|
+
"campaign_criterion.topic.path",
|
|
10633
|
+
"campaign_criterion.webpage.sample.sample_urls",
|
|
10634
|
+
"conversion_value_rule.audience_condition.user_interests",
|
|
10635
|
+
"conversion_value_rule.audience_condition.user_lists",
|
|
10636
|
+
"conversion_value_rule.device_condition.device_types",
|
|
10637
|
+
"conversion_value_rule.geo_location_condition.excluded_geo_target_constants",
|
|
10638
|
+
"conversion_value_rule.geo_location_condition.geo_target_constants",
|
|
10639
|
+
"conversion_value_rule_set.conversion_value_rules",
|
|
10640
|
+
"conversion_value_rule_set.dimensions",
|
|
10641
|
+
"custom_conversion_goal.conversion_actions",
|
|
10642
|
+
"customer.pay_per_conversion_eligibility_failure_reasons",
|
|
10643
|
+
"customer_asset.primary_status_reasons",
|
|
10644
|
+
"customer_client.applied_labels",
|
|
10645
|
+
"experiment_arm.campaigns",
|
|
10646
|
+
"experiment_arm.in_design_campaigns",
|
|
10647
|
+
"keyword_plan_campaign.language_constants",
|
|
10648
|
+
"local_services_employee.category_ids",
|
|
10649
|
+
"local_services_employee.languages_spoken",
|
|
10650
|
+
"metrics.interaction_event_types",
|
|
10651
|
+
"recommendation.campaigns",
|
|
10652
|
+
"shared_criterion.webpage.sample.sample_urls",
|
|
10653
|
+
"shopping_product.target_countries",
|
|
10654
|
+
"topic_constant.path",
|
|
10655
|
+
"user_list.lookalike_user_list.country_codes",
|
|
10656
|
+
"user_list.lookalike_user_list.seed_user_list_ids"
|
|
10657
|
+
]);
|
|
10658
|
+
var LIST_FIELD_OPERATORS = "CONTAINS ALL, CONTAINS ANY, CONTAINS NONE";
|
|
10659
|
+
function listFieldGuidance(field) {
|
|
10660
|
+
return `${field} is a list field: it takes only ${LIST_FIELD_OPERATORS} \u2014 no comparison (=, !=, IN), pattern match or null test. To find rows that have it, drop that condition, keep ${field} in SELECT and filter the rows (rows without it omit the key); to match values, use ${field} CONTAINS ANY ('value')`;
|
|
10661
|
+
}
|
|
10662
|
+
|
|
10567
10663
|
// src/commands/ads/google/correction-table.ts
|
|
10568
10664
|
function buildCommand(query, ctx) {
|
|
10569
10665
|
return `baker ads google query "${query}" --customer-id ${ctx.customerId}`;
|
|
@@ -10591,6 +10687,27 @@ var CORRECTION_RULES = [
|
|
|
10591
10687
|
};
|
|
10592
10688
|
}
|
|
10593
10689
|
},
|
|
10690
|
+
// 0b. OPERATOR_FIELD_MISMATCH — the field refuses this operator, and Google names the
|
|
10691
|
+
// ones it takes. Kept ahead of the field-specific rules for the same reason as rule 0.
|
|
10692
|
+
// A repeated field (final_urls, labels, …) takes only CONTAINS ALL/ANY/NONE, so it has
|
|
10693
|
+
// no null test at all: read it unfiltered and filter the rows instead.
|
|
10694
|
+
{
|
|
10695
|
+
matchApiError: /OPERATOR_FIELD_MISMATCH|is not a valid operator to use with/i,
|
|
10696
|
+
fix: (ctx) => {
|
|
10697
|
+
const message = ctx.apiErrorMessage ?? "";
|
|
10698
|
+
const field = message.match(/valid operator to use with '([\w.]+)'/i)?.[1] ?? "this field";
|
|
10699
|
+
const operator = message.match(/([A-Z=!<>][A-Z_ =!<>]*?) is not a valid operator/)?.[1]?.trim();
|
|
10700
|
+
const valid = message.match(/Valid operators: (.+?)\.?(?:"|$)/i)?.[1]?.trim();
|
|
10701
|
+
const refused = operator ? `${operator} cannot be used on ${field}` : `${field} does not take that operator`;
|
|
10702
|
+
const allowed = valid ? `; its valid operators are ${valid}` : "";
|
|
10703
|
+
const repeated = valid?.split(",").every((op) => /^CONTAINS (ALL|ANY|NONE)$/i.test(op.trim())) ?? false;
|
|
10704
|
+
const guidance = repeated ? `. ${listFieldGuidance(field)}` : ". Rewrite that condition with one of them, or drop it and filter the rows";
|
|
10705
|
+
return {
|
|
10706
|
+
action: "change_operator",
|
|
10707
|
+
explanation: `${refused}${allowed}${guidance}`
|
|
10708
|
+
};
|
|
10709
|
+
}
|
|
10710
|
+
},
|
|
10594
10711
|
// 1. bare keyword.text → ad_group_criterion.keyword.text (leaves <resource>.keyword.text untouched)
|
|
10595
10712
|
{
|
|
10596
10713
|
matchQuery: /(?<![\w.])keyword\.text\b/,
|
|
@@ -10633,10 +10750,11 @@ var CORRECTION_RULES = [
|
|
|
10633
10750
|
};
|
|
10634
10751
|
}
|
|
10635
10752
|
},
|
|
10636
|
-
// 4. CONTAINS → LIKE
|
|
10753
|
+
// 4. CONTAINS → LIKE. Keyed on the query alone: Google's error envelope ("Request contains an
|
|
10754
|
+
// invalid argument … Valid operators: CONTAINS ANY") matches any loose error pattern, and this
|
|
10755
|
+
// advice only makes sense when the query actually wrote CONTAINS(…).
|
|
10637
10756
|
{
|
|
10638
10757
|
matchQuery: /CONTAINS\s*\(/i,
|
|
10639
|
-
matchApiError: /CONTAINS.*not.*supported|invalid.*operator.*CONTAINS/i,
|
|
10640
10758
|
fix: (ctx) => {
|
|
10641
10759
|
const match = ctx.originalQuery.match(/CONTAINS\s*\(\s*([^,]+),\s*'([^']+)'\s*\)/i);
|
|
10642
10760
|
if (match) {
|
|
@@ -13082,6 +13200,73 @@ function rejectOversizedLimit(query, customerId) {
|
|
|
13082
13200
|
}
|
|
13083
13201
|
};
|
|
13084
13202
|
}
|
|
13203
|
+
var WHERE_OPERATOR = /(?<![\w.])([a-z_]+(?:\.[a-z_]+)+)\s*(CONTAINS\s+(?:ALL|ANY|NONE)|IS\s+NOT\s+NULL|IS\s+NULL|NOT\s+LIKE|NOT\s+IN|NOT\s+REGEXP_MATCH|REGEXP_MATCH|LIKE|IN|BETWEEN|DURING|!=|<=|>=|=|<|>)/gi;
|
|
13204
|
+
function escapeRegExp(text2) {
|
|
13205
|
+
return text2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13206
|
+
}
|
|
13207
|
+
function withoutNullTest(query, field) {
|
|
13208
|
+
const test = `${escapeRegExp(field)}\\s+IS\\s+(?:NOT\\s+)?NULL\\b`;
|
|
13209
|
+
const dropped = query.replace(new RegExp(`\\bWHERE\\s+${test}\\s+AND\\s+`, "i"), "WHERE ").replace(new RegExp(`\\s+AND\\s+${test}`, "i"), "").replace(new RegExp(`\\s*\\bWHERE\\s+${test}`, "i"), "");
|
|
13210
|
+
return mentions(selectClause(dropped), field) ? dropped : dropped.replace(/SELECT\s+/i, `SELECT ${field}, `);
|
|
13211
|
+
}
|
|
13212
|
+
function asListCondition(query, field) {
|
|
13213
|
+
const condition = new RegExp(
|
|
13214
|
+
`(?<![\\w.])${escapeRegExp(field)}\\s*(NOT\\s+IN\\b|IN\\b|!=|=)\\s*('[^']*'|\\([^)]*\\))`,
|
|
13215
|
+
"i"
|
|
13216
|
+
);
|
|
13217
|
+
const match = query.match(condition);
|
|
13218
|
+
if (!match) return null;
|
|
13219
|
+
const [, operator = "", value = ""] = match;
|
|
13220
|
+
const contains = /^(=|IN)$/i.test(operator.trim()) ? "CONTAINS ANY" : "CONTAINS NONE";
|
|
13221
|
+
const values = value.startsWith("(") ? value : `(${value})`;
|
|
13222
|
+
return query.replace(condition, `${field} ${contains} ${values}`);
|
|
13223
|
+
}
|
|
13224
|
+
function rejectListFieldOperator(query, customerId) {
|
|
13225
|
+
const where = whereClause(query).replace(/'[^']*'/g, "''");
|
|
13226
|
+
const refusals = [...where.matchAll(WHERE_OPERATOR)].map(([, field = "", operator = ""]) => ({
|
|
13227
|
+
field: field.toLowerCase(),
|
|
13228
|
+
operator: operator.toUpperCase().replace(/\s+/g, " ")
|
|
13229
|
+
})).filter(({ field, operator }) => LIST_FIELDS.has(field) && !operator.startsWith("CONTAINS"));
|
|
13230
|
+
const first = refusals[0];
|
|
13231
|
+
if (!first) return null;
|
|
13232
|
+
const fixed = refusals.reduce(
|
|
13233
|
+
(corrected, { field, operator }) => corrected === null ? null : operator.startsWith("IS ") ? withoutNullTest(corrected, field) : asListCondition(corrected, field),
|
|
13234
|
+
query
|
|
13235
|
+
);
|
|
13236
|
+
return {
|
|
13237
|
+
ok: false,
|
|
13238
|
+
error: {
|
|
13239
|
+
code: "INVALID_OPERATOR",
|
|
13240
|
+
message: `${first.operator} cannot be used on ${first.field}: it is a list field, so Google would refuse this query.`,
|
|
13241
|
+
fix: {
|
|
13242
|
+
action: "change_operator",
|
|
13243
|
+
...fixed ? { correctedCommand: buildCommand2(fixed, customerId) } : {},
|
|
13244
|
+
explanation: listFieldGuidance(first.field)
|
|
13245
|
+
},
|
|
13246
|
+
retryable: false
|
|
13247
|
+
}
|
|
13248
|
+
};
|
|
13249
|
+
}
|
|
13250
|
+
function rejectContainsCall(query, customerId) {
|
|
13251
|
+
const containsMatch = query.match(/CONTAINS\s*\(\s*([^,]+),\s*'([^']+)'\s*\)/i);
|
|
13252
|
+
if (!containsMatch) return null;
|
|
13253
|
+
const field = containsMatch[1]?.trim();
|
|
13254
|
+
const value = containsMatch[2] ?? "";
|
|
13255
|
+
const fixed = query.replace(/CONTAINS\s*\(\s*[^,]+,\s*'[^']+'\s*\)/i, `${field} LIKE '%${value}%'`);
|
|
13256
|
+
return {
|
|
13257
|
+
ok: false,
|
|
13258
|
+
error: {
|
|
13259
|
+
code: "INVALID_OPERATOR",
|
|
13260
|
+
message: "GAQL does not support CONTAINS. Use LIKE with % wildcards.",
|
|
13261
|
+
fix: {
|
|
13262
|
+
action: "change_operator",
|
|
13263
|
+
correctedCommand: buildCommand2(fixed, customerId),
|
|
13264
|
+
explanation: "GAQL uses LIKE '%value%' for substring matching, not CONTAINS()"
|
|
13265
|
+
},
|
|
13266
|
+
retryable: false
|
|
13267
|
+
}
|
|
13268
|
+
};
|
|
13269
|
+
}
|
|
13085
13270
|
function validatePreflight(query, customerId, limit) {
|
|
13086
13271
|
const warnings = [];
|
|
13087
13272
|
const corrected = query;
|
|
@@ -13104,29 +13289,6 @@ function validatePreflight(query, customerId, limit) {
|
|
|
13104
13289
|
}
|
|
13105
13290
|
};
|
|
13106
13291
|
}
|
|
13107
|
-
const containsMatch = corrected.match(/CONTAINS\s*\(\s*([^,]+),\s*'([^']+)'\s*\)/i);
|
|
13108
|
-
if (containsMatch) {
|
|
13109
|
-
const field = containsMatch[1]?.trim();
|
|
13110
|
-
const value = containsMatch[2] ?? "";
|
|
13111
|
-
const fixed = corrected.replace(/CONTAINS\s*\(\s*[^,]+,\s*'[^']+'\s*\)/i, `${field} LIKE '%${value}%'`);
|
|
13112
|
-
return {
|
|
13113
|
-
valid: false,
|
|
13114
|
-
warnings: [],
|
|
13115
|
-
error: {
|
|
13116
|
-
ok: false,
|
|
13117
|
-
error: {
|
|
13118
|
-
code: "INVALID_OPERATOR",
|
|
13119
|
-
message: "GAQL does not support CONTAINS. Use LIKE with % wildcards.",
|
|
13120
|
-
fix: {
|
|
13121
|
-
action: "change_operator",
|
|
13122
|
-
correctedCommand: buildCommand2(fixed, customerId),
|
|
13123
|
-
explanation: "GAQL uses LIKE '%value%' for substring matching, not CONTAINS()"
|
|
13124
|
-
},
|
|
13125
|
-
retryable: false
|
|
13126
|
-
}
|
|
13127
|
-
}
|
|
13128
|
-
};
|
|
13129
|
-
}
|
|
13130
13292
|
const openDateMatch = corrected.match(/segments\.date\s*>=\s*'(\d{4}-\d{2}-\d{2})'/i);
|
|
13131
13293
|
if (openDateMatch && !/BETWEEN/i.test(corrected)) {
|
|
13132
13294
|
const startDate = openDateMatch[1] ?? "";
|
|
@@ -13153,10 +13315,10 @@ function validatePreflight(query, customerId, limit) {
|
|
|
13153
13315
|
}
|
|
13154
13316
|
};
|
|
13155
13317
|
}
|
|
13156
|
-
const
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13318
|
+
for (const reject of [rejectContainsCall, rejectListFieldOperator, rejectUnsupportedDuring, rejectOversizedLimit]) {
|
|
13319
|
+
const rejection2 = reject(corrected, customerId);
|
|
13320
|
+
if (rejection2) return { valid: false, warnings: [], error: rejection2 };
|
|
13321
|
+
}
|
|
13160
13322
|
if (/\bsegments\.conversion_action_name\b/i.test(corrected) && /\bmetrics\.cost_micros\b/i.test(corrected)) {
|
|
13161
13323
|
return {
|
|
13162
13324
|
valid: false,
|
|
@@ -33401,19 +33563,6 @@ function pageOf(args5) {
|
|
|
33401
33563
|
...size ? { pageSize: Number(size) } : {}
|
|
33402
33564
|
};
|
|
33403
33565
|
}
|
|
33404
|
-
function isWholePositive(raw) {
|
|
33405
|
-
return /^[1-9]\d*$/.test(String(raw));
|
|
33406
|
-
}
|
|
33407
|
-
function paginationError(args5) {
|
|
33408
|
-
if (args5.page !== void 0 && !isWholePositive(args5.page)) {
|
|
33409
|
-
return `--page takes a page number of a list report (1, 2, \u2026), not "${String(args5.page)}". To narrow a report to one page of the site, pass --landing <internalId> (from \`baker analytics landings\`), or read one path with \`baker analytics page --path /pricing\`.`;
|
|
33410
|
-
}
|
|
33411
|
-
const size = args5["page-size"];
|
|
33412
|
-
if (size !== void 0 && !isWholePositive(size)) {
|
|
33413
|
-
return `--page-size takes a number of rows (1 to 200), not "${String(size)}".`;
|
|
33414
|
-
}
|
|
33415
|
-
return null;
|
|
33416
|
-
}
|
|
33417
33566
|
function requestBody(args5, options) {
|
|
33418
33567
|
const candidates = {
|
|
33419
33568
|
preset: options.preset,
|
|
@@ -33478,11 +33627,6 @@ async function runPreset(args5, options) {
|
|
|
33478
33627
|
});
|
|
33479
33628
|
process.exit(1);
|
|
33480
33629
|
}
|
|
33481
|
-
const pagination = paginationError(args5);
|
|
33482
|
-
if (pagination) {
|
|
33483
|
-
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message: pagination } });
|
|
33484
|
-
process.exit(1);
|
|
33485
|
-
}
|
|
33486
33630
|
try {
|
|
33487
33631
|
const response = await apiPost("/api/analytics/query", requestBody(args5, options));
|
|
33488
33632
|
const requestedPlatform = args5.platform === void 0 ? "" : String(args5.platform);
|
|
@@ -57541,7 +57685,7 @@ function mentionsInSource(source, names) {
|
|
|
57541
57685
|
const out = [];
|
|
57542
57686
|
for (const name of names) {
|
|
57543
57687
|
const seen = /* @__PURE__ */ new Set();
|
|
57544
|
-
for (const m of visible.matchAll(new RegExp(`\\b${
|
|
57688
|
+
for (const m of visible.matchAll(new RegExp(`\\b${escapeRegExp2(name)}\\b`, "gi"))) {
|
|
57545
57689
|
const at = m.index ?? 0;
|
|
57546
57690
|
if (tables.some(([from, to]) => at >= from && at < to)) continue;
|
|
57547
57691
|
const start = sentenceStart(visible, at);
|
|
@@ -57570,7 +57714,7 @@ function blankHtmlKeepingOffsets(text2) {
|
|
|
57570
57714
|
}
|
|
57571
57715
|
return out.join("");
|
|
57572
57716
|
}
|
|
57573
|
-
function
|
|
57717
|
+
function escapeRegExp2(value) {
|
|
57574
57718
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
57575
57719
|
}
|
|
57576
57720
|
function detectSource(source) {
|
|
@@ -68628,36 +68772,19 @@ function findUnknownFlags(root, argv) {
|
|
|
68628
68772
|
}
|
|
68629
68773
|
return unknown;
|
|
68630
68774
|
}
|
|
68631
|
-
var SYNONYMS = {
|
|
68632
|
-
from: ["start-date", "start", "since"],
|
|
68633
|
-
since: ["start-date", "start", "from"],
|
|
68634
|
-
start: ["start-date", "since", "from"],
|
|
68635
|
-
to: ["end-date", "end", "until"],
|
|
68636
|
-
until: ["end-date", "end", "to"],
|
|
68637
|
-
end: ["end-date", "until", "to"],
|
|
68638
|
-
path: ["landing"],
|
|
68639
|
-
url: ["landing"]
|
|
68640
|
-
};
|
|
68641
68775
|
function closestFlag(unknown, command) {
|
|
68642
68776
|
const accepted = acceptedNames(command);
|
|
68643
68777
|
if (!accepted) {
|
|
68644
68778
|
return null;
|
|
68645
68779
|
}
|
|
68646
68780
|
const name = unknown.replace(/^--/, "").split("=")[0] ?? "";
|
|
68647
|
-
const synonym = SYNONYMS[name]?.find((candidate) => accepted.has(candidate));
|
|
68648
|
-
if (synonym) {
|
|
68649
|
-
return `--${synonym}`;
|
|
68650
|
-
}
|
|
68651
68781
|
const scored = [...accepted].filter((candidate) => !ALWAYS_ACCEPTED.has(candidate)).map((candidate) => ({
|
|
68652
68782
|
candidate,
|
|
68653
68783
|
prefix: sharedPrefix(name, candidate),
|
|
68654
68784
|
distance: editDistance(name, candidate)
|
|
68655
|
-
})).filter(({ prefix, distance }) => prefix >= 4 || distance <=
|
|
68785
|
+
})).filter(({ prefix, distance }) => prefix >= 4 || distance <= 3).sort((a, b) => b.prefix - a.prefix || a.distance - b.distance);
|
|
68656
68786
|
return scored[0] ? `--${scored[0].candidate}` : null;
|
|
68657
68787
|
}
|
|
68658
|
-
function typoBudget(name) {
|
|
68659
|
-
return Math.max(1, Math.floor(name.length / 3));
|
|
68660
|
-
}
|
|
68661
68788
|
function sharedPrefix(a, b) {
|
|
68662
68789
|
let i = 0;
|
|
68663
68790
|
while (i < a.length && i < b.length && a[i] === b[i]) {
|
|
@@ -68681,24 +68808,6 @@ function commandFor(root, argv) {
|
|
|
68681
68808
|
const { command, resolved } = resolveCommand2(root, argv);
|
|
68682
68809
|
return resolved ? command : null;
|
|
68683
68810
|
}
|
|
68684
|
-
function suggestFlag(unknown, command) {
|
|
68685
|
-
const flag = closestFlag(unknown, command);
|
|
68686
|
-
if (!flag) {
|
|
68687
|
-
return null;
|
|
68688
|
-
}
|
|
68689
|
-
const args5 = argsOf(command) ?? {};
|
|
68690
|
-
const name = flag.slice(2);
|
|
68691
|
-
const def = args5[name] ?? args5[camel(name)];
|
|
68692
|
-
const described = def && typeof def === "object" ? def.description : void 0;
|
|
68693
|
-
const description = typeof described === "string" ? described.split(/\.\s/)[0]?.trim().replace(/\.$/, "") : "";
|
|
68694
|
-
return description ? { flag, description } : { flag };
|
|
68695
|
-
}
|
|
68696
|
-
function suggestionText(suggestion) {
|
|
68697
|
-
if (!suggestion) {
|
|
68698
|
-
return "";
|
|
68699
|
-
}
|
|
68700
|
-
return suggestion.description ? `Did you mean ${suggestion.flag}? It is described as: ${suggestion.description}. ` : `Did you mean ${suggestion.flag}? `;
|
|
68701
|
-
}
|
|
68702
68811
|
var OUTPUT_EXPLANATION = "This command has no --output option: `--output json` is accepted by every command that prints the JSON envelope, and md or files only where `baker schema` lists `output`. Drop the option and read the default output. ";
|
|
68703
68812
|
function unknownFlagEnvelope(unknown, commandPath, suggestion, hasSchema) {
|
|
68704
68813
|
const list = unknown.join(", ");
|
|
@@ -68709,7 +68818,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion, hasSchema) {
|
|
|
68709
68818
|
message: `${list} ${unknown.length > 1 ? "are not options" : "is not an option"} of \`baker ${commandPath}\`.`,
|
|
68710
68819
|
fix: {
|
|
68711
68820
|
action: hasSchema ? "check_schema" : "check_help",
|
|
68712
|
-
explanation: (unknown.some((flag) => flag === "--output" || flag.startsWith("--output=")) ? OUTPUT_EXPLANATION : "") +
|
|
68821
|
+
explanation: (unknown.some((flag) => flag === "--output" || flag.startsWith("--output=")) ? OUTPUT_EXPLANATION : "") + (suggestion ? `Did you mean ${suggestion}? ` : "") + `Run \`${hasSchema ? `baker schema ${commandPath}` : `baker ${commandPath} --help`}\` to see every option this command takes. Do not re-run the same call: until this version an unrecognised option was accepted and ignored, so a command that looked like it had filtered or narrowed the result was in fact answering the unfiltered question.`
|
|
68713
68822
|
},
|
|
68714
68823
|
retryable: false
|
|
68715
68824
|
}
|
|
@@ -68739,7 +68848,7 @@ function refuseUnknownFlags(root, argv) {
|
|
|
68739
68848
|
}
|
|
68740
68849
|
const command = commandFor(root, argv);
|
|
68741
68850
|
const first = unknown[0];
|
|
68742
|
-
const suggestion = command && first ?
|
|
68851
|
+
const suggestion = command && first ? closestFlag(first, command) : null;
|
|
68743
68852
|
const path48 = commandPathOf(root, argv);
|
|
68744
68853
|
process.stdout.write(
|
|
68745
68854
|
`${JSON.stringify(unknownFlagEnvelope(unknown, path48, suggestion, findSchema(path48.split(" ")) !== void 0), null, 2)}
|