react-semaphor 0.1.380 → 0.1.382

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 (74) hide show
  1. package/DATA_APP_SDK.md +238 -0
  2. package/README.md +7 -0
  3. package/dist/analytics-protocol/index.cjs +1 -1
  4. package/dist/analytics-protocol/index.js +45 -41
  5. package/dist/brand-studio/index.cjs +1 -1
  6. package/dist/brand-studio/index.js +6 -6
  7. package/dist/chunks/analyze-result-contract-CtXfp3nv.js +1 -0
  8. package/dist/chunks/analyze-result-contract-DuhlklhI.js +102 -0
  9. package/dist/chunks/{braces-BT-ZyB-g.js → braces-CGi-YFZp.js} +1 -1
  10. package/dist/chunks/{braces-DOxxfERN.js → braces-CP8BEzl3.js} +1 -1
  11. package/dist/chunks/{calendar-preferences-dialog-Dsgs8WDv.js → calendar-preferences-dialog-CV4xF2Tp.js} +3 -3
  12. package/dist/chunks/{calendar-preferences-dialog-iZs8XqyH.js → calendar-preferences-dialog-rDDobeLo.js} +1 -1
  13. package/dist/chunks/catalog-field-grounding-Bnx-3tE0.js +1 -0
  14. package/dist/chunks/catalog-field-grounding-CJKAqtiC.js +100 -0
  15. package/dist/chunks/{dashboard-briefing-launcher-Coks66cV.js → dashboard-briefing-launcher-BT00MvGB.js} +5 -5
  16. package/dist/chunks/{dashboard-briefing-launcher-B5vPTl8P.js → dashboard-briefing-launcher-Dcbh-mjY.js} +1 -1
  17. package/dist/chunks/{dashboard-controls-BfkcnIdy.js → dashboard-controls-B6y7jkKO.js} +8 -8
  18. package/dist/chunks/{dashboard-controls-Dyqye6fh.js → dashboard-controls-CRqnPibB.js} +1 -1
  19. package/dist/chunks/{dashboard-json-DjXi4cI6.js → dashboard-json-CfIUG8k1.js} +3 -3
  20. package/dist/chunks/{dashboard-json-CV_LnO9x.js → dashboard-json-DEQqRR1x.js} +1 -1
  21. package/dist/chunks/{edit-dashboard-visual-DOW1Ap1N.js → edit-dashboard-visual-DMbf89xa.js} +5 -5
  22. package/dist/chunks/{edit-dashboard-visual-yinO0yU-.js → edit-dashboard-visual-wDOcHak3.js} +1 -1
  23. package/dist/chunks/{index-DlprYjr6.js → index-BAsWLkZ8.js} +169 -168
  24. package/dist/chunks/{index-CkoRCh3g.js → index-CrKxP9uF.js} +5 -5
  25. package/dist/chunks/{layout-grid-DTbOIOsE.js → layout-grid-BsKH3TgY.js} +1 -1
  26. package/dist/chunks/{layout-grid-DccceHv4.js → layout-grid-jJQUqDN9.js} +1 -1
  27. package/dist/chunks/operators-C8TxpM4C.js +48 -0
  28. package/dist/chunks/operators-DrTQsJXv.js +1 -0
  29. package/dist/chunks/{palette-SimHJELn.js → palette-9zLPGlj2.js} +1 -1
  30. package/dist/chunks/{palette-DCzLwqIw.js → palette-xU9Qt6bE.js} +1 -1
  31. package/dist/chunks/{save-D2O96E5A.js → save-8A_q6K4E.js} +1 -1
  32. package/dist/chunks/{save-zNVYH02T.js → save-DzciESDh.js} +1 -1
  33. package/dist/chunks/{source-identity-Dj3dryN9.js → source-identity-CN4xiyKJ.js} +5 -5
  34. package/dist/chunks/{switch-DMPsMpHW.js → switch-DArtNJZh.js} +292 -291
  35. package/dist/chunks/{switch-Jhyl63RF.js → switch-k7kj6NRg.js} +1 -1
  36. package/dist/chunks/{use-create-flow-overlay-state-r5JKyXU8.js → use-create-flow-overlay-state-BdG1DiSx.js} +4 -4
  37. package/dist/chunks/{use-create-flow-overlay-state-NsqFPwdB.js → use-create-flow-overlay-state-ipeaE65_.js} +1 -1
  38. package/dist/chunks/{validators-CtNmgsvG.js → validators-CHPH6ORs.js} +641 -498
  39. package/dist/chunks/validators-lWo8m0Q7.js +1 -0
  40. package/dist/dashboard/index.cjs +1 -1
  41. package/dist/dashboard/index.js +1 -1
  42. package/dist/dashboard-authoring/index.cjs +3 -3
  43. package/dist/dashboard-authoring/index.js +105 -92
  44. package/dist/data-app-builder/index.cjs +1 -1
  45. package/dist/data-app-builder/index.js +3 -3
  46. package/dist/data-app-sdk/index.cjs +1 -1
  47. package/dist/data-app-sdk/index.js +444 -380
  48. package/dist/data-app-sdk-adapters/index.cjs +1 -0
  49. package/dist/data-app-sdk-adapters/index.js +383 -0
  50. package/dist/data-app-sdk-validation/index.cjs +1 -1
  51. package/dist/data-app-sdk-validation/index.js +1073 -6
  52. package/dist/index.cjs +1 -1
  53. package/dist/index.js +7 -7
  54. package/dist/surfboard/index.cjs +1 -1
  55. package/dist/surfboard/index.js +2 -2
  56. package/dist/types/analytics-protocol.d.ts +58 -31
  57. package/dist/types/dashboard-assistant.d.ts +40 -15
  58. package/dist/types/dashboard-authoring.d.ts +36 -16
  59. package/dist/types/dashboard.d.ts +8 -8
  60. package/dist/types/data-app-builder.d.ts +35 -11
  61. package/dist/types/data-app-sdk-adapters.d.ts +733 -0
  62. package/dist/types/data-app-sdk-validation.d.ts +85 -25
  63. package/dist/types/data-app-sdk.d.ts +99 -155
  64. package/dist/types/main.d.ts +35 -11
  65. package/dist/types/shared.d.ts +8 -8
  66. package/dist/types/surfboard.d.ts +8 -8
  67. package/dist/types/types.d.ts +8 -8
  68. package/package.json +9 -2
  69. package/src/data-app-sdk/README.md +240 -0
  70. package/dist/chunks/catalog-field-grounding-8L9I0zdg.js +0 -1
  71. package/dist/chunks/catalog-field-grounding-BK4BX8sZ.js +0 -200
  72. package/dist/chunks/validation-BM3-ShHV.js +0 -1003
  73. package/dist/chunks/validation-BVpqRFar.js +0 -1
  74. package/dist/chunks/validators-jpoYhpHh.js +0 -1
@@ -2015,15 +2015,9 @@ declare type SemaphorDerivedFieldInput = {
2015
2015
  kind: 'field';
2016
2016
  field: SemaphorFieldRef;
2017
2017
  aggregate?: SemaphorAggregateFunction;
2018
- } | {
2019
- kind: 'metric';
2020
- metric: SemaphorFieldRef;
2021
- } | {
2022
- kind: 'dimension';
2023
- dimension: SemaphorFieldRef;
2024
2018
  };
2025
2019
 
2026
- declare type SemaphorDerivedFieldResultRole = 'measure' | 'group' | 'date' | 'id' | 'filter';
2020
+ declare type SemaphorDerivedFieldResultRole = 'measure' | 'dimension' | 'date' | 'id' | 'unknown';
2027
2021
 
2028
2022
  declare type SemaphorDialect = 'postgres' | 'mysql' | 'mssql' | 'snowflake' | 'clickhouse' | 'bigquery' | 'redshift' | 'duckdb' | 'sqlite' | 'unknown';
2029
2023
 
@@ -2047,9 +2041,10 @@ declare type SemaphorFieldRef = {
2047
2041
  declare type SemaphorInputBinding = {
2048
2042
  inputId: string;
2049
2043
  kind?: 'filter' | 'control';
2050
- controlRole?: 'grain' | 'metric' | 'dimension' | 'aggregation' | 'sqlParam';
2044
+ controlRole?: 'grain' | 'measure' | 'dimension' | 'aggregation' | 'sqlParam';
2051
2045
  operator?: SemaphorInputOperator;
2052
2046
  field?: SemaphorFieldRef;
2047
+ relationshipHint?: SemaphorRelationshipHint;
2053
2048
  };
2054
2049
 
2055
2050
  declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'not_contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
@@ -2112,6 +2107,7 @@ declare type SemaphorMatrixIntent = {
2112
2107
  values: SemaphorMatrixValueField[];
2113
2108
  filters?: SemaphorAnalyticsFilter[];
2114
2109
  inputs?: SemaphorInputBinding[];
2110
+ relationshipHint?: SemaphorRelationshipHint;
2115
2111
  totals?: SemaphorMatrixTotalOptions;
2116
2112
  sort?: SemaphorMatrixSortRule[];
2117
2113
  expansion?: SemaphorMatrixExpansionOptions;
@@ -2200,6 +2196,10 @@ declare type SemaphorMatrixValueField = {
2200
2196
 
2201
2197
  declare type SemaphorProtocolVersion = 1;
2202
2198
 
2199
+ declare type SemaphorRelationshipHint = {
2200
+ relationshipIds?: string[];
2201
+ };
2202
+
2203
2203
  declare type SemaphorSemanticSourceRef = Extract<SemaphorSourceRef, {
2204
2204
  kind: 'semantic';
2205
2205
  }>;
@@ -3010,15 +3010,9 @@ declare type SemaphorDerivedFieldInput = {
3010
3010
  kind: 'field';
3011
3011
  field: SemaphorFieldRef;
3012
3012
  aggregate?: SemaphorAggregateFunction;
3013
- } | {
3014
- kind: 'metric';
3015
- metric: SemaphorFieldRef;
3016
- } | {
3017
- kind: 'dimension';
3018
- dimension: SemaphorFieldRef;
3019
3013
  };
3020
3014
 
3021
- declare type SemaphorDerivedFieldResultRole = 'measure' | 'group' | 'date' | 'id' | 'filter';
3015
+ declare type SemaphorDerivedFieldResultRole = 'measure' | 'dimension' | 'date' | 'id' | 'unknown';
3022
3016
 
3023
3017
  declare type SemaphorDialect = 'postgres' | 'mysql' | 'mssql' | 'snowflake' | 'clickhouse' | 'bigquery' | 'redshift' | 'duckdb' | 'sqlite' | 'unknown';
3024
3018
 
@@ -3042,9 +3036,10 @@ declare type SemaphorFieldRef = {
3042
3036
  declare type SemaphorInputBinding = {
3043
3037
  inputId: string;
3044
3038
  kind?: 'filter' | 'control';
3045
- controlRole?: 'grain' | 'metric' | 'dimension' | 'aggregation' | 'sqlParam';
3039
+ controlRole?: 'grain' | 'measure' | 'dimension' | 'aggregation' | 'sqlParam';
3046
3040
  operator?: SemaphorInputOperator;
3047
3041
  field?: SemaphorFieldRef;
3042
+ relationshipHint?: SemaphorRelationshipHint;
3048
3043
  };
3049
3044
 
3050
3045
  declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'not_contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';
@@ -3107,6 +3102,7 @@ declare type SemaphorMatrixIntent = {
3107
3102
  values: SemaphorMatrixValueField[];
3108
3103
  filters?: SemaphorAnalyticsFilter[];
3109
3104
  inputs?: SemaphorInputBinding[];
3105
+ relationshipHint?: SemaphorRelationshipHint;
3110
3106
  totals?: SemaphorMatrixTotalOptions;
3111
3107
  sort?: SemaphorMatrixSortRule[];
3112
3108
  expansion?: SemaphorMatrixExpansionOptions;
@@ -3230,6 +3226,10 @@ declare type SemaphorProtocolVersion = 1;
3230
3226
 
3231
3227
  declare type SemaphorQueryPath = 'query_spec' | 'sql' | 'sql_python';
3232
3228
 
3229
+ declare type SemaphorRelationshipHint = {
3230
+ relationshipIds?: string[];
3231
+ };
3232
+
3233
3233
  declare type SemaphorSemanticSourceRef = Extract<SemaphorSourceRef, {
3234
3234
  kind: 'semantic';
3235
3235
  }>;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "email": "support@semaphor.cloud"
6
6
  },
7
7
  "license": "MIT",
8
- "version": "0.1.380",
8
+ "version": "0.1.382",
9
9
  "description": "Fully interactive and customizable dashboards for your apps.",
10
10
  "keywords": [
11
11
  "react",
@@ -16,7 +16,9 @@
16
16
  "type": "module",
17
17
  "files": [
18
18
  "dist",
19
- "CHANGELOG.md"
19
+ "CHANGELOG.md",
20
+ "DATA_APP_SDK.md",
21
+ "src/data-app-sdk/README.md"
20
22
  ],
21
23
  "main": "dist/index.cjs",
22
24
  "module": "dist/index.js",
@@ -72,6 +74,11 @@
72
74
  "import": "./dist/data-app-sdk/index.js",
73
75
  "require": "./dist/data-app-sdk/index.cjs"
74
76
  },
77
+ "./data-app-sdk/adapters": {
78
+ "types": "./dist/types/data-app-sdk-adapters.d.ts",
79
+ "import": "./dist/data-app-sdk-adapters/index.js",
80
+ "require": "./dist/data-app-sdk-adapters/index.cjs"
81
+ },
75
82
  "./data-app-sdk/validation": {
76
83
  "types": "./dist/types/data-app-sdk-validation.d.ts",
77
84
  "import": "./dist/data-app-sdk-validation/index.js",
@@ -0,0 +1,240 @@
1
+ # Data App SDK Quick Reference
2
+
3
+ Use this file as the public contract quick reference for generated Semaphor
4
+ Data Apps. Do not inspect SDK implementation internals to discover these
5
+ patterns.
6
+
7
+ ## Imports
8
+
9
+ ```tsx
10
+ import {
11
+ SemaphorDataAppProvider,
12
+ semaphor,
13
+ useClearInvalidSemaphorInputValue,
14
+ useSemaphorInputs,
15
+ useSemaphorQuery,
16
+ } from "react-semaphor/data-app-sdk";
17
+
18
+ import type {
19
+ SemaphorQueryResult,
20
+ SemaphorRecordsField,
21
+ SemaphorRecordsQueryResult,
22
+ SemaphorSourceRef,
23
+ } from "react-semaphor/data-app-sdk";
24
+ ```
25
+
26
+ ## Source And Fields
27
+
28
+ ```tsx
29
+ const source = {
30
+ kind: "semantic",
31
+ domainId: "sales",
32
+ datasetName: "orders",
33
+ } satisfies SemaphorSourceRef;
34
+
35
+ const revenue = {
36
+ name: "revenue",
37
+ label: "Revenue",
38
+ role: "measure",
39
+ dataType: "number",
40
+ aggregate: "SUM",
41
+ source,
42
+ } satisfies SemaphorRecordsField;
43
+
44
+ const segment = {
45
+ name: "segment",
46
+ label: "Segment",
47
+ role: "dimension",
48
+ dataType: "string",
49
+ source,
50
+ } satisfies SemaphorRecordsField;
51
+ ```
52
+
53
+ Use `SemaphorRecordsField` for `semaphor.records(...)` fields so every selected
54
+ field has a concrete role.
55
+
56
+ ## Metric
57
+
58
+ ```tsx
59
+ const revenueKpi = semaphor.metric({
60
+ id: "revenue-kpi",
61
+ source,
62
+ measures: [revenue],
63
+ primaryMeasure: revenue,
64
+ });
65
+
66
+ const result = useSemaphorQuery(revenueKpi);
67
+ ```
68
+
69
+ ## Records
70
+
71
+ ```tsx
72
+ const revenueBySegment = semaphor.records({
73
+ id: "revenue-by-segment",
74
+ source,
75
+ fields: [segment, revenue],
76
+ orderBy: { field: revenue, direction: "desc" },
77
+ limit: 10,
78
+ });
79
+
80
+ const result = useSemaphorQuery(revenueBySegment);
81
+ ```
82
+
83
+ ## Row Access
84
+
85
+ Read rows with `columns[].key`; display `columns[].label`.
86
+
87
+ ```tsx
88
+ function RecordsTable({ result }: { result: SemaphorRecordsQueryResult }) {
89
+ const records = result.records ?? [];
90
+ const columns = result.columns ?? [];
91
+
92
+ return (
93
+ <table>
94
+ <thead>
95
+ <tr>
96
+ {columns.map((column) => (
97
+ <th key={column.key}>{column.label || column.name}</th>
98
+ ))}
99
+ </tr>
100
+ </thead>
101
+ <tbody>
102
+ {records.map((row, rowIndex) => (
103
+ <tr key={rowIndex}>
104
+ {columns.map((column) => (
105
+ <td key={column.key}>{String(row[column.key] ?? "")}</td>
106
+ ))}
107
+ </tr>
108
+ ))}
109
+ </tbody>
110
+ </table>
111
+ );
112
+ }
113
+ ```
114
+
115
+ When accepting a generic `SemaphorQueryResult`, narrow before reading records:
116
+
117
+ ```tsx
118
+ function queryRecords(result: SemaphorQueryResult) {
119
+ return "records" in result && Array.isArray(result.records)
120
+ ? result.records
121
+ : [];
122
+ }
123
+ ```
124
+
125
+ ## Input Options
126
+
127
+ ```tsx
128
+ const segmentFilter = semaphor.filter({
129
+ id: "segment",
130
+ label: "Segment",
131
+ field: segment,
132
+ operator: "in",
133
+ });
134
+
135
+ const segmentOptions = semaphor.inputOptions({
136
+ id: "segment-options",
137
+ inputId: "segment",
138
+ source,
139
+ labelField: segment,
140
+ valueField: segment,
141
+ dependencies: { mode: "auto" },
142
+ limit: 100,
143
+ });
144
+
145
+ function SegmentFilter() {
146
+ const [segmentHandle] = useSemaphorInputs([segmentFilter]);
147
+ const optionsResult = useSemaphorQuery(segmentOptions, {
148
+ inputs: [segmentHandle],
149
+ });
150
+
151
+ useClearInvalidSemaphorInputValue(segmentHandle, optionsResult);
152
+ }
153
+ ```
154
+
155
+ Pass the full `optionsResult` to `useClearInvalidSemaphorInputValue`; do not
156
+ pass only `optionsResult.options`, because idle/loading results can also expose
157
+ an empty options array.
158
+
159
+ ## Shared Inputs With Source-Specific Bindings
160
+
161
+ Use `semaphor.bindInput(...)` when one visible input maps to different query
162
+ fields.
163
+
164
+ ```tsx
165
+ const dateRange = semaphor.filter({
166
+ id: "date_range",
167
+ label: "Date Range",
168
+ field: orderDate,
169
+ operator: "between",
170
+ });
171
+
172
+ function Dashboard() {
173
+ const [dateRangeHandle] = useSemaphorInputs([dateRange]);
174
+
175
+ const orders = useSemaphorQuery(ordersQuery, {
176
+ inputs: [semaphor.bindInput(dateRangeHandle, { field: orderDate })],
177
+ });
178
+ const invoices = useSemaphorQuery(invoicesQuery, {
179
+ inputs: [semaphor.bindInput(dateRangeHandle, { field: invoiceDate })],
180
+ });
181
+
182
+ const range = Array.isArray(dateRangeHandle.value)
183
+ ? dateRangeHandle.value
184
+ : [];
185
+ const [start, end] = range;
186
+ }
187
+ ```
188
+
189
+ Narrow `handle.value` with `Array.isArray(...)` before indexing date ranges or
190
+ multi-select values.
191
+
192
+ ## Related Dimension Filters
193
+
194
+ Use a related human-readable dimension as the visible filter and preserve the
195
+ relationship hint when binding that input into each fact query.
196
+
197
+ ```tsx
198
+ const materialFamilyFilter = semaphor.filter<string[]>({
199
+ id: "material_family",
200
+ label: "Material Family",
201
+ field: materialFamily,
202
+ operator: "in",
203
+ multi: true,
204
+ });
205
+
206
+ const materialOptions = semaphor.inputOptions({
207
+ id: "material-family-options",
208
+ inputId: "material_family",
209
+ source: materialSource,
210
+ labelField: materialFamily,
211
+ valueField: materialFamily,
212
+ limit: 100,
213
+ });
214
+
215
+ function OpsViews() {
216
+ const materialHandle = useSemaphorInput(materialFamilyFilter);
217
+ useSemaphorQuery(materialOptions);
218
+
219
+ useSemaphorQuery(purchaseQuery, {
220
+ inputs: [
221
+ semaphor.bindInput(materialHandle, {
222
+ field: materialFamily,
223
+ relationshipHint: { relationshipIds: ["purchase_material"] },
224
+ }),
225
+ ],
226
+ });
227
+
228
+ useSemaphorQuery(salesQuery, {
229
+ inputs: [
230
+ semaphor.bindInput(materialHandle, {
231
+ field: materialFamily,
232
+ relationshipHint: { relationshipIds: ["sales_material"] },
233
+ }),
234
+ ],
235
+ });
236
+ }
237
+ ```
238
+
239
+ Do not fetch broad rows and filter or join them in React to simulate
240
+ related-dimension behavior. Let Semaphor execute the relationship-aware filter.
@@ -1 +0,0 @@
1
- "use strict";const o={answerSummary:"string",responseDetail:"responseDetail",mode:"string",comparisonType:"string",executionResult:"unknown",compiledQuery:"unknown",data:"unknown",resultSets:"record",columns:"unknownArray",records:"recordArray",rowCount:"number",rowLimitExceeded:"boolean",output:"string",querySpec:"unknown",metadata:"record",validation:"unknown",coverage:"unknown",diagnosticFeedback:"unknown",missingFields:"stringArray",warnings:"unknownArray",comparison:"unknown",population:"unknown",comparisons:"recordArray",fieldsUsed:"unknown",changes:"recordArray",largestNegativeChanges:"recordArray",largestPositiveChanges:"recordArray",drivers:"recordArray",absoluteDeltaDrivers:"recordArray",largestNegativeDrivers:"recordArray",largestPositiveDrivers:"recordArray",periodRows:"recordArray",sql:"unknown",omitted:"stringArray"},b=new Set(Object.keys(o)),S=new Set(["compact","standard","debug"]);function D(){return Object.keys(o)}function g(e){return b.has(e)}function F(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Semaphor analyze result must be an object.");const n=e,t=Object.keys(n).filter(r=>!g(r));if(t.length)throw new Error(`Semaphor analyze result contains unsupported top-level field(s): ${t.join(", ")}.`);for(const[r,i]of Object.entries(n)){if(i===void 0)continue;const a=o[r];if(!k(i,a))throw new Error(`Semaphor analyze result field "${r}" does not match contract kind "${a}".`)}return n}function k(e,n){switch(n){case"boolean":return typeof e=="boolean";case"number":return typeof e=="number"&&Number.isFinite(e);case"record":return A(e);case"recordArray":return Array.isArray(e)&&e.every(A);case"responseDetail":return typeof e=="string"&&S.has(e);case"string":return typeof e=="string";case"stringArray":return Array.isArray(e)&&e.every(t=>typeof t=="string");case"unknown":return!0;case"unknownArray":return Array.isArray(e)}}function A(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function c(e){return typeof e=="string"?e.trim().toLowerCase():""}function p(e){return String(e.column_name||e.name||e.qualifiedFieldName||"")}function w(e){return Array.from(new Set([e.column_name,e.name,e.qualifiedFieldName,e.alias].filter(n=>typeof n=="string"&&n.trim().length>0).map(n=>n.trim())))}function d(e){const n=T(e);return n?n.includes("int")||n.includes("uint")||n.includes("bigint")||n.includes("smallint")||n.includes("tinyint")||n.includes("numeric")||n.includes("decimal")||n.includes("double")||n.includes("float")||n.includes("number")||n.includes("real")||n.includes("money")||n.includes("currency")||n.includes("percent")?"number":n.includes("timestamp")||n.includes("datetime")||n.startsWith("time")?"datetime":n.includes("date")?"date":n.includes("bool")?"boolean":"string":"unknown"}function T(e){let n=c(e),t="";for(;n&&n!==t;)t=n,n=f(n,"nullable"),n=f(n,"lowcardinality");return n}function f(e,n){const t=`${n}(`;return!e.startsWith(t)||!e.endsWith(")")?e:e.slice(t.length,-1).trim()}function h(e){const n=d(e);return n==="date"||n==="datetime"}function u(e){return h(e.dataType||e.data_type)}function y(e){const n=C(e);return n==="id"||n==="row_id"}function l(e){const n=C(e);return y(e)||n.endsWith("_id")||n.endsWith("_key")||n.endsWith("_number")}function C(e){return c(p(e)||e.name||e.alias).replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function m(e,n={}){const t=c(e.role);return t==="metric"||t==="measure"?!n.excludeIdentifiers||!l(e):t==="groupby"||t==="dimension"||t==="date"||t==="id"?!1:d(e.dataType||e.data_type)==="number"&&(!n.excludeIdentifiers||!l(e))}function _(e){return!m(e)&&!u(e)}function E(e){const n=new Set,t=new Set,r=new Set;for(const i of e){if(y(i))continue;const a=w(i);if(a.length!==0){if(u(i)){a.forEach(s=>t.add(s));continue}if(m(i,{excludeIdentifiers:!0})){a.forEach(s=>n.add(s));continue}a.forEach(s=>r.add(s))}}return{validMetricCandidates:Array.from(n).sort(),validDateCandidates:Array.from(t).sort(),validDimensionCandidates:Array.from(r).sort()}}exports.SEMAPHOR_ANALYZE_RESULT_FIELD_CONTRACT=o;exports.buildAnalyticsCatalogFieldSummary=E;exports.getAnalyticsCatalogFieldCandidates=w;exports.getAnalyticsCatalogFieldName=p;exports.getSemaphorAnalyzeResultFieldNames=D;exports.isAnalyticsCatalogDateField=u;exports.isAnalyticsCatalogDimensionField=_;exports.isAnalyticsCatalogMetricField=m;exports.isAnalyticsDateLikeDataType=h;exports.isAnalyticsMetricIdentifierField=l;exports.isAnalyticsTechnicalIdentifierField=y;exports.isSemaphorAnalyzeResultFieldName=g;exports.normalizeAnalyticsCatalogDataType=d;exports.normalizeAnalyticsCatalogName=c;exports.parseSemaphorAnalyzeResult=F;
@@ -1,200 +0,0 @@
1
- const o = {
2
- answerSummary: "string",
3
- responseDetail: "responseDetail",
4
- mode: "string",
5
- comparisonType: "string",
6
- executionResult: "unknown",
7
- compiledQuery: "unknown",
8
- data: "unknown",
9
- resultSets: "record",
10
- columns: "unknownArray",
11
- records: "recordArray",
12
- rowCount: "number",
13
- rowLimitExceeded: "boolean",
14
- output: "string",
15
- querySpec: "unknown",
16
- metadata: "record",
17
- validation: "unknown",
18
- coverage: "unknown",
19
- diagnosticFeedback: "unknown",
20
- missingFields: "stringArray",
21
- warnings: "unknownArray",
22
- comparison: "unknown",
23
- population: "unknown",
24
- comparisons: "recordArray",
25
- fieldsUsed: "unknown",
26
- changes: "recordArray",
27
- largestNegativeChanges: "recordArray",
28
- largestPositiveChanges: "recordArray",
29
- drivers: "recordArray",
30
- absoluteDeltaDrivers: "recordArray",
31
- largestNegativeDrivers: "recordArray",
32
- largestPositiveDrivers: "recordArray",
33
- periodRows: "recordArray",
34
- sql: "unknown",
35
- omitted: "stringArray"
36
- }, g = new Set(
37
- Object.keys(o)
38
- ), w = /* @__PURE__ */ new Set([
39
- "compact",
40
- "standard",
41
- "debug"
42
- ]);
43
- function _() {
44
- return Object.keys(
45
- o
46
- );
47
- }
48
- function h(e) {
49
- return g.has(e);
50
- }
51
- function E(e) {
52
- if (!e || typeof e != "object" || Array.isArray(e))
53
- throw new Error("Semaphor analyze result must be an object.");
54
- const n = e, r = Object.keys(n).filter(
55
- (t) => !h(t)
56
- );
57
- if (r.length)
58
- throw new Error(
59
- `Semaphor analyze result contains unsupported top-level field(s): ${r.join(", ")}.`
60
- );
61
- for (const [t, a] of Object.entries(n)) {
62
- if (a === void 0)
63
- continue;
64
- const i = o[t];
65
- if (!b(a, i))
66
- throw new Error(
67
- `Semaphor analyze result field "${t}" does not match contract kind "${i}".`
68
- );
69
- }
70
- return n;
71
- }
72
- function b(e, n) {
73
- switch (n) {
74
- case "boolean":
75
- return typeof e == "boolean";
76
- case "number":
77
- return typeof e == "number" && Number.isFinite(e);
78
- case "record":
79
- return d(e);
80
- case "recordArray":
81
- return Array.isArray(e) && e.every(d);
82
- case "responseDetail":
83
- return typeof e == "string" && w.has(e);
84
- case "string":
85
- return typeof e == "string";
86
- case "stringArray":
87
- return Array.isArray(e) && e.every((r) => typeof r == "string");
88
- case "unknown":
89
- return !0;
90
- case "unknownArray":
91
- return Array.isArray(e);
92
- }
93
- }
94
- function d(e) {
95
- return !!(e && typeof e == "object" && !Array.isArray(e));
96
- }
97
- function c(e) {
98
- return typeof e == "string" ? e.trim().toLowerCase() : "";
99
- }
100
- function k(e) {
101
- return String(e.column_name || e.name || e.qualifiedFieldName || "");
102
- }
103
- function S(e) {
104
- return Array.from(
105
- new Set(
106
- [
107
- e.column_name,
108
- e.name,
109
- e.qualifiedFieldName,
110
- e.alias
111
- ].filter(
112
- (n) => typeof n == "string" && n.trim().length > 0
113
- ).map((n) => n.trim())
114
- )
115
- );
116
- }
117
- function y(e) {
118
- const n = C(e);
119
- return n ? n.includes("int") || n.includes("uint") || n.includes("bigint") || n.includes("smallint") || n.includes("tinyint") || n.includes("numeric") || n.includes("decimal") || n.includes("double") || n.includes("float") || n.includes("number") || n.includes("real") || n.includes("money") || n.includes("currency") || n.includes("percent") ? "number" : n.includes("timestamp") || n.includes("datetime") || n.startsWith("time") ? "datetime" : n.includes("date") ? "date" : n.includes("bool") ? "boolean" : "string" : "unknown";
120
- }
121
- function C(e) {
122
- let n = c(e), r = "";
123
- for (; n && n !== r; )
124
- r = n, n = u(n, "nullable"), n = u(n, "lowcardinality");
125
- return n;
126
- }
127
- function u(e, n) {
128
- const r = `${n}(`;
129
- return !e.startsWith(r) || !e.endsWith(")") ? e : e.slice(r.length, -1).trim();
130
- }
131
- function D(e) {
132
- const n = y(e);
133
- return n === "date" || n === "datetime";
134
- }
135
- function m(e) {
136
- return D(e.dataType || e.data_type);
137
- }
138
- function f(e) {
139
- const n = p(e);
140
- return n === "id" || n === "row_id";
141
- }
142
- function l(e) {
143
- const n = p(e);
144
- return f(e) || n.endsWith("_id") || n.endsWith("_key") || n.endsWith("_number");
145
- }
146
- function p(e) {
147
- return c(
148
- k(e) || e.name || e.alias
149
- ).replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
150
- }
151
- function A(e, n = {}) {
152
- const r = c(e.role);
153
- return r === "metric" || r === "measure" ? !n.excludeIdentifiers || !l(e) : r === "groupby" || r === "dimension" || r === "date" || r === "id" ? !1 : y(
154
- e.dataType || e.data_type
155
- ) === "number" && (!n.excludeIdentifiers || !l(e));
156
- }
157
- function F(e) {
158
- return !A(e) && !m(e);
159
- }
160
- function T(e) {
161
- const n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set();
162
- for (const a of e) {
163
- if (f(a))
164
- continue;
165
- const i = S(a);
166
- if (i.length !== 0) {
167
- if (m(a)) {
168
- i.forEach((s) => r.add(s));
169
- continue;
170
- }
171
- if (A(a, { excludeIdentifiers: !0 })) {
172
- i.forEach((s) => n.add(s));
173
- continue;
174
- }
175
- i.forEach((s) => t.add(s));
176
- }
177
- }
178
- return {
179
- validMetricCandidates: Array.from(n).sort(),
180
- validDateCandidates: Array.from(r).sort(),
181
- validDimensionCandidates: Array.from(t).sort()
182
- };
183
- }
184
- export {
185
- o as S,
186
- k as a,
187
- S as b,
188
- y as c,
189
- D as d,
190
- m as e,
191
- f,
192
- _ as g,
193
- l as h,
194
- h as i,
195
- A as j,
196
- F as k,
197
- T as l,
198
- c as n,
199
- E as p
200
- };