@tenderprompt/cli 0.1.11 → 0.1.12

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 (3) hide show
  1. package/README.md +9 -8
  2. package/dist/index.js +128 -266
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -169,7 +169,7 @@ tender app analytics suggestions artifact_123 --range 30d --json
169
169
 
170
170
  tender app analytics charts templates --json
171
171
 
172
- tender app analytics property-slots list artifact_123 --json
172
+ tender app analytics properties list artifact_123 --json
173
173
  ```
174
174
 
175
175
  Safe write previews:
@@ -177,7 +177,7 @@ Safe write previews:
177
177
  ```bash
178
178
  tender app analytics dashboards artifact_123 --create "Agent dashboard" --dry-run --json
179
179
 
180
- tender app analytics property-slots activate artifact_123 \
180
+ tender app analytics properties activate artifact_123 \
181
181
  --event signup_started \
182
182
  --property plan \
183
183
  --type dimension \
@@ -217,11 +217,12 @@ inspection. For example, inspect where the app calls
217
217
  `__TP_ANALYTICS.invoke(...)`, propose a chart spec, validate it with
218
218
  `analytics query`, and only then create a saved chart.
219
219
  Use `charts templates --json` for reusable chart shapes; adapt any placeholders
220
- to observed events, paths, or promoted property keys before querying or saving.
221
- Property group-bys and property metrics need promoted slots; `charts create`
222
- and `charts update` activate missing slots automatically when the spec includes
223
- an `event_name = ...` filter. `analytics query` is read-only, so use
224
- `property-slots activate` first when trying an ad hoc property query. When a
220
+ to observed events, paths, or queryable property keys before querying or saving.
221
+ Property group-bys and property metrics need the custom event property to be
222
+ available for dashboard queries; `charts create` and `charts update` activate
223
+ missing properties automatically when the spec includes an `event_name = ...`
224
+ filter. `analytics query` is read-only, so use
225
+ `properties activate` first when trying an ad hoc property query. When a
225
226
  query fails for a missing dashboard-query property, the CLI prints the exact
226
227
  activation commands to run and does not perform that write automatically.
227
228
 
@@ -237,7 +238,7 @@ activation commands to run and does not perform that write automatically.
237
238
  remote URLs.
238
239
  - Analytics commands use tenant/artifact-scoped API routes. They do not expose
239
240
  raw query credentials or raw SQL.
240
- - Property slot activation is an explicit analytics write and remains
241
+ - Dashboard-query property activation is an explicit analytics write and remains
241
242
  tenant/artifact-scoped.
242
243
  - Raw analytics event export is intentionally not available; exports are bounded
243
244
  catalog metadata or validated aggregate query rows.
package/dist/index.js CHANGED
@@ -213,10 +213,10 @@ Commands:
213
213
  Update a saved chart title or spec
214
214
  tender app analytics charts delete <app-id>
215
215
  Delete a saved chart
216
- tender app analytics property-slots list <app-id>
217
- List promoted property slots
218
- tender app analytics property-slots activate <app-id>
219
- Activate a promoted property slot
216
+ tender app analytics properties list <app-id>
217
+ List properties available to dashboard queries
218
+ tender app analytics properties activate <app-id>
219
+ Make a custom event property queryable
220
220
  tender app context fetch <app-id>
221
221
  Fetch AGENTS.md, skills, and Tender App scaffold files
222
222
  tender app context status <app-id>
@@ -255,8 +255,8 @@ Examples:
255
255
  tender app analytics charts list artifact_123 --dashboard analytics_dashboard_123 --json
256
256
  tender app analytics charts update artifact_123 --chart analytics_chart_123 --title "Signup funnel" --spec funnel.json --dry-run --json
257
257
  tender app analytics charts delete artifact_123 --chart analytics_chart_123 --dry-run --json
258
- tender app analytics property-slots list artifact_123 --json
259
- tender app analytics property-slots activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json
258
+ tender app analytics properties list artifact_123 --json
259
+ tender app analytics properties activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json
260
260
  tender app context fetch artifact_123 --dir ./widget --dry-run --json
261
261
  tender app context status artifact_123 --dir ./widget --json
262
262
  tender app context refresh artifact_123 --dir ./widget --dry-run --json
@@ -294,8 +294,8 @@ Commands:
294
294
  tender app analytics charts list <app-id> List saved charts in one dashboard
295
295
  tender app analytics charts update <app-id> Update a saved chart
296
296
  tender app analytics charts delete <app-id> Delete a saved chart
297
- tender app analytics property-slots list <app-id> List promoted property slots
298
- tender app analytics property-slots activate <app-id> Activate a promoted property slot
297
+ tender app analytics properties list <app-id> List queryable custom event properties
298
+ tender app analytics properties activate <app-id> Make a property queryable
299
299
 
300
300
  Examples:
301
301
  tender app analytics summary artifact_123 --range 30d --json
@@ -311,8 +311,8 @@ Examples:
311
311
  tender app analytics charts list artifact_123 --dashboard analytics_dashboard_123 --json
312
312
  tender app analytics charts update artifact_123 --chart analytics_chart_123 --title "Signup funnel" --spec funnel.json --dry-run --json
313
313
  tender app analytics charts delete artifact_123 --chart analytics_chart_123 --dry-run --json
314
- tender app analytics property-slots list artifact_123 --json
315
- tender app analytics property-slots activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json`;
314
+ tender app analytics properties list artifact_123 --json
315
+ tender app analytics properties activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json`;
316
316
  }
317
317
  function analyticsSummaryHelp() {
318
318
  return `Usage: tender app analytics summary <app-id> [--range <7d|30d|90d|YYYY-MM-DD..YYYY-MM-DD>] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
@@ -388,7 +388,7 @@ Examples:
388
388
  function analyticsChartsCreateHelp() {
389
389
  return `Usage: tender app analytics charts create <app-id> --dashboard <dashboard-id> --title <title> --spec <file|-> [--dry-run] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
390
390
 
391
- Property charts automatically activate required promoted property slots before
391
+ Property charts automatically make required custom event properties queryable before
392
392
  saving when the spec has an event_name = filter.
393
393
 
394
394
  Examples:
@@ -406,7 +406,7 @@ function analyticsChartsUpdateHelp() {
406
406
 
407
407
  At least one of --title or --spec is required. When one is omitted, the CLI reads
408
408
  the existing saved chart and keeps that value.
409
- Property charts automatically activate required promoted property slots before
409
+ Property charts automatically make required custom event properties queryable before
410
410
  saving when the spec has an event_name = filter.
411
411
 
412
412
  Examples:
@@ -421,19 +421,19 @@ Examples:
421
421
  tender app analytics charts delete artifact_123 --chart analytics_chart_123 --dry-run --json
422
422
  tender app analytics charts delete artifact_123 --chart analytics_chart_123 --json`;
423
423
  }
424
- function analyticsPropertySlotsListHelp() {
425
- return `Usage: tender app analytics property-slots list <app-id> [--event <event-name>] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
424
+ function analyticsPropertiesListHelp() {
425
+ return `Usage: tender app analytics properties list <app-id> [--event <event-name>] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
426
426
 
427
427
  Examples:
428
- tender app analytics property-slots list artifact_123 --json
429
- tender app analytics property-slots list artifact_123 --event signup_started --json`;
428
+ tender app analytics properties list artifact_123 --json
429
+ tender app analytics properties list artifact_123 --event signup_started --json`;
430
430
  }
431
- function analyticsPropertySlotsActivateHelp() {
432
- return `Usage: tender app analytics property-slots activate <app-id> --event <event-name> --property <property-key> --type <dimension|metric> [--slot <slot-name>] [--label <label>] [--dry-run] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
431
+ function analyticsPropertiesActivateHelp() {
432
+ return `Usage: tender app analytics properties activate <app-id> --event <event-name> --property <property-key> --type <dimension|metric> [--label <label>] [--dry-run] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
433
433
 
434
434
  Examples:
435
- tender app analytics property-slots activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json
436
- tender app analytics property-slots activate artifact_123 --event score_saved --property score --type metric --json`;
435
+ tender app analytics properties activate artifact_123 --event signup_started --property plan --type dimension --dry-run --json
436
+ tender app analytics properties activate artifact_123 --event score_saved --property score --type metric --json`;
437
437
  }
438
438
  function artifactsListHelp() {
439
439
  return `Usage: tender app list [--base-url <url>] [--token <token>] [--profile <name>] [--json]
@@ -816,8 +816,8 @@ function tenderCliCapabilities() {
816
816
  "tender app analytics charts templates --json",
817
817
  "tender app analytics query <artifact-id> --spec chart.json --json",
818
818
  "tender app analytics export query <artifact-id> --spec chart.json --format csv",
819
- "tender app analytics property-slots list <artifact-id> --json",
820
- "tender app analytics property-slots activate <artifact-id> --event <event-name> --property <property-key> --type dimension --dry-run --json",
819
+ "tender app analytics properties list <artifact-id> --json",
820
+ "tender app analytics properties activate <artifact-id> --event <event-name> --property <property-key> --type dimension --dry-run --json",
821
821
  "tender app analytics dashboards <artifact-id> --create \"Agent dashboard\" --dry-run --json",
822
822
  "tender app analytics charts create <artifact-id> --dashboard <dashboard-id> --title <title> --spec chart.json --dry-run --json",
823
823
  "tender app analytics charts list <artifact-id> --dashboard <dashboard-id> --json",
@@ -827,8 +827,8 @@ function tenderCliCapabilities() {
827
827
  notes: [
828
828
  "Combine CLI capabilities with local source inspection of analytics calls.",
829
829
  "Validate chart specs with query before creating or updating saved charts.",
830
- "Property chart create/update commands automatically activate missing promoted property slots when the spec has an event_name = filter.",
831
- "Ad hoc query is read-only; if it reports a missing property slot, activate the slot first or save the chart through charts create/update.",
830
+ "Property chart create/update commands automatically make missing custom event properties queryable when the spec has an event_name = filter.",
831
+ "Ad hoc query is read-only; if it reports a missing dashboard-query property, activate the property first or save the chart through charts create/update.",
832
832
  "Use list before writes so agents can avoid duplicates and explain the exact chart they are changing.",
833
833
  ],
834
834
  },
@@ -886,14 +886,14 @@ function tenderCliCapabilities() {
886
886
  writes: false,
887
887
  },
888
888
  {
889
- command: "tender app analytics property-slots list <artifact-id> --json",
890
- purpose: "List active promoted property slots that make custom event properties queryable.",
889
+ command: "tender app analytics properties list <artifact-id> --json",
890
+ purpose: "List custom event properties available to dashboard queries.",
891
891
  requiresAuth: true,
892
892
  writes: false,
893
893
  },
894
894
  {
895
- command: "tender app analytics property-slots activate <artifact-id> --event <event-name> --property <property-key> --type <dimension|metric> --dry-run --json",
896
- purpose: "Preview or activate the promoted slot needed for a property group-by or property metric chart.",
895
+ command: "tender app analytics properties activate <artifact-id> --event <event-name> --property <property-key> --type <dimension|metric> --dry-run --json",
896
+ purpose: "Preview or activate the custom event property needed for a property group-by or property metric chart.",
897
897
  requiresAuth: true,
898
898
  writes: true,
899
899
  dryRun: true,
@@ -2938,13 +2938,13 @@ function analyticsChartTemplates() {
2938
2938
  id: "property_breakdown",
2939
2939
  title: "Property breakdown",
2940
2940
  visualization: "bar",
2941
- purpose: "Compare a promoted dimension property observed in events.",
2941
+ purpose: "Compare a queryable dimension property observed in events.",
2942
2942
  usableAsIs: false,
2943
2943
  placeholders: {
2944
- property: "<promoted_dimension_property>",
2944
+ property: "<queryable_dimension_property>",
2945
2945
  },
2946
2946
  adaptWith: [
2947
- "Use a property key promoted by capabilities chartSpec.groupBy, such as property:plan.",
2947
+ "Use a queryable property key from capabilities chartSpec.groupBy, such as property:plan.",
2948
2948
  "Choose stable categorical properties with enough observations to compare.",
2949
2949
  ],
2950
2950
  spec: {
@@ -2952,7 +2952,7 @@ function analyticsChartTemplates() {
2952
2952
  dataset: "events",
2953
2953
  visualization: "bar",
2954
2954
  metric: { name: "custom_event_count" },
2955
- groupBy: [{ field: "property:<promoted_dimension_property>" }],
2955
+ groupBy: [{ field: "property:<queryable_dimension_property>" }],
2956
2956
  filters: [],
2957
2957
  range: { preset: "30d" },
2958
2958
  sort: [{ field: "value", direction: "desc" }],
@@ -2966,17 +2966,17 @@ function analyticsChartTemplates() {
2966
2966
  purpose: "Track an observed numeric event property over time.",
2967
2967
  usableAsIs: false,
2968
2968
  placeholders: {
2969
- metric: "avg:<promoted_metric_property>",
2969
+ metric: "avg:<queryable_metric_property>",
2970
2970
  },
2971
2971
  adaptWith: [
2972
- "Use a numeric property key promoted by capabilities chartSpec.metrics.",
2972
+ "Use a queryable numeric property key from capabilities chartSpec.metrics.",
2973
2973
  "Prefer averages for scores, durations, quantities, or ordinal values.",
2974
2974
  ],
2975
2975
  spec: {
2976
2976
  version: 1,
2977
2977
  dataset: "events",
2978
2978
  visualization: "line",
2979
- metric: { name: "avg:<promoted_metric_property>" },
2979
+ metric: { name: "avg:<queryable_metric_property>" },
2980
2980
  groupBy: [{ field: "day" }],
2981
2981
  filters: [],
2982
2982
  range: { preset: "30d" },
@@ -3019,7 +3019,7 @@ function runAnalyticsChartsTemplates(command, io) {
3019
3019
  templates,
3020
3020
  next: [
3021
3021
  "Run tender app analytics capabilities <artifact-id> --include-catalog --range 30d --json.",
3022
- "Choose a template and replace placeholders with observed events, paths, or promoted property keys.",
3022
+ "Choose a template and replace placeholders with observed events, paths, or queryable property keys.",
3023
3023
  "Validate with tender app analytics query <artifact-id> --spec chart.json --json.",
3024
3024
  "Preview saved writes with tender app analytics dashboards ... --dry-run and charts create ... --dry-run.",
3025
3025
  ],
@@ -3206,13 +3206,13 @@ function parseAnalyticsChartsDeleteArgs(args) {
3206
3206
  ...parsed,
3207
3207
  };
3208
3208
  }
3209
- function parseAnalyticsPropertySlotsListArgs(args) {
3209
+ function parseAnalyticsPropertiesListArgs(args) {
3210
3210
  if (args.includes("--help") || args.includes("-h")) {
3211
- return { command: "help", topic: "app analytics property-slots list" };
3211
+ return { command: "help", topic: "app analytics properties list" };
3212
3212
  }
3213
3213
  const artifactId = args[0];
3214
3214
  if (!artifactId || artifactId.startsWith("-")) {
3215
- throw new TenderCliUsageError("app id is required. Example: tender app analytics property-slots list <app-id> --json");
3215
+ throw new TenderCliUsageError("app id is required. Example: tender app analytics properties list <app-id> --json");
3216
3216
  }
3217
3217
  const parsed = parseAnalyticsCommonArgs(args, 1);
3218
3218
  let eventName = null;
@@ -3223,28 +3223,27 @@ function parseAnalyticsPropertySlotsListArgs(args) {
3223
3223
  index += 1;
3224
3224
  continue;
3225
3225
  }
3226
- throw new TenderCliUsageError(`Unknown analytics property-slots list option: ${arg}`);
3226
+ throw new TenderCliUsageError(`Unknown analytics properties list option: ${arg}`);
3227
3227
  }
3228
3228
  return {
3229
- command: "app analytics property-slots list",
3229
+ command: "app analytics properties list",
3230
3230
  artifactId,
3231
3231
  eventName,
3232
3232
  ...parsed,
3233
3233
  };
3234
3234
  }
3235
- function parseAnalyticsPropertySlotsActivateArgs(args) {
3235
+ function parseAnalyticsPropertiesActivateArgs(args) {
3236
3236
  if (args.includes("--help") || args.includes("-h")) {
3237
- return { command: "help", topic: "app analytics property-slots activate" };
3237
+ return { command: "help", topic: "app analytics properties activate" };
3238
3238
  }
3239
3239
  const artifactId = args[0];
3240
3240
  if (!artifactId || artifactId.startsWith("-")) {
3241
- throw new TenderCliUsageError("app id is required. Example: tender app analytics property-slots activate <app-id> --event <event-name> --property <property-key> --type dimension --json");
3241
+ throw new TenderCliUsageError("app id is required. Example: tender app analytics properties activate <app-id> --event <event-name> --property <property-key> --type dimension --json");
3242
3242
  }
3243
3243
  const parsed = parseAnalyticsCommonArgs(args, 1);
3244
3244
  let eventName = null;
3245
3245
  let propertyKey = null;
3246
- let slotType = null;
3247
- let slotName = null;
3246
+ let propertyType = null;
3248
3247
  let label = null;
3249
3248
  let dryRun = false;
3250
3249
  for (let index = 0; index < parsed.remaining.length; index += 1) {
@@ -3264,12 +3263,7 @@ function parseAnalyticsPropertySlotsActivateArgs(args) {
3264
3263
  if (value !== "dimension" && value !== "metric") {
3265
3264
  throw new TenderCliUsageError("--type must be dimension or metric.");
3266
3265
  }
3267
- slotType = value;
3268
- index += 1;
3269
- continue;
3270
- }
3271
- if (arg === "--slot") {
3272
- slotName = parseRequiredFlagValue(parsed.remaining[index + 1], "--slot");
3266
+ propertyType = value;
3273
3267
  index += 1;
3274
3268
  continue;
3275
3269
  }
@@ -3282,18 +3276,17 @@ function parseAnalyticsPropertySlotsActivateArgs(args) {
3282
3276
  dryRun = true;
3283
3277
  continue;
3284
3278
  }
3285
- throw new TenderCliUsageError(`Unknown analytics property-slots activate option: ${arg}`);
3279
+ throw new TenderCliUsageError(`Unknown analytics properties activate option: ${arg}`);
3286
3280
  }
3287
- if (!eventName || !propertyKey || !slotType) {
3288
- throw new TenderCliUsageError("--event, --property, and --type are required. Example: tender app analytics property-slots activate artifact_123 --event signup_started --property plan --type dimension --json");
3281
+ if (!eventName || !propertyKey || !propertyType) {
3282
+ throw new TenderCliUsageError("--event, --property, and --type are required. Example: tender app analytics properties activate artifact_123 --event signup_started --property plan --type dimension --json");
3289
3283
  }
3290
3284
  return {
3291
- command: "app analytics property-slots activate",
3285
+ command: "app analytics properties activate",
3292
3286
  artifactId,
3293
3287
  eventName,
3294
3288
  propertyKey,
3295
- slotType,
3296
- slotName,
3289
+ propertyType,
3297
3290
  label,
3298
3291
  dryRun,
3299
3292
  ...parsed,
@@ -3383,21 +3376,21 @@ function parseTenderArgs(args) {
3383
3376
  return parseAnalyticsDashboardsArgs(resourceArgs.slice(3));
3384
3377
  }
3385
3378
  if (resourceArgs[1] === "analytics" &&
3386
- resourceArgs[2] === "property-slots" &&
3379
+ resourceArgs[2] === "properties" &&
3387
3380
  (resourceArgs[3] === undefined ||
3388
3381
  resourceArgs[3] === "--help" ||
3389
3382
  resourceArgs[3] === "-h")) {
3390
- return { command: "help", topic: "app analytics property-slots list" };
3383
+ return { command: "help", topic: "app analytics properties list" };
3391
3384
  }
3392
3385
  if (resourceArgs[1] === "analytics" &&
3393
- resourceArgs[2] === "property-slots" &&
3386
+ resourceArgs[2] === "properties" &&
3394
3387
  resourceArgs[3] === "list") {
3395
- return parseAnalyticsPropertySlotsListArgs(resourceArgs.slice(4));
3388
+ return parseAnalyticsPropertiesListArgs(resourceArgs.slice(4));
3396
3389
  }
3397
3390
  if (resourceArgs[1] === "analytics" &&
3398
- resourceArgs[2] === "property-slots" &&
3391
+ resourceArgs[2] === "properties" &&
3399
3392
  resourceArgs[3] === "activate") {
3400
- return parseAnalyticsPropertySlotsActivateArgs(resourceArgs.slice(4));
3393
+ return parseAnalyticsPropertiesActivateArgs(resourceArgs.slice(4));
3401
3394
  }
3402
3395
  if (resourceArgs[1] === "analytics" &&
3403
3396
  resourceArgs[2] === "export" &&
@@ -3859,8 +3852,8 @@ function analyticsCorrectedExample(artifactId, analyticsPath) {
3859
3852
  if (analyticsPath === "suggestions") {
3860
3853
  return `tender app analytics suggestions ${artifactId} --range 30d --json`;
3861
3854
  }
3862
- if (analyticsPath === "property-slots") {
3863
- return `tender app analytics property-slots list ${artifactId} --json`;
3855
+ if (analyticsPath === "properties") {
3856
+ return `tender app analytics properties list ${artifactId} --json`;
3864
3857
  }
3865
3858
  if (analyticsPath === "dashboards") {
3866
3859
  return `tender app analytics dashboards ${artifactId} --json`;
@@ -3877,6 +3870,10 @@ function readCliStringField(record, field) {
3877
3870
  const value = record[field];
3878
3871
  return typeof value === "string" ? value : null;
3879
3872
  }
3873
+ function readCliBooleanField(record, field) {
3874
+ const value = record[field];
3875
+ return typeof value === "boolean" ? value : false;
3876
+ }
3880
3877
  function readAnalyticsDashboardRecords(payload) {
3881
3878
  return Array.isArray(payload.dashboards)
3882
3879
  ? payload.dashboards.filter(isCliJsonRecord)
@@ -3912,9 +3909,9 @@ function readAnalyticsChartSpec(chart) {
3912
3909
  function readAnalyticsChartLayout(chart) {
3913
3910
  return isCliJsonRecord(chart.layout) ? chart.layout : {};
3914
3911
  }
3915
- function readAnalyticsPropertySlotRecords(payload) {
3916
- return Array.isArray(payload.propertySlots)
3917
- ? payload.propertySlots.filter(isCliJsonRecord)
3912
+ function readAnalyticsPropertyRecords(payload) {
3913
+ return Array.isArray(payload.properties)
3914
+ ? payload.properties.filter(isCliJsonRecord)
3918
3915
  : [];
3919
3916
  }
3920
3917
  function readAnalyticsSpecEventNameFilter(spec) {
@@ -3940,34 +3937,34 @@ function readAnalyticsSpecGroupField(spec) {
3940
3937
  const [group] = spec.groupBy.filter(isCliJsonRecord);
3941
3938
  return group ? readCliStringField(group, "field") : null;
3942
3939
  }
3943
- function readRequiredAnalyticsPropertySlotsFromSpec(spec) {
3940
+ function readRequiredAnalyticsPropertiesFromSpec(spec) {
3944
3941
  const eventName = readAnalyticsSpecEventNameFilter(spec);
3945
3942
  const requirements = [];
3946
3943
  const groupField = readAnalyticsSpecGroupField(spec);
3947
3944
  if (groupField?.startsWith("property:")) {
3948
3945
  if (!eventName) {
3949
- throw new TenderCliUsageError("Property group-by chart specs require an event_name = filter so the CLI can activate the promoted property slot.");
3946
+ throw new TenderCliUsageError("Property group-by chart specs require an event_name = filter so the CLI can make the property available to dashboard queries.");
3950
3947
  }
3951
3948
  requirements.push({
3952
3949
  eventName,
3953
3950
  propertyKey: groupField.slice("property:".length),
3954
- slotType: "dimension",
3951
+ propertyType: "dimension",
3955
3952
  });
3956
3953
  }
3957
3954
  const metricName = readAnalyticsSpecMetricName(spec);
3958
3955
  if (metricName?.startsWith("sum:") || metricName?.startsWith("avg:")) {
3959
3956
  if (!eventName) {
3960
- throw new TenderCliUsageError("Property metric chart specs require an event_name = filter so the CLI can activate the promoted property slot.");
3957
+ throw new TenderCliUsageError("Property metric chart specs require an event_name = filter so the CLI can make the property available to dashboard queries.");
3961
3958
  }
3962
3959
  requirements.push({
3963
3960
  eventName,
3964
3961
  propertyKey: metricName.slice(metricName.indexOf(":") + 1),
3965
- slotType: "metric",
3962
+ propertyType: "metric",
3966
3963
  });
3967
3964
  }
3968
3965
  const seen = new Set();
3969
3966
  return requirements.filter((requirement) => {
3970
- const key = `${requirement.slotType}:${requirement.eventName}:${requirement.propertyKey}`;
3967
+ const key = `${requirement.propertyType}:${requirement.eventName}:${requirement.propertyKey}`;
3971
3968
  if (seen.has(key)) {
3972
3969
  return false;
3973
3970
  }
@@ -3975,107 +3972,22 @@ function readRequiredAnalyticsPropertySlotsFromSpec(spec) {
3975
3972
  return true;
3976
3973
  });
3977
3974
  }
3978
- function analyticsPropertySlotNames(slotType) {
3979
- return slotType === "dimension"
3980
- ? Array.from({ length: 13 }, (_, index) => `blob${index + 8}`)
3981
- : Array.from({ length: 19 }, (_, index) => `double${index + 2}`);
3982
- }
3983
- function isValidAnalyticsPropertySlotName(input) {
3984
- return analyticsPropertySlotNames(input.slotType).includes(input.slotName);
3985
- }
3986
- function findExistingAnalyticsPropertySlot(input) {
3987
- return (input.propertySlots.find((slot) => readCliStringField(slot, "status") === "active" &&
3988
- readCliStringField(slot, "eventName") === input.requirement.eventName &&
3989
- readCliStringField(slot, "propertyKey") === input.requirement.propertyKey &&
3990
- readCliStringField(slot, "slotType") === input.requirement.slotType) ?? null);
3991
- }
3992
- function chooseAnalyticsPropertySlotName(input) {
3993
- if (input.requestedSlotName) {
3994
- if (!isValidAnalyticsPropertySlotName({
3995
- slotType: input.requirement.slotType,
3996
- slotName: input.requestedSlotName,
3997
- })) {
3998
- throw new TenderCliUsageError(`--slot must be a valid ${input.requirement.slotType} analytics slot.`);
3999
- }
4000
- const conflictingSlot = input.propertySlots.find((slot) => readCliStringField(slot, "status") === "active" &&
4001
- readCliStringField(slot, "eventName") === input.requirement.eventName &&
4002
- readCliStringField(slot, "slotType") === input.requirement.slotType &&
4003
- readCliStringField(slot, "slotName") === input.requestedSlotName &&
4004
- readCliStringField(slot, "propertyKey") !== input.requirement.propertyKey);
4005
- if (conflictingSlot) {
4006
- throw new TenderCliUsageError(`--slot ${input.requestedSlotName} is already active for another ${input.requirement.slotType} property on ${input.requirement.eventName}.`);
4007
- }
4008
- return input.requestedSlotName;
4009
- }
4010
- const usedSlots = new Set(input.propertySlots
4011
- .filter((slot) => readCliStringField(slot, "status") === "active" &&
4012
- readCliStringField(slot, "eventName") === input.requirement.eventName &&
4013
- readCliStringField(slot, "slotType") === input.requirement.slotType)
4014
- .map((slot) => readCliStringField(slot, "slotName"))
4015
- .filter((slotName) => Boolean(slotName)));
4016
- const slotName = analyticsPropertySlotNames(input.requirement.slotType).find((candidate) => !usedSlots.has(candidate));
4017
- if (!slotName) {
4018
- throw new Error("analytics_property_slots_full");
4019
- }
4020
- return slotName;
4021
- }
4022
- async function fetchAnalyticsPropertySlots(input) {
4023
- const payload = await requestAnalyticsApi({
4024
- artifactId: input.command.artifactId,
4025
- analyticsPath: "property-slots",
4026
- method: "GET",
4027
- baseUrl: input.credentials.baseUrl,
4028
- token: input.credentials.token,
4029
- fetcher: input.runtime.fetcher ?? fetch,
4030
- });
4031
- return { payload, propertySlots: readAnalyticsPropertySlotRecords(payload) };
4032
- }
4033
- async function ensureAnalyticsPropertySlots(input) {
3975
+ async function ensureAnalyticsProperties(input) {
4034
3976
  if (input.requirements.length === 0) {
4035
3977
  return [];
4036
3978
  }
4037
- const { propertySlots } = await fetchAnalyticsPropertySlots({
4038
- command: input.command,
4039
- credentials: input.credentials,
4040
- runtime: input.runtime,
4041
- });
4042
3979
  const plan = [];
4043
3980
  for (const requirement of input.requirements) {
4044
- const existing = findExistingAnalyticsPropertySlot({
4045
- propertySlots,
4046
- requirement,
4047
- });
4048
- if (existing) {
4049
- plan.push({
4050
- ...requirement,
4051
- slotName: readCliStringField(existing, "slotName") ?? "",
4052
- label: readCliStringField(existing, "label") ?? requirement.propertyKey,
4053
- status: "existing",
4054
- propertySlot: existing,
4055
- });
4056
- continue;
4057
- }
4058
- const slotName = chooseAnalyticsPropertySlotName({
4059
- propertySlots,
4060
- requirement,
4061
- });
4062
3981
  const body = {
4063
3982
  eventName: requirement.eventName,
4064
3983
  propertyKey: requirement.propertyKey,
4065
- slotType: requirement.slotType,
4066
- slotName,
3984
+ propertyType: requirement.propertyType,
4067
3985
  label: requirement.propertyKey,
3986
+ dryRun: input.dryRun,
4068
3987
  };
4069
- if (input.dryRun) {
4070
- plan.push({
4071
- ...body,
4072
- status: "planned",
4073
- });
4074
- continue;
4075
- }
4076
3988
  const payload = await requestAnalyticsApi({
4077
3989
  artifactId: input.command.artifactId,
4078
- analyticsPath: "property-slots",
3990
+ analyticsPath: "properties",
4079
3991
  method: "POST",
4080
3992
  baseUrl: input.credentials.baseUrl,
4081
3993
  token: input.credentials.token,
@@ -4083,17 +3995,16 @@ async function ensureAnalyticsPropertySlots(input) {
4083
3995
  body,
4084
3996
  });
4085
3997
  plan.push({
4086
- ...body,
4087
- status: "activated",
4088
- propertySlot: payload.propertySlot,
4089
- });
4090
- propertySlots.push({
4091
- eventName: body.eventName,
4092
- propertyKey: body.propertyKey,
4093
- slotType: body.slotType,
4094
- slotName: body.slotName,
4095
- label: body.label,
4096
- status: "active",
3998
+ eventName: requirement.eventName,
3999
+ propertyKey: requirement.propertyKey,
4000
+ propertyType: requirement.propertyType,
4001
+ label: requirement.propertyKey,
4002
+ status: readCliBooleanField(payload, "alreadyActive")
4003
+ ? "existing"
4004
+ : input.dryRun
4005
+ ? "planned"
4006
+ : "activated",
4007
+ property: payload.property,
4097
4008
  });
4098
4009
  }
4099
4010
  return plan;
@@ -4108,12 +4019,12 @@ function analyticsCommandAuthFlags(command) {
4108
4019
  }
4109
4020
  return flags;
4110
4021
  }
4111
- function analyticsPropertySlotActivationCommand(input) {
4022
+ function analyticsPropertyActivationCommand(input) {
4112
4023
  return [
4113
4024
  "tender",
4114
4025
  "app",
4115
4026
  "analytics",
4116
- "property-slots",
4027
+ "properties",
4117
4028
  "activate",
4118
4029
  shellQuote(input.command.artifactId),
4119
4030
  "--event",
@@ -4121,16 +4032,16 @@ function analyticsPropertySlotActivationCommand(input) {
4121
4032
  "--property",
4122
4033
  shellQuote(input.requirement.propertyKey),
4123
4034
  "--type",
4124
- input.requirement.slotType,
4035
+ input.requirement.propertyType,
4125
4036
  ...(input.dryRun ? ["--dry-run"] : []),
4126
4037
  ...analyticsCommandAuthFlags(input.command),
4127
4038
  "--json",
4128
4039
  ].join(" ");
4129
4040
  }
4130
- function createAnalyticsPropertySlotGuidance(input) {
4041
+ function createAnalyticsPropertyGuidance(input) {
4131
4042
  let requirements;
4132
4043
  try {
4133
- requirements = readRequiredAnalyticsPropertySlotsFromSpec(input.spec);
4044
+ requirements = readRequiredAnalyticsPropertiesFromSpec(input.spec);
4134
4045
  }
4135
4046
  catch {
4136
4047
  return null;
@@ -4142,11 +4053,11 @@ function createAnalyticsPropertySlotGuidance(input) {
4142
4053
  "To make this chart available for dashboard queries, activate the custom event property first:",
4143
4054
  ];
4144
4055
  for (const requirement of requirements) {
4145
- lines.push(analyticsPropertySlotActivationCommand({
4056
+ lines.push(analyticsPropertyActivationCommand({
4146
4057
  command: input.command,
4147
4058
  requirement,
4148
4059
  dryRun: true,
4149
- }), analyticsPropertySlotActivationCommand({
4060
+ }), analyticsPropertyActivationCommand({
4150
4061
  command: input.command,
4151
4062
  requirement,
4152
4063
  dryRun: false,
@@ -4172,8 +4083,8 @@ async function requestAnalyticsQueryWithPropertyGuidance(input) {
4172
4083
  }
4173
4084
  catch (error) {
4174
4085
  if (error instanceof TenderCliAnalyticsApiError &&
4175
- error.reasonCode === "analytics_property_slot_not_found") {
4176
- const guidance = createAnalyticsPropertySlotGuidance({
4086
+ error.reasonCode === "analytics_property_not_queryable") {
4087
+ const guidance = createAnalyticsPropertyGuidance({
4177
4088
  command: input.command,
4178
4089
  spec: input.spec,
4179
4090
  });
@@ -6380,93 +6291,43 @@ async function runAnalyticsExportQuery(command, io, runtime) {
6380
6291
  io.stdout(JSON.stringify(payload, null, 2));
6381
6292
  return 0;
6382
6293
  }
6383
- async function runAnalyticsPropertySlotsList(command, io, runtime) {
6294
+ async function runAnalyticsPropertiesList(command, io, runtime) {
6384
6295
  const credentials = await resolveAnalyticsCredentials(command, runtime);
6385
6296
  const payload = await requestAnalyticsApi({
6386
6297
  artifactId: command.artifactId,
6387
- analyticsPath: "property-slots",
6298
+ analyticsPath: "properties",
6388
6299
  method: "GET",
6389
6300
  baseUrl: credentials.baseUrl,
6390
6301
  token: credentials.token,
6391
6302
  fetcher: runtime.fetcher ?? fetch,
6392
6303
  });
6393
- const propertySlots = readAnalyticsPropertySlotRecords(payload).filter((slot) => !command.eventName ||
6394
- readCliStringField(slot, "eventName") === command.eventName);
6304
+ const properties = readAnalyticsPropertyRecords(payload).filter((property) => !command.eventName ||
6305
+ readCliStringField(property, "eventName") === command.eventName);
6395
6306
  printAnalyticsPayload(command, io, {
6396
6307
  ok: true,
6397
6308
  command: command.command,
6398
6309
  artifactId: command.artifactId,
6399
6310
  eventName: command.eventName,
6400
- propertySlots,
6311
+ properties,
6401
6312
  }, [
6402
6313
  `app_id: ${command.artifactId}`,
6403
6314
  command.eventName ? `event: ${command.eventName}` : "event: all",
6404
- `property_slots: ${propertySlots.length}`,
6315
+ `properties: ${properties.length}`,
6405
6316
  ]);
6406
6317
  return 0;
6407
6318
  }
6408
- async function runAnalyticsPropertySlotsActivate(command, io, runtime) {
6319
+ async function runAnalyticsPropertiesActivate(command, io, runtime) {
6409
6320
  const credentials = await resolveAnalyticsCredentials(command, runtime);
6410
- const requirement = {
6411
- eventName: command.eventName,
6412
- propertyKey: command.propertyKey,
6413
- slotType: command.slotType,
6414
- };
6415
- const { propertySlots } = await fetchAnalyticsPropertySlots({
6416
- command,
6417
- credentials,
6418
- runtime,
6419
- });
6420
- const existing = findExistingAnalyticsPropertySlot({
6421
- propertySlots,
6422
- requirement,
6423
- });
6424
- if (existing) {
6425
- const payload = {
6426
- ok: true,
6427
- command: command.command,
6428
- artifactId: command.artifactId,
6429
- alreadyActive: true,
6430
- propertySlot: existing,
6431
- };
6432
- printAnalyticsPayload(command, io, payload, [
6433
- `app_id: ${command.artifactId}`,
6434
- "already_active: true",
6435
- `slot_name: ${readCliStringField(existing, "slotName") ?? ""}`,
6436
- ]);
6437
- return 0;
6438
- }
6439
- const slotName = chooseAnalyticsPropertySlotName({
6440
- propertySlots,
6441
- requirement,
6442
- requestedSlotName: command.slotName,
6443
- });
6444
6321
  const request = {
6445
6322
  eventName: command.eventName,
6446
6323
  propertyKey: command.propertyKey,
6447
- slotType: command.slotType,
6448
- slotName,
6324
+ propertyType: command.propertyType,
6449
6325
  label: command.label ?? command.propertyKey,
6326
+ dryRun: command.dryRun,
6450
6327
  };
6451
- if (command.dryRun) {
6452
- printAnalyticsPayload(command, io, {
6453
- ok: true,
6454
- command: command.command,
6455
- dryRun: true,
6456
- artifactId: command.artifactId,
6457
- request,
6458
- }, [
6459
- `app_id: ${command.artifactId}`,
6460
- `event: ${command.eventName}`,
6461
- `property: ${command.propertyKey}`,
6462
- `slot_name: ${slotName}`,
6463
- "dry_run: true",
6464
- ]);
6465
- return 0;
6466
- }
6467
6328
  const payload = await requestAnalyticsApi({
6468
6329
  artifactId: command.artifactId,
6469
- analyticsPath: "property-slots",
6330
+ analyticsPath: "properties",
6470
6331
  method: "POST",
6471
6332
  baseUrl: credentials.baseUrl,
6472
6333
  token: credentials.token,
@@ -6477,7 +6338,8 @@ async function runAnalyticsPropertySlotsActivate(command, io, runtime) {
6477
6338
  `app_id: ${command.artifactId}`,
6478
6339
  `event: ${command.eventName}`,
6479
6340
  `property: ${command.propertyKey}`,
6480
- `slot_name: ${slotName}`,
6341
+ `type: ${command.propertyType}`,
6342
+ ...(command.dryRun ? ["dry_run: true"] : []),
6481
6343
  ]);
6482
6344
  return 0;
6483
6345
  }
@@ -6492,16 +6354,16 @@ async function runAnalyticsChartsCreate(command, io, runtime) {
6492
6354
  spec,
6493
6355
  layout: {},
6494
6356
  };
6495
- const requiredPropertySlots = readRequiredAnalyticsPropertySlotsFromSpec(spec);
6496
- const credentials = !command.dryRun || requiredPropertySlots.length > 0
6357
+ const requiredProperties = readRequiredAnalyticsPropertiesFromSpec(spec);
6358
+ const credentials = !command.dryRun || requiredProperties.length > 0
6497
6359
  ? await resolveAnalyticsCredentials(command, runtime)
6498
6360
  : null;
6499
- const propertySlots = credentials
6500
- ? await ensureAnalyticsPropertySlots({
6361
+ const properties = credentials
6362
+ ? await ensureAnalyticsProperties({
6501
6363
  command,
6502
6364
  credentials,
6503
6365
  runtime,
6504
- requirements: requiredPropertySlots,
6366
+ requirements: requiredProperties,
6505
6367
  dryRun: command.dryRun,
6506
6368
  })
6507
6369
  : [];
@@ -6510,7 +6372,7 @@ async function runAnalyticsChartsCreate(command, io, runtime) {
6510
6372
  ok: true,
6511
6373
  dryRun: true,
6512
6374
  artifactId: command.artifactId,
6513
- propertySlots,
6375
+ properties,
6514
6376
  request: body,
6515
6377
  };
6516
6378
  printAnalyticsPayload(command, io, payload, [
@@ -6533,10 +6395,10 @@ async function runAnalyticsChartsCreate(command, io, runtime) {
6533
6395
  fetcher: runtime.fetcher ?? fetch,
6534
6396
  body,
6535
6397
  });
6536
- printAnalyticsPayload(command, io, { ...payload, propertySlots }, [
6398
+ printAnalyticsPayload(command, io, { ...payload, properties }, [
6537
6399
  `app_id: ${command.artifactId}`,
6538
6400
  `chart_id: ${String(payload.chart?.id ?? "")}`,
6539
- `property_slots: ${propertySlots.length}`,
6401
+ `properties: ${properties.length}`,
6540
6402
  ]);
6541
6403
  return 0;
6542
6404
  }
@@ -6583,11 +6445,11 @@ async function runAnalyticsChartsUpdate(command, io, runtime) {
6583
6445
  spec,
6584
6446
  layout: readAnalyticsChartLayout(existing.chart),
6585
6447
  };
6586
- const propertySlots = await ensureAnalyticsPropertySlots({
6448
+ const properties = await ensureAnalyticsProperties({
6587
6449
  command,
6588
6450
  credentials,
6589
6451
  runtime,
6590
- requirements: readRequiredAnalyticsPropertySlotsFromSpec(spec),
6452
+ requirements: readRequiredAnalyticsPropertiesFromSpec(spec),
6591
6453
  dryRun: command.dryRun,
6592
6454
  });
6593
6455
  const dashboardId = readCliStringField(existing.dashboard, "id");
@@ -6599,7 +6461,7 @@ async function runAnalyticsChartsUpdate(command, io, runtime) {
6599
6461
  chartId: command.chartId,
6600
6462
  dashboardId,
6601
6463
  currentChart: existing.chart,
6602
- propertySlots,
6464
+ properties,
6603
6465
  request: body,
6604
6466
  }, [
6605
6467
  `app_id: ${command.artifactId}`,
@@ -6619,11 +6481,11 @@ async function runAnalyticsChartsUpdate(command, io, runtime) {
6619
6481
  fetcher: runtime.fetcher ?? fetch,
6620
6482
  body,
6621
6483
  });
6622
- printAnalyticsPayload(command, io, { ...payload, propertySlots }, [
6484
+ printAnalyticsPayload(command, io, { ...payload, properties }, [
6623
6485
  `app_id: ${command.artifactId}`,
6624
6486
  `chart_id: ${command.chartId}`,
6625
6487
  `title: ${String(payload.chart?.title ?? title)}`,
6626
- `property_slots: ${propertySlots.length}`,
6488
+ `properties: ${properties.length}`,
6627
6489
  ]);
6628
6490
  return 0;
6629
6491
  }
@@ -6792,11 +6654,11 @@ export async function runTenderCli(args, io = {
6792
6654
  else if (command.topic === "app analytics charts delete") {
6793
6655
  io.stdout(analyticsChartsDeleteHelp());
6794
6656
  }
6795
- else if (command.topic === "app analytics property-slots list") {
6796
- io.stdout(analyticsPropertySlotsListHelp());
6657
+ else if (command.topic === "app analytics properties list") {
6658
+ io.stdout(analyticsPropertiesListHelp());
6797
6659
  }
6798
- else if (command.topic === "app analytics property-slots activate") {
6799
- io.stdout(analyticsPropertySlotsActivateHelp());
6660
+ else if (command.topic === "app analytics properties activate") {
6661
+ io.stdout(analyticsPropertiesActivateHelp());
6800
6662
  }
6801
6663
  else if (command.topic === "app") {
6802
6664
  io.stdout(appHelp());
@@ -6908,11 +6770,11 @@ export async function runTenderCli(args, io = {
6908
6770
  if (command.command === "app analytics charts delete") {
6909
6771
  return await runAnalyticsChartsDelete(command, io, runtime);
6910
6772
  }
6911
- if (command.command === "app analytics property-slots list") {
6912
- return await runAnalyticsPropertySlotsList(command, io, runtime);
6773
+ if (command.command === "app analytics properties list") {
6774
+ return await runAnalyticsPropertiesList(command, io, runtime);
6913
6775
  }
6914
- if (command.command === "app analytics property-slots activate") {
6915
- return await runAnalyticsPropertySlotsActivate(command, io, runtime);
6776
+ if (command.command === "app analytics properties activate") {
6777
+ return await runAnalyticsPropertiesActivate(command, io, runtime);
6916
6778
  }
6917
6779
  if (command.command === "app git remote") {
6918
6780
  return await runGitRemote(command, io, runtime);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenderprompt/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "tender": "bin/tender.js"