react-semaphor 0.1.335 → 0.1.337

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.
@@ -550,13 +550,15 @@ export declare type DashboardCardQueryFieldRef = {
550
550
  };
551
551
 
552
552
  export declare type DashboardCardQueryIntent = {
553
- metric?: string;
554
553
  metrics?: string[];
554
+ primaryMetric?: string;
555
+ metricRefs?: DashboardCardQueryFieldRef[];
555
556
  dateField?: string;
556
557
  dateFieldRef?: DashboardCardQueryFieldRef;
557
558
  timeGrain?: 'day' | 'week' | 'month' | 'quarter' | 'year';
558
559
  dimensions?: string[];
559
560
  dimensionRefs?: DashboardCardQueryFieldRef[];
561
+ filters?: SemaphorAnalyticsFilter[];
560
562
  limit?: number;
561
563
  };
562
564
 
@@ -1827,6 +1829,16 @@ declare type SelectedEntities = SelectedEntity[];
1827
1829
 
1828
1830
  declare type SelectedEntity = DatabaseEntityReference | DataModelEntityReference | DatasetEntityReference | FileEntityReference;
1829
1831
 
1832
+ declare type SemaphorAnalyticsFilter = {
1833
+ id?: string;
1834
+ field: SemaphorFieldRef;
1835
+ operator?: SemaphorAnalyticsFilterOperator;
1836
+ value?: unknown;
1837
+ values?: unknown[];
1838
+ };
1839
+
1840
+ declare type SemaphorAnalyticsFilterOperator = SemaphorInputOperator | 'not_contains' | 'is_null' | 'is_not_null';
1841
+
1830
1842
  declare type SemaphorAnalyticsIntent = SemaphorMetricIntent | SemaphorRecordsIntent | SemaphorInputOptionsIntent | SemaphorSqlIntent;
1831
1843
 
1832
1844
  declare type SemaphorDashboardIntent = {
@@ -1869,7 +1881,7 @@ declare type SemaphorInputBinding = {
1869
1881
  field?: SemaphorFieldRef;
1870
1882
  };
1871
1883
 
1872
- declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | '>' | '>=' | '<' | '<=';
1884
+ declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
1873
1885
 
1874
1886
  declare type SemaphorInputOptionsIntent = {
1875
1887
  kind: 'inputOptions';
@@ -1918,12 +1930,15 @@ declare type SemaphorMetricIntent = {
1918
1930
  version?: SemaphorProtocolVersion;
1919
1931
  id?: string;
1920
1932
  source: SemaphorSourceRef;
1921
- metric: string;
1922
- metrics?: string[];
1933
+ metrics: string[];
1934
+ primaryMetric?: string;
1935
+ metricRefs?: SemaphorFieldRef[];
1923
1936
  label?: string;
1924
1937
  dateField?: SemaphorFieldRef;
1925
1938
  timeGrain?: SemaphorTimeGrain;
1939
+ timeWindow?: SemaphorTimeWindow;
1926
1940
  dimensions?: SemaphorFieldRef[];
1941
+ filters?: SemaphorAnalyticsFilter[];
1927
1942
  comparison?: {
1928
1943
  kind: 'previous_period' | 'previous_year' | 'target';
1929
1944
  targetValue?: number;
@@ -1997,7 +2012,7 @@ declare type SemaphorSqlIntent = {
1997
2012
  declare type SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
1998
2013
 
1999
2014
  declare type SemaphorTimeWindow = {
2000
- unit: 'day' | 'month';
2015
+ unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
2001
2016
  value: number;
2002
2017
  anchor?: 'now' | 'latest_available';
2003
2018
  };
@@ -480,6 +480,16 @@ export declare type GeneratedRevision = {
480
480
 
481
481
  export declare type ReasoningEffort = 'low' | 'medium' | 'high';
482
482
 
483
+ declare type SemaphorAnalyticsFilter = {
484
+ id?: string;
485
+ field: SemaphorFieldRef;
486
+ operator?: SemaphorAnalyticsFilterOperator;
487
+ value?: unknown;
488
+ values?: unknown[];
489
+ };
490
+
491
+ declare type SemaphorAnalyticsFilterOperator = SemaphorInputOperator | 'not_contains' | 'is_null' | 'is_not_null';
492
+
483
493
  declare type SemaphorAnalyticsIntent = SemaphorMetricIntent | SemaphorRecordsIntent | SemaphorInputOptionsIntent | SemaphorSqlIntent;
484
494
 
485
495
  declare type SemaphorDialect = 'semantic' | 'postgres' | 'mysql' | 'mssql' | 'snowflake' | 'clickhouse' | 'bigquery' | 'redshift' | 'duckdb' | 'sqlite' | 'unknown';
@@ -497,7 +507,7 @@ declare type SemaphorInputBinding = {
497
507
  field?: SemaphorFieldRef;
498
508
  };
499
509
 
500
- declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | '>' | '>=' | '<' | '<=';
510
+ declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
501
511
 
502
512
  declare type SemaphorInputOptionsIntent = {
503
513
  kind: 'inputOptions';
@@ -522,12 +532,15 @@ declare type SemaphorMetricIntent = {
522
532
  version?: SemaphorProtocolVersion;
523
533
  id?: string;
524
534
  source: SemaphorSourceRef;
525
- metric: string;
526
- metrics?: string[];
535
+ metrics: string[];
536
+ primaryMetric?: string;
537
+ metricRefs?: SemaphorFieldRef[];
527
538
  label?: string;
528
539
  dateField?: SemaphorFieldRef;
529
540
  timeGrain?: SemaphorTimeGrain;
541
+ timeWindow?: SemaphorTimeWindow;
530
542
  dimensions?: SemaphorFieldRef[];
543
+ filters?: SemaphorAnalyticsFilter[];
531
544
  comparison?: {
532
545
  kind: 'previous_period' | 'previous_year' | 'target';
533
546
  targetValue?: number;
@@ -601,7 +614,7 @@ declare type SemaphorSqlIntent = {
601
614
  declare type SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
602
615
 
603
616
  declare type SemaphorTimeWindow = {
604
- unit: 'day' | 'month';
617
+ unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
605
618
  value: number;
606
619
  anchor?: 'now' | 'latest_available';
607
620
  };
@@ -16,6 +16,16 @@ export declare function normalizeSemaphorInputOptions(options?: Array<{
16
16
 
17
17
  export declare function readWindowRuntime(): SemaphorDataAppWindowRuntime | undefined;
18
18
 
19
+ declare type SemaphorAnalyticsFilter = {
20
+ id?: string;
21
+ field: SemaphorFieldRef;
22
+ operator?: SemaphorAnalyticsFilterOperator;
23
+ value?: unknown;
24
+ values?: unknown[];
25
+ };
26
+
27
+ declare type SemaphorAnalyticsFilterOperator = SemaphorInputOperator | 'not_contains' | 'is_null' | 'is_not_null';
28
+
19
29
  declare type SemaphorAnalyticsIntent = SemaphorMetricIntent | SemaphorRecordsIntent | SemaphorInputOptionsIntent | SemaphorSqlIntent;
20
30
 
21
31
  export declare const SemaphorDataAppContext: Context<SemaphorDataAppRuntime>;
@@ -139,8 +149,8 @@ export declare type SemaphorDataAppMetricResult = SemaphorDataAppQueryState & Se
139
149
  export declare type SemaphorDataAppMetricSpec = SemaphorDataAppSourceSpec & {
140
150
  id?: string;
141
151
  label?: string;
142
- metric: string;
143
- metrics?: string[];
152
+ metrics: SemaphorDataAppNonEmptyArray<string>;
153
+ primaryMetric?: string;
144
154
  dateField?: SemaphorDataAppFieldSpec;
145
155
  timeGrain?: SemaphorTimeGrain;
146
156
  dimensions?: SemaphorDataAppFieldSpec[];
@@ -261,7 +271,7 @@ declare type SemaphorInputBinding = {
261
271
  field?: SemaphorFieldRef;
262
272
  };
263
273
 
264
- declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | '>' | '>=' | '<' | '<=';
274
+ declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
265
275
 
266
276
  declare type SemaphorInputOptionsIntent = {
267
277
  kind: 'inputOptions';
@@ -286,12 +296,15 @@ declare type SemaphorMetricIntent = {
286
296
  version?: SemaphorProtocolVersion;
287
297
  id?: string;
288
298
  source: SemaphorSourceRef;
289
- metric: string;
290
- metrics?: string[];
299
+ metrics: string[];
300
+ primaryMetric?: string;
301
+ metricRefs?: SemaphorFieldRef[];
291
302
  label?: string;
292
303
  dateField?: SemaphorFieldRef;
293
304
  timeGrain?: SemaphorTimeGrain;
305
+ timeWindow?: SemaphorTimeWindow;
294
306
  dimensions?: SemaphorFieldRef[];
307
+ filters?: SemaphorAnalyticsFilter[];
295
308
  comparison?: {
296
309
  kind: 'previous_period' | 'previous_year' | 'target';
297
310
  targetValue?: number;
@@ -365,7 +378,7 @@ declare type SemaphorSqlIntent = {
365
378
  declare type SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
366
379
 
367
380
  declare type SemaphorTimeWindow = {
368
- unit: 'day' | 'month';
381
+ unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
369
382
  value: number;
370
383
  anchor?: 'now' | 'latest_available';
371
384
  };
@@ -1778,13 +1778,15 @@ declare type DashboardCardQueryFieldRef = {
1778
1778
  };
1779
1779
 
1780
1780
  declare type DashboardCardQueryIntent = {
1781
- metric?: string;
1782
1781
  metrics?: string[];
1782
+ primaryMetric?: string;
1783
+ metricRefs?: DashboardCardQueryFieldRef[];
1783
1784
  dateField?: string;
1784
1785
  dateFieldRef?: DashboardCardQueryFieldRef;
1785
1786
  timeGrain?: 'day' | 'week' | 'month' | 'quarter' | 'year';
1786
1787
  dimensions?: string[];
1787
1788
  dimensionRefs?: DashboardCardQueryFieldRef[];
1789
+ filters?: SemaphorAnalyticsFilter[];
1788
1790
  limit?: number;
1789
1791
  };
1790
1792
 
@@ -4415,6 +4417,16 @@ declare type SemanticExecutionPayload = {
4415
4417
  }>;
4416
4418
  };
4417
4419
 
4420
+ declare type SemaphorAnalyticsFilter = {
4421
+ id?: string;
4422
+ field: SemaphorFieldRef;
4423
+ operator?: SemaphorAnalyticsFilterOperator;
4424
+ value?: unknown;
4425
+ values?: unknown[];
4426
+ };
4427
+
4428
+ declare type SemaphorAnalyticsFilterOperator = SemaphorInputOperator | 'not_contains' | 'is_null' | 'is_not_null';
4429
+
4418
4430
  declare type SemaphorAnalyticsIntent = SemaphorMetricIntent | SemaphorRecordsIntent | SemaphorInputOptionsIntent | SemaphorSqlIntent;
4419
4431
 
4420
4432
  export declare const SemaphorContextProvider: ({ children, dashboardProps, }: {
@@ -4437,6 +4449,8 @@ declare type SemaphorInputBinding = {
4437
4449
  field?: SemaphorFieldRef;
4438
4450
  };
4439
4451
 
4452
+ declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
4453
+
4440
4454
  declare type SemaphorInputOptionsIntent = {
4441
4455
  kind: 'inputOptions';
4442
4456
  version?: SemaphorProtocolVersion;
@@ -4460,12 +4474,15 @@ declare type SemaphorMetricIntent = {
4460
4474
  version?: SemaphorProtocolVersion;
4461
4475
  id?: string;
4462
4476
  source: SemaphorSourceRef;
4463
- metric: string;
4464
- metrics?: string[];
4477
+ metrics: string[];
4478
+ primaryMetric?: string;
4479
+ metricRefs?: SemaphorFieldRef[];
4465
4480
  label?: string;
4466
4481
  dateField?: SemaphorFieldRef;
4467
4482
  timeGrain?: SemaphorTimeGrain;
4483
+ timeWindow?: SemaphorTimeWindow;
4468
4484
  dimensions?: SemaphorFieldRef[];
4485
+ filters?: SemaphorAnalyticsFilter[];
4469
4486
  comparison?: {
4470
4487
  kind: 'previous_period' | 'previous_year' | 'target';
4471
4488
  targetValue?: number;
@@ -4545,7 +4562,7 @@ declare type SemaphorSqlIntent = {
4545
4562
  declare type SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
4546
4563
 
4547
4564
  declare type SemaphorTimeWindow = {
4548
- unit: 'day' | 'month';
4565
+ unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
4549
4566
  value: number;
4550
4567
  anchor?: 'now' | 'latest_available';
4551
4568
  };
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "email": "support@semaphor.cloud"
6
6
  },
7
7
  "license": "MIT",
8
- "version": "0.1.335",
8
+ "version": "0.1.337",
9
9
  "description": "Fully interactive and customizable dashboards for your apps.",
10
10
  "keywords": [
11
11
  "react",
@@ -1,2 +0,0 @@
1
- "use strict";function s(e,i,n){return n?{code:e,message:i,path:n}:{code:e,message:i}}function y(e){const i=new Set;for(const n of e){if(i.has(n))return n;i.add(n)}return null}function a(e){return typeof e=="string"&&e.trim().length>0}function m(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function _(e,i,n,t={}){if(!e||typeof e!="object"){n.push(s("missing_source","Analytics intent needs a source.",i));return}if(e.kind==="semantic"){a(e.domainId)||n.push(s("missing_semantic_domain","Semantic source needs a domainId.",`${i}.domainId`)),a(e.datasetName)||n.push(s("missing_dataset_name","Semantic source needs a datasetName.",`${i}.datasetName`));return}if(e.kind==="physical"){a(e.connectionId)||n.push(s("missing_connection_id","Physical source needs a connectionId.",`${i}.connectionId`)),a(e.tableName)||n.push(s("missing_table_name","Physical source needs a tableName.",`${i}.tableName`));return}if(e.kind==="sql"){a(e.connectionId)||n.push(s("missing_connection_id","SQL source needs a connectionId.",`${i}.connectionId`)),t.requireSqlText!==!1&&!a(e.sql)&&n.push(s("missing_sql","SQL source needs SQL text.",`${i}.sql`));return}n.push(s("invalid_source_kind","Source kind is not supported.",i))}function f(e,i,n,t={}){if(!e||!m(e)){t.required&&n.push(s("missing_field_ref","Field reference needs a name.",i));return}a(e.name)||n.push(s("missing_field_ref","Field reference needs a name.",`${i}.name`)),e.source!==void 0&&_(e.source,`${i}.source`,n,{requireSqlText:!1})}function k(e,i){if(e.analysis===void 0)return;if(!m(e.analysis)){i.push(s("invalid_metric_analysis","Metric analysis must be a structured object.","analysis"));return}if(e.analysis.kind!=="period_change"){i.push(s("invalid_metric_analysis","Metric analysis kind is not supported.","analysis.kind"));return}e.dateField||i.push(s("missing_analysis_date_field","Period-change analysis needs a dateField.","dateField")),e.timeGrain||i.push(s("missing_analysis_time_grain","Period-change analysis needs a timeGrain.","timeGrain"));const{timeWindow:n}=e.analysis;if(n!==void 0){if(!m(n)){i.push(s("invalid_time_window","Analysis timeWindow must be a structured object.","analysis.timeWindow"));return}n.unit!=="day"&&n.unit!=="month"&&i.push(s("invalid_time_window","Analysis timeWindow unit must be day or month.","analysis.timeWindow.unit")),(typeof n.value!="number"||!Number.isFinite(n.value)||n.value<=0)&&i.push(s("invalid_time_window","Analysis timeWindow value must be a positive number.","analysis.timeWindow.value")),n.anchor!==void 0&&n.anchor!=="now"&&n.anchor!=="latest_available"&&i.push(s("invalid_time_window","Analysis timeWindow anchor must be now or latest_available.","analysis.timeWindow.anchor"))}}function h(e){var t,c,d,p;const i=[],n=[];return!e||typeof e!="object"?{ok:!1,errors:[s("invalid_analytics_intent","Analytics intent must be a structured object.")],warnings:n,repairHints:[{code:"invalid_analytics_intent",recommendedNextStep:"Send one structured analytics intent object with kind, source, and required fields."}]}:(e.version!==void 0&&e.version!==1&&i.push(s("invalid_version","Analytics intent version must be 1.","version")),_(e.source,"source",i,{requireSqlText:e.kind!=="sql"||!a(e.sql)}),e.kind==="metric"?(a(e.metric)||i.push(s("missing_metric","Metric intent needs a metric.","metric")),e.metrics!==void 0&&!Array.isArray(e.metrics)?i.push(s("invalid_metric_list","Metric intent metrics must be an array of metric names.","metrics")):Array.isArray(e.metrics)&&e.metrics.some(l=>!a(l))&&i.push(s("invalid_metric_list","Metric intent metrics must be an array of non-empty metric names.","metrics")),e.dimensions!==void 0&&!Array.isArray(e.dimensions)?i.push(s("invalid_metric_dimensions","Metric intent dimensions must be an array of field references.","dimensions")):Array.isArray(e.dimensions)&&e.dimensions.some(l=>!m(l)||!a(l.name))&&i.push(s("invalid_metric_dimensions","Metric intent dimensions must be an array of field references with names.","dimensions")),e.dateField!==void 0&&f(e.dateField,"dateField",i),Array.isArray(e.dimensions)&&e.dimensions.forEach((l,r)=>{f(l,`dimensions.${r}`,i)}),k(e,i)):e.kind==="records"?(!Array.isArray(e.fields)||e.fields.length===0?i.push(s("missing_record_fields","Records intent needs at least one field.","fields")):e.fields.some(l=>!m(l)||!a(l.name))&&i.push(s("invalid_record_fields","Records intent fields must be field references with names.","fields")),Array.isArray(e.fields)&&e.fields.forEach((l,r)=>{f(l,`fields.${r}`,i)}),e.dateField!==void 0&&f(e.dateField,"dateField",i)):e.kind==="inputOptions"?((!e.field||!a(e.field.name))&&i.push(s("missing_input_options_field","Input options intent needs a field.","field")),f(e.field,"field",i,{required:!0})):e.kind==="sql"?(((t=e.source)==null?void 0:t.kind)!=="sql"&&((c=e.source)==null?void 0:c.kind)!=="physical"&&i.push(s("invalid_sql_source","SQL analytics intent must use a SQL or physical source.","source")),a(e.sql)&&((d=e.source)==null?void 0:d.kind)==="sql"&&a(e.source.sql)&&v(e.sql)!==v(e.source.sql)&&i.push(s("conflicting_sql","SQL analytics intent cannot define different SQL text in source.sql and sql.","sql")),!a(e.sql)&&!(((p=e.source)==null?void 0:p.kind)==="sql"&&a(e.source.sql))&&i.push(s("missing_sql","SQL analytics intent needs SQL text.","sql")),Array.isArray(e.fields)&&e.fields.forEach((l,r)=>{f(l,`fields.${r}`,i)})):i.push(s("invalid_analytics_kind","Analytics kind is not supported.","kind")),{ok:i.length===0,errors:i,warnings:n,repairHints:q(i)})}function v(e){return e.replace(/\r\n/g,`
2
- `).trim()}function b(e){const i=[],n=[];if(!e||typeof e!="object")return{ok:!1,errors:[s("invalid_operation_intent","Operation intent must be a structured object.")],warnings:n,repairHints:[{code:"invalid_operation_intent",recommendedNextStep:"Send one typed operation intent with version, kind, and required operation fields."}]};if(e.version!==1&&i.push(s("invalid_version","Operation intent version must be 1.","version")),e.kind==="answer_obligations")!Array.isArray(e.obligations)||e.obligations.length===0?i.push(s("missing_obligations","Answer-obligations operation intent needs at least one obligation.","obligations")):e.obligations.forEach((t,c)=>{a(t.id)||i.push(s("missing_obligation_id","Each analytics obligation needs an id.",`obligations.${c}.id`)),a(t.prompt)||i.push(s("missing_obligation_prompt","Each analytics obligation needs a prompt.",`obligations.${c}.prompt`))});else if(e.kind==="dashboard_change"||e.kind==="data_app_change"){if(a(e.instruction)||i.push(s("missing_instruction","Change operation intent needs an instruction.","instruction")),e.analyticsIntent){const t=h(e.analyticsIntent);i.push(...t.errors),n.push(...t.warnings)}}else i.push(s("invalid_operation_kind","Operation intent kind is not supported.","kind"));return{ok:i.length===0,errors:i,warnings:n,repairHints:g(i)}}function S(e){const i=[],n=[];if(!e||typeof e!="object")return{ok:!1,errors:[s("invalid_recovery_plan","Analytics recovery plan must be a structured object.")],warnings:n,repairHints:[{code:"invalid_recovery_plan",recommendedNextStep:"Return a typed recovery plan with operationIntent and plannedToolCalls."}]};e.version!==1&&i.push(s("invalid_version","Recovery plan version must be 1.","version")),e.kind!=="analytics_recovery_plan"&&i.push(s("invalid_recovery_plan_kind","Recovery plan kind must be analytics_recovery_plan.","kind"));const t=b(e.operationIntent);return i.push(...t.errors),n.push(...t.warnings),Array.isArray(e.plannedToolCalls)||i.push(s("invalid_planned_tool_calls","Recovery plan plannedToolCalls must be an array.","plannedToolCalls")),{ok:i.length===0,errors:i,warnings:n,repairHints:g(i)}}function g(e){return e.map(i=>({code:i.code,recommendedNextStep:i.code==="missing_obligations"?"Normalize the user request into one or more typed analytics obligations before recovery planning.":"Correct the operation/recovery contract shape before planning execution."}))}function q(e){return e.map(i=>{switch(i.code){case"missing_source":return{code:i.code,fieldRole:"source",recommendedNextStep:"Provide a semantic, physical, or SQL source before executing analytics."};case"missing_metric":return{code:i.code,fieldRole:"metric",recommendedNextStep:"Choose one exact metric from the grounded schema candidates."};case"missing_record_fields":return{code:i.code,fieldRole:"dimension",recommendedNextStep:"Provide at least one field for the records intent."};case"missing_input_options_field":return{code:i.code,fieldRole:"input",recommendedNextStep:"Provide the exact field whose option values should be listed."};case"missing_sql":return{code:i.code,fieldRole:"sql",recommendedNextStep:"Provide bounded read-only SQL with an explicit outer LIMIT."};case"conflicting_sql":return{code:i.code,fieldRole:"sql",recommendedNextStep:"Use one canonical SQL text location for the intent; prefer top-level sql."};case"missing_semantic_domain":case"missing_dataset_name":case"missing_connection_id":case"missing_table_name":return{code:i.code,fieldRole:"source",recommendedNextStep:"Use grounded catalog metadata to fill the missing source reference."};default:return}}).filter(i=>!!i)}function x(e,i,n,t){if(!e||typeof e!="object"){n.push(s("invalid_view","Dashboard view must be an object.",i));return}if(a(e.title)||n.push(s("missing_view_title","Dashboard view needs a title.",i)),!e.presentation||typeof e.presentation!="object"){n.push(s("missing_presentation","Dashboard view needs a presentation.",`${i}.presentation`));return}if(e.presentation.kind==="text"){a(e.text)||t.push(s("missing_text_content","Text views should include text content.",`${i}.text`));return}if(!e.analytics){n.push(s("missing_view_analytics","Non-text dashboard views need analytics intent.",`${i}.analytics`));return}const c=h(e.analytics);for(const d of c.errors)n.push(s(d.code,d.message,`${i}.analytics${d.path?`.${d.path}`:""}`));for(const d of c.warnings)t.push(s(d.code,d.message,`${i}.analytics${d.path?`.${d.path}`:""}`))}function $(e){const i=[],n=[];if(!e||typeof e!="object")return{ok:!1,errors:[s("invalid_dashboard_intent","Dashboard intent must be a structured object.")],warnings:n};e.version!==1&&i.push(s("invalid_version","Dashboard intent version must be 1.")),e.kind!=="dashboard"&&i.push(s("invalid_kind","Experience intent kind must be dashboard.")),a(e.title)||i.push(s("missing_title","Dashboard intent needs a title.","title"));const t=Array.isArray(e.inputs)?e.inputs:[],c=y(t.filter(m).map(r=>r.id).filter(r=>typeof r=="string"));c&&i.push(s("duplicate_input_id",`Duplicate input id: ${c}.`,"inputs"));for(const[r,o]of t.entries()){const u=`inputs.${r}`;if(!m(o)){i.push(s("invalid_input","Dashboard input must be an object.",u));continue}a(o.id)||i.push(s("missing_input_id","Input needs an id.",`${u}.id`)),a(o.label)||i.push(s("missing_input_label","Input needs a label.",`${u}.label`)),!o.field||!a(o.field.name)?i.push(s("missing_input_field","Input needs a field.",`${u}.field`)):f(o.field,`${u}.field`,i),o.source&&_(o.source,`${u}.source`,i)}const d=Array.isArray(e.sections)?e.sections:[];d.length===0&&i.push(s("missing_sections","Dashboard intent needs at least one section.","sections"));const p=d.flatMap(r=>r&&typeof r=="object"&&Array.isArray(r.views)?r.views.filter(m).map(o=>o.id).filter(o=>!!o):[]),l=y(p);l&&i.push(s("duplicate_view_id",`Duplicate dashboard view id: ${l}.`,"sections"));for(const[r,o]of d.entries()){const u=`sections.${r}`;if(!o||typeof o!="object"){i.push(s("invalid_section","Dashboard section must be an object.",u));continue}if(a(o.title)||i.push(s("missing_section_title","Dashboard section needs a title.",u)),!Array.isArray(o.views)||o.views.length===0){i.push(s("missing_section_views","Dashboard section needs at least one view.",`${u}.views`));continue}for(const[w,A]of o.views.entries())x(A,`${u}.views.${w}`,i,n)}return{ok:i.length===0,errors:i,warnings:n}}exports.validateSemaphorAnalyticsIntent=h;exports.validateSemaphorAnalyticsRecoveryPlan=S;exports.validateSemaphorDashboardIntent=$;exports.validateSemaphorOperationIntent=b;