react-semaphor 0.1.381 → 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.
- package/DATA_APP_SDK.md +238 -0
- package/README.md +7 -0
- package/dist/analytics-protocol/index.cjs +1 -1
- package/dist/analytics-protocol/index.js +45 -41
- package/dist/brand-studio/index.cjs +1 -1
- package/dist/brand-studio/index.js +6 -6
- package/dist/chunks/analyze-result-contract-CtXfp3nv.js +1 -0
- package/dist/chunks/analyze-result-contract-DuhlklhI.js +102 -0
- package/dist/chunks/{braces-BT-ZyB-g.js → braces-CGi-YFZp.js} +1 -1
- package/dist/chunks/{braces-DOxxfERN.js → braces-CP8BEzl3.js} +1 -1
- package/dist/chunks/{calendar-preferences-dialog-Dsgs8WDv.js → calendar-preferences-dialog-CV4xF2Tp.js} +3 -3
- package/dist/chunks/{calendar-preferences-dialog-iZs8XqyH.js → calendar-preferences-dialog-rDDobeLo.js} +1 -1
- package/dist/chunks/catalog-field-grounding-Bnx-3tE0.js +1 -0
- package/dist/chunks/catalog-field-grounding-CJKAqtiC.js +100 -0
- package/dist/chunks/{dashboard-briefing-launcher-Coks66cV.js → dashboard-briefing-launcher-BT00MvGB.js} +5 -5
- package/dist/chunks/{dashboard-briefing-launcher-B5vPTl8P.js → dashboard-briefing-launcher-Dcbh-mjY.js} +1 -1
- package/dist/chunks/{dashboard-controls-BfkcnIdy.js → dashboard-controls-B6y7jkKO.js} +8 -8
- package/dist/chunks/{dashboard-controls-Dyqye6fh.js → dashboard-controls-CRqnPibB.js} +1 -1
- package/dist/chunks/{dashboard-json-DjXi4cI6.js → dashboard-json-CfIUG8k1.js} +3 -3
- package/dist/chunks/{dashboard-json-CV_LnO9x.js → dashboard-json-DEQqRR1x.js} +1 -1
- package/dist/chunks/{edit-dashboard-visual-DOW1Ap1N.js → edit-dashboard-visual-DMbf89xa.js} +5 -5
- package/dist/chunks/{edit-dashboard-visual-yinO0yU-.js → edit-dashboard-visual-wDOcHak3.js} +1 -1
- package/dist/chunks/{index-DlprYjr6.js → index-BAsWLkZ8.js} +169 -168
- package/dist/chunks/{index-CkoRCh3g.js → index-CrKxP9uF.js} +5 -5
- package/dist/chunks/{layout-grid-DTbOIOsE.js → layout-grid-BsKH3TgY.js} +1 -1
- package/dist/chunks/{layout-grid-DccceHv4.js → layout-grid-jJQUqDN9.js} +1 -1
- package/dist/chunks/operators-C8TxpM4C.js +48 -0
- package/dist/chunks/operators-DrTQsJXv.js +1 -0
- package/dist/chunks/{palette-SimHJELn.js → palette-9zLPGlj2.js} +1 -1
- package/dist/chunks/{palette-DCzLwqIw.js → palette-xU9Qt6bE.js} +1 -1
- package/dist/chunks/{save-D2O96E5A.js → save-8A_q6K4E.js} +1 -1
- package/dist/chunks/{save-zNVYH02T.js → save-DzciESDh.js} +1 -1
- package/dist/chunks/{source-identity-Dj3dryN9.js → source-identity-CN4xiyKJ.js} +5 -5
- package/dist/chunks/{switch-DMPsMpHW.js → switch-DArtNJZh.js} +292 -291
- package/dist/chunks/{switch-Jhyl63RF.js → switch-k7kj6NRg.js} +1 -1
- package/dist/chunks/{use-create-flow-overlay-state-r5JKyXU8.js → use-create-flow-overlay-state-BdG1DiSx.js} +4 -4
- package/dist/chunks/{use-create-flow-overlay-state-NsqFPwdB.js → use-create-flow-overlay-state-ipeaE65_.js} +1 -1
- package/dist/chunks/{validators-CtNmgsvG.js → validators-CHPH6ORs.js} +641 -498
- package/dist/chunks/validators-lWo8m0Q7.js +1 -0
- package/dist/dashboard/index.cjs +1 -1
- package/dist/dashboard/index.js +1 -1
- package/dist/dashboard-authoring/index.cjs +3 -3
- package/dist/dashboard-authoring/index.js +105 -92
- package/dist/data-app-builder/index.cjs +1 -1
- package/dist/data-app-builder/index.js +3 -3
- package/dist/data-app-sdk/index.cjs +1 -1
- package/dist/data-app-sdk/index.js +444 -380
- package/dist/data-app-sdk-adapters/index.cjs +1 -0
- package/dist/data-app-sdk-adapters/index.js +383 -0
- package/dist/data-app-sdk-validation/index.cjs +1 -1
- package/dist/data-app-sdk-validation/index.js +1073 -6
- package/dist/index.cjs +1 -1
- package/dist/index.js +7 -7
- package/dist/surfboard/index.cjs +1 -1
- package/dist/surfboard/index.js +2 -2
- package/dist/types/analytics-protocol.d.ts +58 -31
- package/dist/types/dashboard-assistant.d.ts +40 -15
- package/dist/types/dashboard-authoring.d.ts +36 -16
- package/dist/types/dashboard.d.ts +8 -8
- package/dist/types/data-app-builder.d.ts +35 -11
- package/dist/types/data-app-sdk-adapters.d.ts +733 -0
- package/dist/types/data-app-sdk-validation.d.ts +85 -25
- package/dist/types/data-app-sdk.d.ts +99 -155
- package/dist/types/main.d.ts +35 -11
- package/dist/types/shared.d.ts +8 -8
- package/dist/types/surfboard.d.ts +8 -8
- package/dist/types/types.d.ts +8 -8
- package/package.json +9 -2
- package/src/data-app-sdk/README.md +240 -0
- package/dist/chunks/catalog-field-grounding-8L9I0zdg.js +0 -1
- package/dist/chunks/catalog-field-grounding-BK4BX8sZ.js +0 -200
- package/dist/chunks/validation-BM3-ShHV.js +0 -1003
- package/dist/chunks/validation-BVpqRFar.js +0 -1
- 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' | '
|
|
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' | '
|
|
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
|
}>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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' | '
|
|
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' | '
|
|
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.
|
|
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
|
-
};
|