react-semaphor 0.1.325 → 0.1.326

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 (57) hide show
  1. package/dist/analytics-protocol/index.cjs +1 -1
  2. package/dist/analytics-protocol/index.js +260 -226
  3. package/dist/brand-studio/index.cjs +2 -2
  4. package/dist/brand-studio/index.js +7 -6
  5. package/dist/chunks/{braces-C7BeIXvM.js → braces-DVaMJoCd.js} +1 -1
  6. package/dist/chunks/{braces-ZjRH2Kl7.js → braces-dHeaioTd.js} +1 -1
  7. package/dist/chunks/{calendar-preferences-dialog-DHhT6Sja.js → calendar-preferences-dialog--2jD-eKu.js} +6 -5
  8. package/dist/chunks/calendar-preferences-dialog-mqU_uOmY.js +1 -0
  9. package/dist/chunks/{chevrons-up-down-CA-XvN1o.js → chevrons-up-down-CLbzBHoI.js} +1 -1
  10. package/dist/chunks/{chevrons-up-down-Cuilz9aY.js → chevrons-up-down-DNQE-uEp.js} +1 -1
  11. package/dist/chunks/{dashboard-briefing-launcher-DZiFMK8I.js → dashboard-briefing-launcher-DguNfFr8.js} +1 -1
  12. package/dist/chunks/{dashboard-briefing-launcher-BzIxRlzW.js → dashboard-briefing-launcher-DsjXUPFq.js} +29 -28
  13. package/dist/chunks/{dashboard-controls-DVwsWny9.js → dashboard-controls-DgNkM1yT.js} +10 -9
  14. package/dist/chunks/{dashboard-controls-BX693lE0.js → dashboard-controls-XCa9PZuU.js} +1 -1
  15. package/dist/chunks/dashboard-json-DiBd65Xf.js +1 -0
  16. package/dist/chunks/{dashboard-json-D15C_I9e.js → dashboard-json-DkA6Bf0Y.js} +7 -6
  17. package/dist/chunks/{edit-dashboard-visual-90_qEgRc.js → edit-dashboard-visual-BC9eOc4U.js} +2 -2
  18. package/dist/chunks/{edit-dashboard-visual-wQyJEcVH.js → edit-dashboard-visual-Q5hW5MXk.js} +11 -9
  19. package/dist/chunks/{index-YTk9Hab2.js → index-B1-46PoR.js} +213 -213
  20. package/dist/chunks/index-BxM99sFL.js +1 -0
  21. package/dist/chunks/index-CuHybtft.js +51 -0
  22. package/dist/chunks/{index-CffvIaZO.js → index-DwfDwtv2.js} +20578 -20474
  23. package/dist/chunks/{palette-CanPG11m.js → palette-DpcvHAiY.js} +1 -1
  24. package/dist/chunks/{palette-D96DOM7E.js → palette-DtmNws9a.js} +1 -1
  25. package/dist/chunks/{resource-management-panel-DlnrD0y-.js → resource-management-panel-CGwWKZOP.js} +1 -1
  26. package/dist/chunks/{resource-management-panel-CLoO2DL3.js → resource-management-panel-D2oAQkKi.js} +6 -5
  27. package/dist/chunks/{save-DxkSzUTZ.js → save-BY7WF62U.js} +1 -1
  28. package/dist/chunks/{save-CqrBQKG6.js → save-Cv_XRb94.js} +1 -1
  29. package/dist/chunks/{switch-BXICAlvS.js → switch-5aQ_jcLH.js} +39 -39
  30. package/dist/chunks/{switch-Deo2Ltmj.js → switch-j3AThLFk.js} +2580 -2628
  31. package/dist/chunks/{use-create-flow-overlay-state-DocFanjO.js → use-create-flow-overlay-state-BQPXP0AM.js} +1 -1
  32. package/dist/chunks/{use-create-flow-overlay-state-DsPoCfMu.js → use-create-flow-overlay-state-CP6GDQAX.js} +29 -28
  33. package/dist/chunks/{use-visual-utils-BdO22fQZ.js → use-visual-utils-CSXU-96k.js} +2 -2
  34. package/dist/chunks/{use-visual-utils-DSbXQQD1.js → use-visual-utils-NpOW5uZ1.js} +1 -1
  35. package/dist/chunks/validators-DJUMR5An.js +2 -0
  36. package/dist/chunks/validators-DvTxl9i0.js +352 -0
  37. package/dist/dashboard/index.cjs +1 -1
  38. package/dist/dashboard/index.js +1 -1
  39. package/dist/dashboard-authoring/index.cjs +3 -3
  40. package/dist/dashboard-authoring/index.js +168 -136
  41. package/dist/data-app-sdk/index.cjs +1 -0
  42. package/dist/data-app-sdk/index.js +512 -0
  43. package/dist/index.cjs +1 -1
  44. package/dist/index.js +141 -140
  45. package/dist/surfboard/index.cjs +1 -1
  46. package/dist/surfboard/index.js +2 -2
  47. package/dist/types/analytics-protocol.d.ts +325 -2
  48. package/dist/types/dashboard-authoring.d.ts +23 -1
  49. package/dist/types/dashboard.d.ts +6 -1
  50. package/dist/types/data-app-sdk.d.ts +378 -0
  51. package/dist/types/main.d.ts +117 -2
  52. package/dist/types/shared.d.ts +1 -0
  53. package/dist/types/surfboard.d.ts +6 -1
  54. package/dist/types/types.d.ts +6 -1
  55. package/package.json +6 -1
  56. package/dist/chunks/calendar-preferences-dialog-BxeROxyq.js +0 -1
  57. package/dist/chunks/dashboard-json-DxNEFM-p.js +0 -1
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function n(i,e,s){return s?{code:i,message:e,path:s}:{code:i,message:e}}function p(i){const e=new Set;for(const s of i){if(e.has(s))return s;e.add(s)}return null}function a(i){return typeof i=="string"&&i.trim().length>0}function l(i){return!!(i&&typeof i=="object"&&!Array.isArray(i))}function m(i,e,s){if(!i||typeof i!="object"){s.push(n("missing_source","Analytics intent needs a source.",e));return}if(i.kind==="semantic"){a(i.domainId)||s.push(n("missing_semantic_domain","Semantic source needs a domainId.",`${e}.domainId`)),a(i.datasetName)||s.push(n("missing_dataset_name","Semantic source needs a datasetName.",`${e}.datasetName`));return}if(i.kind==="physical"){a(i.connectionId)||s.push(n("missing_connection_id","Physical source needs a connectionId.",`${e}.connectionId`)),a(i.tableName)||s.push(n("missing_table_name","Physical source needs a tableName.",`${e}.tableName`));return}if(i.kind==="sql"){a(i.connectionId)||s.push(n("missing_connection_id","SQL source needs a connectionId.",`${e}.connectionId`)),a(i.sql)||s.push(n("missing_sql","SQL source needs SQL text.",`${e}.sql`));return}s.push(n("invalid_source_kind","Source kind is not supported.",e))}function h(i){var r;const e=[],s=[];return!i||typeof i!="object"?{ok:!1,errors:[n("invalid_analytics_intent","Analytics intent must be a structured object.")],warnings:s}:(m(i.source,"source",e),i.kind==="metric"?a(i.metric)||e.push(n("missing_metric","Metric intent needs a metric.","metric")):i.kind==="records"?(!Array.isArray(i.fields)||i.fields.length===0)&&e.push(n("missing_record_fields","Records intent needs at least one field.","fields")):i.kind==="inputOptions"?(!i.field||!a(i.field.name))&&e.push(n("missing_input_options_field","Input options intent needs a field.","field")):i.kind==="sql"?((r=i.source)==null?void 0:r.kind)!=="sql"&&e.push(n("invalid_sql_source","SQL analytics intent must use a SQL source.","source")):e.push(n("invalid_analytics_kind","Analytics kind is not supported.","kind")),{ok:e.length===0,errors:e,warnings:s})}function g(i,e,s,r){if(!i||typeof i!="object"){s.push(n("invalid_view","Dashboard view must be an object.",e));return}if(a(i.title)||s.push(n("missing_view_title","Dashboard view needs a title.",e)),!i.presentation||typeof i.presentation!="object"){s.push(n("missing_presentation","Dashboard view needs a presentation.",`${e}.presentation`));return}if(i.presentation.kind==="text"){a(i.text)||r.push(n("missing_text_content","Text views should include text content.",`${e}.text`));return}if(!i.analytics){s.push(n("missing_view_analytics","Non-text dashboard views need analytics intent.",`${e}.analytics`));return}const u=h(i.analytics);for(const o of u.errors)s.push(n(o.code,o.message,`${e}.analytics${o.path?`.${o.path}`:""}`));for(const o of u.warnings)r.push(n(o.code,o.message,`${e}.analytics${o.path?`.${o.path}`:""}`))}function v(i){const e=[],s=[];if(!i||typeof i!="object")return{ok:!1,errors:[n("invalid_dashboard_intent","Dashboard intent must be a structured object.")],warnings:s};i.version!==1&&e.push(n("invalid_version","Dashboard intent version must be 1.")),i.kind!=="dashboard"&&e.push(n("invalid_kind","Experience intent kind must be dashboard.")),a(i.title)||e.push(n("missing_title","Dashboard intent needs a title.","title"));const r=Array.isArray(i.inputs)?i.inputs:[],u=p(r.filter(l).map(d=>d.id).filter(d=>typeof d=="string"));u&&e.push(n("duplicate_input_id",`Duplicate input id: ${u}.`,"inputs"));for(const[d,t]of r.entries()){const c=`inputs.${d}`;if(!l(t)){e.push(n("invalid_input","Dashboard input must be an object.",c));continue}a(t.id)||e.push(n("missing_input_id","Input needs an id.",`${c}.id`)),a(t.label)||e.push(n("missing_input_label","Input needs a label.",`${c}.label`)),(!t.field||!a(t.field.name))&&e.push(n("missing_input_field","Input needs a field.",`${c}.field`)),t.source&&m(t.source,`${c}.source`,e)}const o=Array.isArray(i.sections)?i.sections:[];o.length===0&&e.push(n("missing_sections","Dashboard intent needs at least one section.","sections"));const _=o.flatMap(d=>d&&typeof d=="object"&&Array.isArray(d.views)?d.views.filter(l).map(t=>t.id).filter(t=>!!t):[]),f=p(_);f&&e.push(n("duplicate_view_id",`Duplicate dashboard view id: ${f}.`,"sections"));for(const[d,t]of o.entries()){const c=`sections.${d}`;if(!t||typeof t!="object"){e.push(n("invalid_section","Dashboard section must be an object.",c));continue}if(a(t.title)||e.push(n("missing_section_title","Dashboard section needs a title.",c)),!Array.isArray(t.views)||t.views.length===0){e.push(n("missing_section_views","Dashboard section needs at least one view.",`${c}.views`));continue}for(const[b,y]of t.views.entries())g(y,`${c}.views.${b}`,e,s)}return{ok:e.length===0,errors:e,warnings:s}}exports.validateSemaphorAnalyticsIntent=h;exports.validateSemaphorDashboardIntent=v;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("../chunks/validators-DJUMR5An.js");function o(e){return typeof e=="string"?e.trim().toLowerCase():""}function f(e){return String(e.column_name||e.name||e.qualifiedFieldName||"")}function v(e){return Array.from(new Set([e.column_name,e.name,e.qualifiedFieldName,e.alias].filter(i=>typeof i=="string"&&i.trim().length>0).map(i=>i.trim())))}function m(e){const i=o(e);return i?i.includes("int")||i.includes("numeric")||i.includes("decimal")||i.includes("double")||i.includes("float")||i.includes("number")||i.includes("real")||i.includes("money")?"number":i.includes("timestamp")||i.includes("datetime")||i==="time"||i.startsWith("time ")?"datetime":i.includes("date")?"date":i.includes("bool")?"boolean":"string":"unknown"}function A(e){const i=m(e);return i==="date"||i==="datetime"}function u(e){return A(e.dataType||e.data_type)}function p(e){const i=b(e);return i==="id"||i==="row_id"}function l(e){const i=b(e);return p(e)||i.endsWith("_id")||i.endsWith("_key")||i.endsWith("_number")}function b(e){return o(f(e)||e.name||e.alias).replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function g(e,i={}){const n=o(e.role);return n==="metric"||n==="measure"?!i.excludeIdentifiers||!l(e):n==="groupby"||n==="dimension"||n==="date"||n==="id"?!1:m(e.dataType||e.data_type)==="number"&&(!i.excludeIdentifiers||!l(e))}function T(e){return!g(e)&&!u(e)}function F(e){return[e.column_name,e.name,e.label,e.alias,e.qualifiedFieldName].filter(i=>typeof i=="string"&&i.trim().length>0).map(i=>o(i).replace(/[^a-z0-9]+/g," ")).join(" ")}function d(e,i){return i.some(n=>{const t=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|\\s)${t}(\\s|$)`,"i").test(e)})}function C(e){const i=F(e);if(i)return d(i,["pct","percent","percentage","rate","ratio","share","conversion","retention","churn","growth","margin rate","margin pct","margin percent","margin percentage"])?{type:"percent",minimumFractionDigits:0,maximumFractionDigits:1,percentValueMode:"fraction"}:d(i,["revenue","sales","profit","arr","mrr","gmv","amount","price","cost","spend","expense","budget","income","value","booking","bookings"])?{type:"currency",currency:"USD",minimumFractionDigits:0,maximumFractionDigits:1,compact:!0}:d(i,["count","quantity","orders","order","users","customers","tickets","units","sessions","visits","items","rows"])?{type:"number",minimumFractionDigits:0,maximumFractionDigits:0,compact:!0}:{type:"number",minimumFractionDigits:0,maximumFractionDigits:1,compact:!0}}function D(e){const i=new Set,n=new Set,t=new Set;for(const s of e){if(p(s))continue;const c=v(s);if(c.length!==0){if(u(s)){c.forEach(a=>n.add(a));continue}if(g(s,{excludeIdentifiers:!0})){c.forEach(a=>i.add(a));continue}c.forEach(a=>t.add(a))}}return{validMetricCandidates:Array.from(i).sort(),validDateCandidates:Array.from(n).sort(),validDimensionCandidates:Array.from(t).sort()}}const r={kind:"semantic",domainId:"domain_sales",datasetName:"orders",connectionId:"conn_sales",label:"Orders"},_={revenueKpi:{version:1,kind:"metric",id:"revenue-kpi",label:"Revenue",source:r,metric:"revenue",comparison:{kind:"previous_period"},limit:1},revenueTrend:{version:1,kind:"records",id:"revenue-trend",label:"Revenue trend",source:r,fields:[{name:"order_date",role:"date",dataType:"date",label:"Order Date"}],measures:["revenue"],dateField:{name:"order_date",role:"date",dataType:"date"},timeGrain:"month",limit:100},topCustomersRecords:{version:1,kind:"records",id:"top-customers",label:"Top customers",source:r,fields:[{name:"customer_name",role:"dimension",dataType:"string"},{name:"segment",role:"dimension",dataType:"string"},{name:"revenue",role:"measure",dataType:"number"}],measures:["revenue"],orderBy:{field:"revenue",direction:"desc"},limit:20},regionInputOptions:{version:1,kind:"inputOptions",id:"region-options",label:"Region options",source:r,field:{name:"region",role:"dimension",dataType:"string"},limit:100},previousPeriodRevenueComparison:{version:1,kind:"metric",id:"revenue-previous-period",label:"Revenue previous period comparison",source:r,metric:"revenue",dateField:{name:"order_date",role:"date",dataType:"date"},timeGrain:"week",comparison:{kind:"previous_period"},limit:100},boundedSqlRanking:{version:1,kind:"sql",id:"top-customer-ranking-sql",label:"Top customer ranking SQL",source:{kind:"physical",connectionId:"conn_sales",databaseName:"warehouse",schemaName:"public",tableName:"orders",dialect:"postgres"},sql:"SELECT customer_name, SUM(revenue) AS revenue FROM public.orders GROUP BY customer_name ORDER BY revenue DESC LIMIT 20",limit:20,rationale:"Ranking is SQL-natural because it requires ordering grouped aggregate rows.",fields:[{name:"customer_name",role:"dimension",dataType:"string"},{name:"revenue",role:"measure",dataType:"number"}]}};exports.validateSemaphorAnalyticsIntent=y.validateSemaphorAnalyticsIntent;exports.validateSemaphorDashboardIntent=y.validateSemaphorDashboardIntent;exports.SEMAPHOR_ANALYTICS_INTENT_FIXTURES=_;exports.buildAnalyticsCatalogFieldSummary=D;exports.getAnalyticsCatalogFieldCandidates=v;exports.getAnalyticsCatalogFieldName=f;exports.inferAnalyticsMetricFormat=C;exports.isAnalyticsCatalogDateField=u;exports.isAnalyticsCatalogDimensionField=T;exports.isAnalyticsCatalogMetricField=g;exports.isAnalyticsDateLikeDataType=A;exports.isAnalyticsMetricIdentifierField=l;exports.isAnalyticsTechnicalIdentifierField=p;exports.normalizeAnalyticsCatalogDataType=m;exports.normalizeAnalyticsCatalogName=o;
@@ -1,240 +1,274 @@
1
- function s(i, e, n) {
2
- return n ? { code: i, message: e, path: n } : { code: i, message: e };
1
+ import { v as C, a as S } from "../chunks/validators-DvTxl9i0.js";
2
+ function d(e) {
3
+ return typeof e == "string" ? e.trim().toLowerCase() : "";
3
4
  }
4
- function p(i) {
5
- const e = /* @__PURE__ */ new Set();
6
- for (const n of i) {
7
- if (e.has(n))
8
- return n;
9
- e.add(n);
10
- }
11
- return null;
5
+ function f(e) {
6
+ return String(e.column_name || e.name || e.qualifiedFieldName || "");
12
7
  }
13
- function a(i) {
14
- return typeof i == "string" && i.trim().length > 0;
8
+ function v(e) {
9
+ return Array.from(
10
+ new Set(
11
+ [
12
+ e.column_name,
13
+ e.name,
14
+ e.qualifiedFieldName,
15
+ e.alias
16
+ ].filter(
17
+ (n) => typeof n == "string" && n.trim().length > 0
18
+ ).map((n) => n.trim())
19
+ )
20
+ );
15
21
  }
16
- function l(i) {
17
- return !!(i && typeof i == "object" && !Array.isArray(i));
22
+ function m(e) {
23
+ const n = d(e);
24
+ return n ? n.includes("int") || n.includes("numeric") || n.includes("decimal") || n.includes("double") || n.includes("float") || n.includes("number") || n.includes("real") || n.includes("money") ? "number" : n.includes("timestamp") || n.includes("datetime") || n === "time" || n.startsWith("time ") ? "datetime" : n.includes("date") ? "date" : n.includes("bool") ? "boolean" : "string" : "unknown";
18
25
  }
19
- function m(i, e, n) {
20
- if (!i || typeof i != "object") {
21
- n.push(s("missing_source", "Analytics intent needs a source.", e));
22
- return;
23
- }
24
- if (i.kind === "semantic") {
25
- a(i.domainId) || n.push(
26
- s(
27
- "missing_semantic_domain",
28
- "Semantic source needs a domainId.",
29
- `${e}.domainId`
30
- )
31
- ), a(i.datasetName) || n.push(
32
- s(
33
- "missing_dataset_name",
34
- "Semantic source needs a datasetName.",
35
- `${e}.datasetName`
36
- )
37
- );
38
- return;
39
- }
40
- if (i.kind === "physical") {
41
- a(i.connectionId) || n.push(
42
- s(
43
- "missing_connection_id",
44
- "Physical source needs a connectionId.",
45
- `${e}.connectionId`
46
- )
47
- ), a(i.tableName) || n.push(
48
- s(
49
- "missing_table_name",
50
- "Physical source needs a tableName.",
51
- `${e}.tableName`
52
- )
53
- );
54
- return;
55
- }
56
- if (i.kind === "sql") {
57
- a(i.connectionId) || n.push(
58
- s(
59
- "missing_connection_id",
60
- "SQL source needs a connectionId.",
61
- `${e}.connectionId`
62
- )
63
- ), a(i.sql) || n.push(s("missing_sql", "SQL source needs SQL text.", `${e}.sql`));
64
- return;
65
- }
66
- n.push(s("invalid_source_kind", "Source kind is not supported.", e));
26
+ function b(e) {
27
+ const n = m(e);
28
+ return n === "date" || n === "datetime";
67
29
  }
68
- function y(i) {
69
- var r;
70
- const e = [], n = [];
71
- return !i || typeof i != "object" ? {
72
- ok: !1,
73
- errors: [
74
- s(
75
- "invalid_analytics_intent",
76
- "Analytics intent must be a structured object."
77
- )
78
- ],
79
- warnings: n
80
- } : (m(i.source, "source", e), i.kind === "metric" ? a(i.metric) || e.push(
81
- s("missing_metric", "Metric intent needs a metric.", "metric")
82
- ) : i.kind === "records" ? (!Array.isArray(i.fields) || i.fields.length === 0) && e.push(
83
- s(
84
- "missing_record_fields",
85
- "Records intent needs at least one field.",
86
- "fields"
87
- )
88
- ) : i.kind === "inputOptions" ? (!i.field || !a(i.field.name)) && e.push(
89
- s(
90
- "missing_input_options_field",
91
- "Input options intent needs a field.",
92
- "field"
93
- )
94
- ) : i.kind === "sql" ? ((r = i.source) == null ? void 0 : r.kind) !== "sql" && e.push(
95
- s(
96
- "invalid_sql_source",
97
- "SQL analytics intent must use a SQL source.",
98
- "source"
99
- )
100
- ) : e.push(
101
- s("invalid_analytics_kind", "Analytics kind is not supported.", "kind")
102
- ), { ok: e.length === 0, errors: e, warnings: n });
30
+ function l(e) {
31
+ return b(e.dataType || e.data_type);
103
32
  }
104
- function g(i, e, n, r) {
105
- if (!i || typeof i != "object") {
106
- n.push(s("invalid_view", "Dashboard view must be an object.", e));
107
- return;
108
- }
109
- if (a(i.title) || n.push(s("missing_view_title", "Dashboard view needs a title.", e)), !i.presentation || typeof i.presentation != "object") {
110
- n.push(
111
- s(
112
- "missing_presentation",
113
- "Dashboard view needs a presentation.",
114
- `${e}.presentation`
115
- )
116
- );
117
- return;
118
- }
119
- if (i.presentation.kind === "text") {
120
- a(i.text) || r.push(
121
- s(
122
- "missing_text_content",
123
- "Text views should include text content.",
124
- `${e}.text`
125
- )
126
- );
127
- return;
128
- }
129
- if (!i.analytics) {
130
- n.push(
131
- s(
132
- "missing_view_analytics",
133
- "Non-text dashboard views need analytics intent.",
134
- `${e}.analytics`
135
- )
136
- );
137
- return;
138
- }
139
- const u = y(i.analytics);
140
- for (const o of u.errors)
141
- n.push(
142
- s(o.code, o.message, `${e}.analytics${o.path ? `.${o.path}` : ""}`)
143
- );
144
- for (const o of u.warnings)
145
- r.push(
146
- s(
147
- o.code,
148
- o.message,
149
- `${e}.analytics${o.path ? `.${o.path}` : ""}`
150
- )
151
- );
33
+ function p(e) {
34
+ const n = g(e);
35
+ return n === "id" || n === "row_id";
36
+ }
37
+ function u(e) {
38
+ const n = g(e);
39
+ return p(e) || n.endsWith("_id") || n.endsWith("_key") || n.endsWith("_number");
40
+ }
41
+ function g(e) {
42
+ return d(
43
+ f(e) || e.name || e.alias
44
+ ).replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
45
+ }
46
+ function y(e, n = {}) {
47
+ const i = d(e.role);
48
+ return i === "metric" || i === "measure" ? !n.excludeIdentifiers || !u(e) : i === "groupby" || i === "dimension" || i === "date" || i === "id" ? !1 : m(
49
+ e.dataType || e.data_type
50
+ ) === "number" && (!n.excludeIdentifiers || !u(e));
51
+ }
52
+ function _(e) {
53
+ return !y(e) && !l(e);
152
54
  }
153
- function v(i) {
154
- const e = [], n = [];
155
- if (!i || typeof i != "object")
156
- return {
157
- ok: !1,
158
- errors: [
159
- s(
160
- "invalid_dashboard_intent",
161
- "Dashboard intent must be a structured object."
162
- )
163
- ],
164
- warnings: n
55
+ function T(e) {
56
+ return [
57
+ e.column_name,
58
+ e.name,
59
+ e.label,
60
+ e.alias,
61
+ e.qualifiedFieldName
62
+ ].filter(
63
+ (n) => typeof n == "string" && n.trim().length > 0
64
+ ).map(
65
+ (n) => d(n).replace(/[^a-z0-9]+/g, " ")
66
+ ).join(" ");
67
+ }
68
+ function c(e, n) {
69
+ return n.some((i) => {
70
+ const t = i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
71
+ return new RegExp(`(^|\\s)${t}(\\s|$)`, "i").test(e);
72
+ });
73
+ }
74
+ function F(e) {
75
+ const n = T(e);
76
+ if (n)
77
+ return c(n, [
78
+ "pct",
79
+ "percent",
80
+ "percentage",
81
+ "rate",
82
+ "ratio",
83
+ "share",
84
+ "conversion",
85
+ "retention",
86
+ "churn",
87
+ "growth",
88
+ "margin rate",
89
+ "margin pct",
90
+ "margin percent",
91
+ "margin percentage"
92
+ ]) ? {
93
+ type: "percent",
94
+ minimumFractionDigits: 0,
95
+ maximumFractionDigits: 1,
96
+ percentValueMode: "fraction"
97
+ } : c(n, [
98
+ "revenue",
99
+ "sales",
100
+ "profit",
101
+ "arr",
102
+ "mrr",
103
+ "gmv",
104
+ "amount",
105
+ "price",
106
+ "cost",
107
+ "spend",
108
+ "expense",
109
+ "budget",
110
+ "income",
111
+ "value",
112
+ "booking",
113
+ "bookings"
114
+ ]) ? {
115
+ type: "currency",
116
+ currency: "USD",
117
+ minimumFractionDigits: 0,
118
+ maximumFractionDigits: 1,
119
+ compact: !0
120
+ } : c(n, [
121
+ "count",
122
+ "quantity",
123
+ "orders",
124
+ "order",
125
+ "users",
126
+ "customers",
127
+ "tickets",
128
+ "units",
129
+ "sessions",
130
+ "visits",
131
+ "items",
132
+ "rows"
133
+ ]) ? {
134
+ type: "number",
135
+ minimumFractionDigits: 0,
136
+ maximumFractionDigits: 0,
137
+ compact: !0
138
+ } : {
139
+ type: "number",
140
+ minimumFractionDigits: 0,
141
+ maximumFractionDigits: 1,
142
+ compact: !0
165
143
  };
166
- i.version !== 1 && e.push(s("invalid_version", "Dashboard intent version must be 1.")), i.kind !== "dashboard" && e.push(s("invalid_kind", "Experience intent kind must be dashboard.")), a(i.title) || e.push(s("missing_title", "Dashboard intent needs a title.", "title"));
167
- const r = Array.isArray(i.inputs) ? i.inputs : [], u = p(
168
- r.filter(l).map((d) => d.id).filter((d) => typeof d == "string")
169
- );
170
- u && e.push(
171
- s(
172
- "duplicate_input_id",
173
- `Duplicate input id: ${u}.`,
174
- "inputs"
175
- )
176
- );
177
- for (const [d, t] of r.entries()) {
178
- const c = `inputs.${d}`;
179
- if (!l(t)) {
180
- e.push(s("invalid_input", "Dashboard input must be an object.", c));
181
- continue;
182
- }
183
- a(t.id) || e.push(s("missing_input_id", "Input needs an id.", `${c}.id`)), a(t.label) || e.push(
184
- s("missing_input_label", "Input needs a label.", `${c}.label`)
185
- ), (!t.field || !a(t.field.name)) && e.push(
186
- s("missing_input_field", "Input needs a field.", `${c}.field`)
187
- ), t.source && m(t.source, `${c}.source`, e);
188
- }
189
- const o = Array.isArray(i.sections) ? i.sections : [];
190
- o.length === 0 && e.push(
191
- s(
192
- "missing_sections",
193
- "Dashboard intent needs at least one section.",
194
- "sections"
195
- )
196
- );
197
- const h = o.flatMap(
198
- (d) => d && typeof d == "object" && Array.isArray(d.views) ? d.views.filter(l).map((t) => t.id).filter((t) => !!t) : []
199
- ), f = p(h);
200
- f && e.push(
201
- s(
202
- "duplicate_view_id",
203
- `Duplicate dashboard view id: ${f}.`,
204
- "sections"
205
- )
206
- );
207
- for (const [d, t] of o.entries()) {
208
- const c = `sections.${d}`;
209
- if (!t || typeof t != "object") {
210
- e.push(
211
- s("invalid_section", "Dashboard section must be an object.", c)
212
- );
213
- continue;
214
- }
215
- if (a(t.title) || e.push(
216
- s("missing_section_title", "Dashboard section needs a title.", c)
217
- ), !Array.isArray(t.views) || t.views.length === 0) {
218
- e.push(
219
- s(
220
- "missing_section_views",
221
- "Dashboard section needs at least one view.",
222
- `${c}.views`
223
- )
224
- );
144
+ }
145
+ function D(e) {
146
+ const n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set();
147
+ for (const o of e) {
148
+ if (p(o))
225
149
  continue;
150
+ const s = v(o);
151
+ if (s.length !== 0) {
152
+ if (l(o)) {
153
+ s.forEach((r) => i.add(r));
154
+ continue;
155
+ }
156
+ if (y(o, { excludeIdentifiers: !0 })) {
157
+ s.forEach((r) => n.add(r));
158
+ continue;
159
+ }
160
+ s.forEach((r) => t.add(r));
226
161
  }
227
- for (const [_, b] of t.views.entries())
228
- g(
229
- b,
230
- `${c}.views.${_}`,
231
- e,
232
- n
233
- );
234
162
  }
235
- return { ok: e.length === 0, errors: e, warnings: n };
163
+ return {
164
+ validMetricCandidates: Array.from(n).sort(),
165
+ validDateCandidates: Array.from(i).sort(),
166
+ validDimensionCandidates: Array.from(t).sort()
167
+ };
236
168
  }
169
+ const a = {
170
+ kind: "semantic",
171
+ domainId: "domain_sales",
172
+ datasetName: "orders",
173
+ connectionId: "conn_sales",
174
+ label: "Orders"
175
+ }, h = {
176
+ revenueKpi: {
177
+ version: 1,
178
+ kind: "metric",
179
+ id: "revenue-kpi",
180
+ label: "Revenue",
181
+ source: a,
182
+ metric: "revenue",
183
+ comparison: { kind: "previous_period" },
184
+ limit: 1
185
+ },
186
+ revenueTrend: {
187
+ version: 1,
188
+ kind: "records",
189
+ id: "revenue-trend",
190
+ label: "Revenue trend",
191
+ source: a,
192
+ fields: [
193
+ { name: "order_date", role: "date", dataType: "date", label: "Order Date" }
194
+ ],
195
+ measures: ["revenue"],
196
+ dateField: { name: "order_date", role: "date", dataType: "date" },
197
+ timeGrain: "month",
198
+ limit: 100
199
+ },
200
+ topCustomersRecords: {
201
+ version: 1,
202
+ kind: "records",
203
+ id: "top-customers",
204
+ label: "Top customers",
205
+ source: a,
206
+ fields: [
207
+ { name: "customer_name", role: "dimension", dataType: "string" },
208
+ { name: "segment", role: "dimension", dataType: "string" },
209
+ { name: "revenue", role: "measure", dataType: "number" }
210
+ ],
211
+ measures: ["revenue"],
212
+ orderBy: { field: "revenue", direction: "desc" },
213
+ limit: 20
214
+ },
215
+ regionInputOptions: {
216
+ version: 1,
217
+ kind: "inputOptions",
218
+ id: "region-options",
219
+ label: "Region options",
220
+ source: a,
221
+ field: { name: "region", role: "dimension", dataType: "string" },
222
+ limit: 100
223
+ },
224
+ previousPeriodRevenueComparison: {
225
+ version: 1,
226
+ kind: "metric",
227
+ id: "revenue-previous-period",
228
+ label: "Revenue previous period comparison",
229
+ source: a,
230
+ metric: "revenue",
231
+ dateField: { name: "order_date", role: "date", dataType: "date" },
232
+ timeGrain: "week",
233
+ comparison: { kind: "previous_period" },
234
+ limit: 100
235
+ },
236
+ boundedSqlRanking: {
237
+ version: 1,
238
+ kind: "sql",
239
+ id: "top-customer-ranking-sql",
240
+ label: "Top customer ranking SQL",
241
+ source: {
242
+ kind: "physical",
243
+ connectionId: "conn_sales",
244
+ databaseName: "warehouse",
245
+ schemaName: "public",
246
+ tableName: "orders",
247
+ dialect: "postgres"
248
+ },
249
+ sql: "SELECT customer_name, SUM(revenue) AS revenue FROM public.orders GROUP BY customer_name ORDER BY revenue DESC LIMIT 20",
250
+ limit: 20,
251
+ rationale: "Ranking is SQL-natural because it requires ordering grouped aggregate rows.",
252
+ fields: [
253
+ { name: "customer_name", role: "dimension", dataType: "string" },
254
+ { name: "revenue", role: "measure", dataType: "number" }
255
+ ]
256
+ }
257
+ };
237
258
  export {
238
- y as validateSemaphorAnalyticsIntent,
239
- v as validateSemaphorDashboardIntent
259
+ h as SEMAPHOR_ANALYTICS_INTENT_FIXTURES,
260
+ D as buildAnalyticsCatalogFieldSummary,
261
+ v as getAnalyticsCatalogFieldCandidates,
262
+ f as getAnalyticsCatalogFieldName,
263
+ F as inferAnalyticsMetricFormat,
264
+ l as isAnalyticsCatalogDateField,
265
+ _ as isAnalyticsCatalogDimensionField,
266
+ y as isAnalyticsCatalogMetricField,
267
+ b as isAnalyticsDateLikeDataType,
268
+ u as isAnalyticsMetricIdentifierField,
269
+ p as isAnalyticsTechnicalIdentifierField,
270
+ m as normalizeAnalyticsCatalogDataType,
271
+ d as normalizeAnalyticsCatalogName,
272
+ C as validateSemaphorAnalyticsIntent,
273
+ S as validateSemaphorDashboardIntent
240
274
  };