@finos/legend-application-query 13.8.51 → 13.8.53

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 (95) hide show
  1. package/lib/__lib__/LegendQueryEvent.d.ts +6 -0
  2. package/lib/__lib__/LegendQueryEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendQueryEvent.js +6 -0
  4. package/lib/__lib__/LegendQueryEvent.js.map +1 -1
  5. package/lib/__lib__/LegendQueryLifecycleTelemetry.d.ts +58 -0
  6. package/lib/__lib__/LegendQueryLifecycleTelemetry.d.ts.map +1 -0
  7. package/lib/__lib__/LegendQueryLifecycleTelemetry.js +90 -0
  8. package/lib/__lib__/LegendQueryLifecycleTelemetry.js.map +1 -0
  9. package/lib/__lib__/LegendQueryNavigation.d.ts +1 -1
  10. package/lib/__lib__/LegendQueryNavigation.d.ts.map +1 -1
  11. package/lib/__lib__/LegendQueryNavigation.js +11 -1
  12. package/lib/__lib__/LegendQueryNavigation.js.map +1 -1
  13. package/lib/__lib__/LegendQuerySourceInfo.d.ts +137 -0
  14. package/lib/__lib__/LegendQuerySourceInfo.d.ts.map +1 -0
  15. package/lib/__lib__/LegendQuerySourceInfo.js +33 -0
  16. package/lib/__lib__/LegendQuerySourceInfo.js.map +1 -0
  17. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts +73 -1
  18. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts.map +1 -1
  19. package/lib/__lib__/LegendQueryTelemetryHelper.js +18 -0
  20. package/lib/__lib__/LegendQueryTelemetryHelper.js.map +1 -1
  21. package/lib/application/LegendQueryApplicationConfig.d.ts +2 -0
  22. package/lib/application/LegendQueryApplicationConfig.d.ts.map +1 -1
  23. package/lib/application/LegendQueryApplicationConfig.js +2 -0
  24. package/lib/application/LegendQueryApplicationConfig.js.map +1 -1
  25. package/lib/components/Core_LegendQueryApplicationPlugin.d.ts.map +1 -1
  26. package/lib/components/Core_LegendQueryApplicationPlugin.js +13 -2
  27. package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -1
  28. package/lib/index.css +1 -1
  29. package/lib/index.d.ts +2 -1
  30. package/lib/index.d.ts.map +1 -1
  31. package/lib/index.js +2 -1
  32. package/lib/index.js.map +1 -1
  33. package/lib/light-mode.css +1 -1
  34. package/lib/package.json +1 -1
  35. package/lib/stores/EditExistingQuerySetupStore.d.ts.map +1 -1
  36. package/lib/stores/EditExistingQuerySetupStore.js +4 -13
  37. package/lib/stores/EditExistingQuerySetupStore.js.map +1 -1
  38. package/lib/stores/LegendQueryApplicationPlugin.d.ts +2 -1
  39. package/lib/stores/LegendQueryApplicationPlugin.d.ts.map +1 -1
  40. package/lib/stores/LegendQueryApplicationPlugin.js +23 -0
  41. package/lib/stores/LegendQueryApplicationPlugin.js.map +1 -1
  42. package/lib/stores/QueryEditorStore.d.ts +30 -2
  43. package/lib/stores/QueryEditorStore.d.ts.map +1 -1
  44. package/lib/stores/QueryEditorStore.js +123 -79
  45. package/lib/stores/QueryEditorStore.js.map +1 -1
  46. package/lib/stores/QueryProductionizerSetupStore.d.ts.map +1 -1
  47. package/lib/stores/QueryProductionizerSetupStore.js +4 -13
  48. package/lib/stores/QueryProductionizerSetupStore.js.map +1 -1
  49. package/lib/stores/QuerySetupStore.d.ts.map +1 -1
  50. package/lib/stores/QuerySetupStore.js +1 -0
  51. package/lib/stores/QuerySetupStore.js.map +1 -1
  52. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.d.ts +2 -0
  53. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.d.ts.map +1 -1
  54. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.js +12 -1
  55. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.js.map +1 -1
  56. package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts +10 -0
  57. package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts.map +1 -1
  58. package/lib/stores/data-space/DataProductQueryCreatorStore.js +63 -19
  59. package/lib/stores/data-space/DataProductQueryCreatorStore.js.map +1 -1
  60. package/lib/stores/data-space/DataProductSelectorState.d.ts +4 -2
  61. package/lib/stores/data-space/DataProductSelectorState.d.ts.map +1 -1
  62. package/lib/stores/data-space/DataProductSelectorState.js +30 -9
  63. package/lib/stores/data-space/DataProductSelectorState.js.map +1 -1
  64. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts +2 -0
  65. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts.map +1 -1
  66. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js +13 -7
  67. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js.map +1 -1
  68. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.d.ts.map +1 -1
  69. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js +1 -1
  70. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js.map +1 -1
  71. package/lib/stores/ingest/IngestQueryCreatorStore.d.ts +2 -0
  72. package/lib/stores/ingest/IngestQueryCreatorStore.d.ts.map +1 -1
  73. package/lib/stores/ingest/IngestQueryCreatorStore.js +10 -3
  74. package/lib/stores/ingest/IngestQueryCreatorStore.js.map +1 -1
  75. package/package.json +13 -13
  76. package/src/__lib__/LegendQueryEvent.ts +7 -0
  77. package/src/__lib__/LegendQueryLifecycleTelemetry.ts +132 -0
  78. package/src/__lib__/LegendQueryNavigation.ts +20 -1
  79. package/src/__lib__/LegendQuerySourceInfo.ts +162 -0
  80. package/src/__lib__/LegendQueryTelemetryHelper.ts +120 -1
  81. package/src/application/LegendQueryApplicationConfig.ts +5 -1
  82. package/src/components/Core_LegendQueryApplicationPlugin.tsx +21 -2
  83. package/src/index.ts +6 -1
  84. package/src/stores/EditExistingQuerySetupStore.ts +8 -20
  85. package/src/stores/LegendQueryApplicationPlugin.tsx +38 -0
  86. package/src/stores/QueryEditorStore.ts +178 -86
  87. package/src/stores/QueryProductionizerSetupStore.ts +8 -20
  88. package/src/stores/QuerySetupStore.ts +2 -0
  89. package/src/stores/data-product/DataProductSampleQueryCreatorStore.ts +17 -0
  90. package/src/stores/data-space/DataProductQueryCreatorStore.ts +99 -33
  91. package/src/stores/data-space/DataProductSelectorState.ts +58 -13
  92. package/src/stores/data-space/DataSpaceTemplateQueryCreatorStore.ts +17 -6
  93. package/src/stores/data-space/LegendQueryBareQueryBuilderState.ts +5 -1
  94. package/src/stores/ingest/IngestQueryCreatorStore.ts +16 -5
  95. package/tsconfig.json +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-application-query",
3
- "version": "13.8.51",
3
+ "version": "13.8.53",
4
4
  "description": "Legend Query application core",
5
5
  "keywords": [
6
6
  "legend",
@@ -44,18 +44,18 @@
44
44
  "test:watch": "jest --watch"
45
45
  },
46
46
  "dependencies": {
47
- "@finos/legend-application": "16.0.122",
48
- "@finos/legend-art": "7.1.162",
49
- "@finos/legend-code-editor": "2.0.202",
50
- "@finos/legend-data-cube": "0.3.120",
51
- "@finos/legend-extension-dsl-data-space": "10.4.254",
52
- "@finos/legend-graph": "32.6.33",
53
- "@finos/legend-lego": "2.0.222",
54
- "@finos/legend-query-builder": "4.19.11",
55
- "@finos/legend-server-depot": "6.1.20",
56
- "@finos/legend-server-lakehouse": "0.3.82",
57
- "@finos/legend-shared": "11.0.28",
58
- "@finos/legend-storage": "3.0.150",
47
+ "@finos/legend-application": "16.0.124",
48
+ "@finos/legend-art": "7.1.164",
49
+ "@finos/legend-code-editor": "2.0.204",
50
+ "@finos/legend-data-cube": "0.3.122",
51
+ "@finos/legend-extension-dsl-data-space": "10.4.256",
52
+ "@finos/legend-graph": "32.7.0",
53
+ "@finos/legend-lego": "2.0.224",
54
+ "@finos/legend-query-builder": "4.19.13",
55
+ "@finos/legend-server-depot": "6.1.21",
56
+ "@finos/legend-server-lakehouse": "0.3.84",
57
+ "@finos/legend-shared": "11.0.29",
58
+ "@finos/legend-storage": "3.0.151",
59
59
  "@testing-library/dom": "10.4.0",
60
60
  "@testing-library/react": "16.2.0",
61
61
  "@types/react": "19.0.10",
@@ -22,7 +22,14 @@ export enum LEGEND_QUERY_APP_EVENT {
22
22
  CREATE_QUERY__SUCCESS = 'query-editor.create-query.success',
23
23
  UPDATE_QUERY__SUCCESS = 'query-editor.update-query.success',
24
24
  RENAME_QUERY__SUCCESS = 'query-editor.rename.query.success',
25
+ DELETE_QUERY__SUCCESS = 'query-editor.delete-query.success',
26
+
27
+ CREATE_QUERY__FAILURE = 'query-editor.create-query.failure',
28
+ UPDATE_QUERY__FAILURE = 'query-editor.update-query.failure',
29
+ RENAME_QUERY__FAILURE = 'query-editor.rename-query.failure',
30
+ DELETE_QUERY__FAILURE = 'query-editor.delete-query.failure',
25
31
  INITIALIZE_QUERY_STATE__SUCCESS = 'query-editor.initialize-query-state.success',
32
+ INITIALIZE_QUERY_CREATOR__FAILURE = 'query-editor.initialize-query-creator.failure',
26
33
  LEGENDAI_QUERY_AGENT_CHAT__OPENED = 'query-editor.legendai-query-agent-chat.opened',
27
34
  LEGENDAI_QUERY_AGENT_CHAT__QUERY_LOADED = 'query-editor.legendai-query-agent-chat.query-loaded',
28
35
  LEGENDAI_QUERY_SUGGEST__LAUNCH = 'query-editor.legendai-query-suggest.launch',
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type { LightQuery } from '@finos/legend-graph';
18
+ import { buildTelemetryErrorFields } from '@finos/legend-shared';
19
+ import type { GenericLegendApplicationStore } from '@finos/legend-application';
20
+ import type { CompleteQueryLoaderLifecycleHandlers } from '@finos/legend-query-builder';
21
+ import {
22
+ type PartialQuery_TelemetryData,
23
+ type QueryCreateFailure_TelemetryData,
24
+ type QueryLifecycleFailure_TelemetryData,
25
+ type Query_TelemetryData,
26
+ LegendQueryTelemetryHelper,
27
+ } from './LegendQueryTelemetryHelper.js';
28
+
29
+ /**
30
+ * Builds the error half of a saved-query lifecycle failure payload, applying the
31
+ * same message cap and `errorMessageTruncated` flag as every other failure event.
32
+ */
33
+ export const buildQueryLifecycleFailureData = (
34
+ queryId: string,
35
+ error: Error,
36
+ ): QueryLifecycleFailure_TelemetryData => ({
37
+ // NOTE: only the id is available on these paths — the loader reports a
38
+ // failure by id, and the query it refers to was never resolved
39
+ query: { id: queryId },
40
+ ...buildTelemetryErrorFields(error),
41
+ });
42
+
43
+ /**
44
+ * Maps a query to the identity block every lifecycle event carries.
45
+ */
46
+ export const buildQueryIdentity = (query: LightQuery): Query_TelemetryData => ({
47
+ query: {
48
+ id: query.id,
49
+ name: query.name,
50
+ groupId: query.groupId,
51
+ artifactId: query.artifactId,
52
+ versionId: query.versionId,
53
+ },
54
+ });
55
+
56
+ /**
57
+ * Builds the payload for a failed *create*.
58
+ *
59
+ * Separate from {@link buildQueryLifecycleFailureData} because a failed create
60
+ * has no query to identify — the server assigns the id and the request never got
61
+ * that far. Reporting the chosen name instead of a placeholder id keeps "never
62
+ * persisted" distinguishable from a real value.
63
+ */
64
+ export const buildQueryCreateFailureData = (
65
+ queryName: string,
66
+ error: Error,
67
+ ): QueryCreateFailure_TelemetryData => ({
68
+ queryName,
69
+ ...buildTelemetryErrorFields(error),
70
+ });
71
+
72
+ /**
73
+ * The saved-query lifecycle handlers every `QueryLoaderState` host wires in.
74
+ *
75
+ * Rename and delete happen inside the shared query loader, which reports them
76
+ * back through callbacks — so without this the same emit would be duplicated at
77
+ * each of the three hosts that build a loader (and before this existed, the
78
+ * rename emit was in fact triplicated while delete was reported nowhere).
79
+ *
80
+ * NOTE: these events deliberately carry no source info. They fire from the query
81
+ * *picker*, where the user may rename or delete one query while editing another
82
+ * — attaching the loaded query builder's source info would silently mislabel the
83
+ * row as belonging to the wrong query.
84
+ */
85
+ export const buildQueryLoaderLifecycleTelemetryHandlers = (
86
+ applicationStore: GenericLegendApplicationStore,
87
+ sideEffects?:
88
+ | {
89
+ /**
90
+ * Runs alongside the delete telemetry — hosts use this to prune their
91
+ * recently-viewed list.
92
+ */
93
+ onQueryDeleted?: ((queryId: string) => void) | undefined;
94
+ }
95
+ | undefined,
96
+ ): CompleteQueryLoaderLifecycleHandlers => {
97
+ const { telemetryService } = applicationStore;
98
+ return {
99
+ onQueryRenamed: (query): void => {
100
+ LegendQueryTelemetryHelper.logEvent_RenameQuerySucceeded(
101
+ telemetryService,
102
+ buildQueryIdentity(query),
103
+ );
104
+ },
105
+ onQueryDeleted: (queryId, deletedQuery): void => {
106
+ sideEffects?.onQueryDeleted?.(queryId);
107
+ // the entry may not have been in the loaded list, in which case only the
108
+ // id is known
109
+ const identity: PartialQuery_TelemetryData = deletedQuery
110
+ ? buildQueryIdentity(deletedQuery)
111
+ : { query: { id: queryId } };
112
+ LegendQueryTelemetryHelper.logEvent_DeleteQuerySucceeded(
113
+ telemetryService,
114
+ identity,
115
+ );
116
+ },
117
+ onQueryRenameFailed: (queryId, error): void => {
118
+ // the rename failed, so the loader never resolved the renamed query —
119
+ // only its id and the error are known
120
+ LegendQueryTelemetryHelper.logEvent_RenameQueryFailed(
121
+ telemetryService,
122
+ buildQueryLifecycleFailureData(queryId, error),
123
+ );
124
+ },
125
+ onQueryDeleteFailed: (queryId, error): void => {
126
+ LegendQueryTelemetryHelper.logEvent_DeleteQueryFailed(
127
+ telemetryService,
128
+ buildQueryLifecycleFailureData(queryId, error),
129
+ );
130
+ },
131
+ };
132
+ };
@@ -442,6 +442,20 @@ export const EXTERNAL_APPLICATION_NAVIGATION__generateNewDataCubeUrl = (
442
442
  )}`;
443
443
  };
444
444
 
445
+ /**
446
+ * Mirrors `generateAnchorForSection` from `@finos/legend-extension-dsl-data-product`,
447
+ * which this package does not depend on. The data product viewer registers one anchor
448
+ * per access point group, and reads the zone from the URL hash on load.
449
+ *
450
+ * @external_application_navigation This depends on Legend Marketplace routing and is hardcoded so it's potentially brittle
451
+ */
452
+ const EXTERNAL_APPLICATION_NAVIGATION__generateAccessPointGroupAnchor = (
453
+ accessPointGroupId: string,
454
+ ): string =>
455
+ encodeURIComponent(
456
+ `apg-${accessPointGroupId}`.trim().toLowerCase().replace(/\s+/gu, '-'),
457
+ );
458
+
445
459
  /**
446
460
  * @external_application_navigation This depends on Legend Marketplace routing and is hardcoded so it's potentially brittle
447
461
  */
@@ -450,5 +464,10 @@ export const EXTERNAL_APPLICATION_NAVIGATION__generateMarketplaceDataProductUrl
450
464
  marketplaceApplicationUrl: string,
451
465
  dataProductId: string,
452
466
  deploymentId: string,
467
+ accessPointGroupId?: string | undefined,
453
468
  ): string =>
454
- `${marketplaceApplicationUrl}/dataProduct/deployed/${dataProductId}/${deploymentId}`;
469
+ `${marketplaceApplicationUrl}/dataProduct/deployed/${dataProductId}/${deploymentId}${
470
+ accessPointGroupId
471
+ ? `#${EXTERNAL_APPLICATION_NAVIGATION__generateAccessPointGroupAnchor(accessPointGroupId)}`
472
+ : ''
473
+ }`;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type { LegendSourceInfo } from '@finos/legend-storage';
18
+
19
+ /**
20
+ * The entry point a query creator was started from.
21
+ */
22
+ export enum LegendQuerySourceType {
23
+ MAPPING = 'mapping',
24
+ SERVICE = 'service',
25
+ DATA_SPACE = 'data-space',
26
+ DATA_SPACE_TEMPLATE = 'data-space.template',
27
+ DATA_PRODUCT = 'data-product',
28
+ DATA_PRODUCT_SAMPLE = 'data-product.sample',
29
+ INGEST = 'ingest',
30
+ /**
31
+ * The default route, when no data product or data space has been selected yet
32
+ */
33
+ UNSELECTED = 'unselected',
34
+ }
35
+
36
+ /**
37
+ * Coordinates of the project the query is started from
38
+ */
39
+ interface LegendQueryProjectSourceInfo extends LegendSourceInfo {
40
+ groupId: string;
41
+ artifactId: string;
42
+ versionId: string;
43
+ /**
44
+ * Set when a *saved* query was opened (the `/existing/:queryId` route) rather
45
+ * than a new one created from a creator route. The `sourceType` still
46
+ * describes what the query targets — a saved data space query reports
47
+ * `data-space`, same as a freshly created one — so a dashboard can slice by
48
+ * target without caring how the query was opened, and use the presence of
49
+ * this field to separate saved from new when it does care.
50
+ */
51
+ queryId?: string | undefined;
52
+ }
53
+
54
+ /**
55
+ * Query created on a mapping and runtime
56
+ * `/create/manual/:gav/:mappingPath/:runtimePath`
57
+ */
58
+ export interface LegendQueryMappingSourceInfo
59
+ extends LegendQueryProjectSourceInfo {
60
+ sourceType: LegendQuerySourceType.MAPPING;
61
+ mapping: string;
62
+ runtime: string;
63
+ }
64
+
65
+ /**
66
+ * Query created from a service
67
+ * `/create-from-service/:gav/:servicePath`
68
+ */
69
+ export interface LegendQueryServiceSourceInfo
70
+ extends LegendQueryProjectSourceInfo {
71
+ sourceType: LegendQuerySourceType.SERVICE;
72
+ service: string;
73
+ }
74
+
75
+ /**
76
+ * Query created on a data space
77
+ * `/dataspace/:gav/:dataSpacePath/:executionContext?`
78
+ */
79
+ export interface LegendQueryDataSpaceSourceInfo
80
+ extends LegendQueryProjectSourceInfo {
81
+ sourceType: LegendQuerySourceType.DATA_SPACE;
82
+ dataSpace: string;
83
+ /**
84
+ * The key of the execution context the query was started with, when known
85
+ */
86
+ executionContext?: string | undefined;
87
+ }
88
+
89
+ /**
90
+ * Query created from a data space template query
91
+ * `/dataspace/:gav/:dataSpacePath/template/:templateQueryId`
92
+ */
93
+ export interface LegendQueryDataSpaceTemplateSourceInfo
94
+ extends LegendQueryProjectSourceInfo {
95
+ sourceType: LegendQuerySourceType.DATA_SPACE_TEMPLATE;
96
+ dataSpace: string;
97
+ templateQueryId: string;
98
+ }
99
+
100
+ /**
101
+ * Query created on a data product
102
+ * `/data-product/:accessType/:gav/:dataProductPath/:accessId`
103
+ */
104
+ export interface LegendQueryDataProductSourceInfo
105
+ extends LegendQueryProjectSourceInfo {
106
+ sourceType: LegendQuerySourceType.DATA_PRODUCT;
107
+ dataProduct: string;
108
+ /**
109
+ * The access type (e.g. native, model, lakehouse) the query was started
110
+ * with, when known
111
+ */
112
+ accessType?: string | undefined;
113
+ /**
114
+ * The ID of the access point (group) or execution context the query was
115
+ * started with, when known
116
+ */
117
+ accessId?: string | undefined;
118
+ }
119
+
120
+ /**
121
+ * Query created from a data product sample query
122
+ * `/data-product/native/sample-query/:gav/:dataProductPath/:sampleQueryId`
123
+ */
124
+ export interface LegendQueryDataProductSampleSourceInfo
125
+ extends LegendQueryProjectSourceInfo {
126
+ sourceType: LegendQuerySourceType.DATA_PRODUCT_SAMPLE;
127
+ dataProduct: string;
128
+ sampleQueryId: string;
129
+ }
130
+
131
+ /**
132
+ * Query created on an ingest data set
133
+ * `/ingest/:gav/:ingestDefinitionPath/:dataSet`
134
+ */
135
+ export interface LegendQueryIngestSourceInfo
136
+ extends LegendQueryProjectSourceInfo {
137
+ sourceType: LegendQuerySourceType.INGEST;
138
+ ingestDefinitionPath: string;
139
+ dataSet: string;
140
+ }
141
+
142
+ /**
143
+ * The default route `/`, when no data product or data space has been
144
+ * selected yet
145
+ */
146
+ export interface LegendQueryUnselectedSourceInfo extends LegendSourceInfo {
147
+ sourceType: LegendQuerySourceType.UNSELECTED;
148
+ }
149
+
150
+ /**
151
+ * Where a query creator was started from, used as the query builder state
152
+ * source info (see `QueryBuilderState.sourceInfo`) and reported in telemetry
153
+ */
154
+ export type LegendQuerySourceInfo =
155
+ | LegendQueryMappingSourceInfo
156
+ | LegendQueryServiceSourceInfo
157
+ | LegendQueryDataSpaceSourceInfo
158
+ | LegendQueryDataSpaceTemplateSourceInfo
159
+ | LegendQueryDataProductSourceInfo
160
+ | LegendQueryDataProductSampleSourceInfo
161
+ | LegendQueryIngestSourceInfo
162
+ | LegendQueryUnselectedSourceInfo;
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import type { TelemetryService } from '@finos/legend-application';
18
+ import type { TelemetryErrorFields, TimingsRecord } from '@finos/legend-shared';
18
19
  import { LEGEND_QUERY_APP_EVENT } from './LegendQueryEvent.js';
19
20
  import {
20
21
  type GraphManagerOperationReport,
@@ -22,7 +23,7 @@ import {
22
23
  type GraphInitializationReport,
23
24
  } from '@finos/legend-graph';
24
25
 
25
- type Query_TelemetryData = {
26
+ export type Query_TelemetryData = {
26
27
  query: {
27
28
  name: string;
28
29
  id: string;
@@ -46,6 +47,79 @@ type IntializeQueryState_TelemetryData = Query_TelemetryData &
46
47
  dependenciesCount: number;
47
48
  };
48
49
 
50
+ /**
51
+ * Where the query creator was started from, returned by each creator store's
52
+ * `getInitializeTelemetrySource()`.
53
+ *
54
+ * The entry point the query creator was started from ({@link
55
+ * LegendQuerySourceInfo}) is spread FLAT into this payload, matching how
56
+ * `sourceInfo` is reported on every other query telemetry event.
57
+ *
58
+ * The index signature is what allows those flat keys — they vary by entry point
59
+ * and `LegendQuerySourceInfo` is a union, so they cannot be enumerated here.
60
+ * The union stays strictly typed where it is built, in each creator store's
61
+ * `getSourceInfo()` override.
62
+ */
63
+ export type InitializeTelemetrySource = Record<PropertyKey, unknown> & {
64
+ /**
65
+ * Whether the most recently visited source was reopened, rather than the
66
+ * source being specified by the route
67
+ */
68
+ restoredFromRecent: boolean;
69
+ };
70
+
71
+ /**
72
+ * Base payload for the query creator failure event.
73
+ *
74
+ * There is no success counterpart: a successful load is reported by
75
+ * `query-builder.opened` from `legend-query-builder`, which fires for every
76
+ * route rather than creators only. This one survives because when a load fails
77
+ * there is no query builder to emit from, so it is the only record that an
78
+ * attempt happened.
79
+ */
80
+ export type InitializeQueryCreator_TelemetryData = InitializeTelemetrySource & {
81
+ timings: TimingsRecord;
82
+ };
83
+
84
+ export type InitializeQueryCreatorFailure_TelemetryData =
85
+ InitializeQueryCreator_TelemetryData & TelemetryErrorFields;
86
+
87
+ /**
88
+ * The query a lifecycle event acted on. `id` is always known for update, rename
89
+ * and delete — they act on a query that already exists. Identity beyond the id
90
+ * is partial: a delete resolves the entry from the loaded list, which may not
91
+ * contain it.
92
+ */
93
+ export type PartialQuery_TelemetryData = {
94
+ query: {
95
+ id: string;
96
+ name?: string | undefined;
97
+ versionId?: string | undefined;
98
+ groupId?: string | undefined;
99
+ artifactId?: string | undefined;
100
+ };
101
+ };
102
+
103
+ /**
104
+ * Payload for a failed *create*.
105
+ *
106
+ * Deliberately has no `query` block: the server assigns the id, and a failed
107
+ * create never got that far, so no query exists to identify. The name the user
108
+ * chose is the only identity there is. Keeping this a separate type from
109
+ * {@link QueryLifecycleFailure_TelemetryData} means the three events that *do*
110
+ * always have an id cannot accidentally omit it.
111
+ */
112
+ export type QueryCreateFailure_TelemetryData = {
113
+ queryName: string;
114
+ } & TelemetryErrorFields;
115
+
116
+ /**
117
+ * Payload for a failed update, rename or delete — actions on a query that
118
+ * already exists, so `query.id` is always present.
119
+ */
120
+ export type QueryLifecycleFailure_TelemetryData = PartialQuery_TelemetryData &
121
+ TelemetryErrorFields;
122
+
49
123
  export class LegendQueryTelemetryHelper {
50
124
  static logEvent_ViewQuerySucceeded(
51
125
  service: TelemetryService,
@@ -64,6 +138,16 @@ export class LegendQueryTelemetryHelper {
64
138
  );
65
139
  }
66
140
 
141
+ static logEvent_InitializeQueryCreatorFailed(
142
+ service: TelemetryService,
143
+ data: InitializeQueryCreatorFailure_TelemetryData,
144
+ ): void {
145
+ service.logEvent(
146
+ LEGEND_QUERY_APP_EVENT.INITIALIZE_QUERY_CREATOR__FAILURE,
147
+ data,
148
+ );
149
+ }
150
+
67
151
  static logEvent_CreateQuerySucceeded(
68
152
  service: TelemetryService,
69
153
  data: Query_TelemetryData,
@@ -109,6 +193,41 @@ export class LegendQueryTelemetryHelper {
109
193
  service.logEvent(LEGEND_QUERY_APP_EVENT.RENAME_QUERY__SUCCESS, data);
110
194
  }
111
195
 
196
+ static logEvent_DeleteQuerySucceeded(
197
+ service: TelemetryService,
198
+ data: PartialQuery_TelemetryData,
199
+ ): void {
200
+ service.logEvent(LEGEND_QUERY_APP_EVENT.DELETE_QUERY__SUCCESS, data);
201
+ }
202
+
203
+ static logEvent_CreateQueryFailed(
204
+ service: TelemetryService,
205
+ data: QueryCreateFailure_TelemetryData,
206
+ ): void {
207
+ service.logEvent(LEGEND_QUERY_APP_EVENT.CREATE_QUERY__FAILURE, data);
208
+ }
209
+
210
+ static logEvent_UpdateQueryFailed(
211
+ service: TelemetryService,
212
+ data: QueryLifecycleFailure_TelemetryData,
213
+ ): void {
214
+ service.logEvent(LEGEND_QUERY_APP_EVENT.UPDATE_QUERY__FAILURE, data);
215
+ }
216
+
217
+ static logEvent_RenameQueryFailed(
218
+ service: TelemetryService,
219
+ data: QueryLifecycleFailure_TelemetryData,
220
+ ): void {
221
+ service.logEvent(LEGEND_QUERY_APP_EVENT.RENAME_QUERY__FAILURE, data);
222
+ }
223
+
224
+ static logEvent_DeleteQueryFailed(
225
+ service: TelemetryService,
226
+ data: QueryLifecycleFailure_TelemetryData,
227
+ ): void {
228
+ service.logEvent(LEGEND_QUERY_APP_EVENT.DELETE_QUERY__FAILURE, data);
229
+ }
230
+
112
231
  static logEvent_QueryAISuggestLaunched(service: TelemetryService): void {
113
232
  service.logEvent(LEGEND_QUERY_APP_EVENT.LEGENDAI_QUERY_SUGGEST__LAUNCH, {});
114
233
  }
@@ -142,7 +142,7 @@ export interface LegendQueryApplicationConfigurationData
142
142
  depot: {
143
143
  url: string;
144
144
  };
145
- engine: { url: string; queryUrl?: string };
145
+ engine: { url: string; queryUrl?: string; useCookieAuthOnly?: boolean };
146
146
  studio: {
147
147
  url: string;
148
148
  instances: LegendStudioApplicationInstanceConfigurationData[];
@@ -171,6 +171,7 @@ export class LegendQueryApplicationConfig extends LegendApplicationConfig {
171
171
 
172
172
  readonly engineServerUrl: string;
173
173
  readonly engineQueryServerUrl?: string | undefined;
174
+ readonly engineUseCookieAuthOnly: boolean;
174
175
  readonly depotServerUrl: string;
175
176
  readonly studioApplicationUrl: string;
176
177
  readonly taxonomyApplicationUrl?: string;
@@ -204,6 +205,9 @@ export class LegendQueryApplicationConfig extends LegendApplicationConfig {
204
205
  input.configData.engine.queryUrl,
205
206
  )
206
207
  : undefined;
208
+ this.engineUseCookieAuthOnly = Boolean(
209
+ input.configData.engine.useCookieAuthOnly,
210
+ );
207
211
 
208
212
  // depot
209
213
  assertNonNullable(
@@ -141,6 +141,19 @@ import { LegendQueryDataProductQueryBuilderState } from '../stores/data-product/
141
141
  import { IngestLegendQueryBuilderState } from '../stores/ingest/IngestLegendQueryBuilderState.js';
142
142
  import { renderDataProductSampleQueryPanelContent } from './data-product/DataProductSampleQueryPanel.js';
143
143
 
144
+ const isDataProductOrIngestQuery = (
145
+ queryBuilderState: QueryBuilderState,
146
+ ): boolean =>
147
+ queryBuilderState instanceof DataProductQueryBuilderState ||
148
+ queryBuilderState instanceof IngestLegendQueryBuilderState;
149
+
150
+ const getUnsupportedExportActionMessage = (
151
+ queryBuilderState: QueryBuilderState,
152
+ ): string =>
153
+ isDataProductOrIngestQuery(queryBuilderState)
154
+ ? 'Not supported for Data Product or Ingest queries'
155
+ : 'Requires saved query';
156
+
144
157
  export const QUERY_DATACUBE_USAGE_TITLE = 'Legend DataCube';
145
158
  const QUERY_DATACUBE_SOURCE_TYPE = 'legendQuery';
146
159
 
@@ -387,6 +400,9 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
387
400
  title: 'Promote Curated Template query...',
388
401
  label: 'Curated Template Query',
389
402
  disableFunc: (queryBuilderState): boolean => {
403
+ if (isDataProductOrIngestQuery(queryBuilderState)) {
404
+ return true;
405
+ }
390
406
  if (
391
407
  queryBuilderState.workflowState.actionConfig instanceof
392
408
  QueryBuilderActionConfig_QueryApplication
@@ -463,13 +479,16 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
463
479
  }
464
480
  },
465
481
  icon: <ArrowCircleUpIcon />,
466
- disableMessage: 'Requires saved query',
482
+ getDisableMessage: getUnsupportedExportActionMessage,
467
483
  },
468
484
  {
469
485
  key: 'legend-datacube-query',
470
486
  title: 'Launch Legend DataCube...',
471
487
  label: 'Legend DataCube',
472
488
  disableFunc: (queryBuilderState): boolean => {
489
+ if (isDataProductOrIngestQuery(queryBuilderState)) {
490
+ return true;
491
+ }
473
492
  if (
474
493
  queryBuilderState.workflowState.actionConfig instanceof
475
494
  QueryBuilderActionConfig_QueryApplication
@@ -515,7 +534,7 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
515
534
  }
516
535
  },
517
536
  icon: <CubeIcon />,
518
- disableMessage: 'Requires saved query',
537
+ getDisableMessage: getUnsupportedExportActionMessage,
519
538
  },
520
539
  ];
521
540
  }
package/src/index.ts CHANGED
@@ -21,7 +21,12 @@ export * from './application/LegendQueryPluginManager.js';
21
21
 
22
22
  export * from './__lib__/LegendQueryEvent.js';
23
23
  export * from './__lib__/LegendQueryEventHelper.js';
24
- export { LegendQueryTelemetryHelper } from './__lib__/LegendQueryTelemetryHelper.js';
24
+ export {
25
+ LegendQueryTelemetryHelper,
26
+ type InitializeQueryCreator_TelemetryData,
27
+ type InitializeQueryCreatorFailure_TelemetryData,
28
+ } from './__lib__/LegendQueryTelemetryHelper.js';
29
+ export * from './__lib__/LegendQuerySourceInfo.js';
25
30
  export { LegendQueryAgentChatTelemetryHelper } from './__lib__/LegendQueryAgentChatTelemetryHelper.js';
26
31
  export {
27
32
  generateExistingQueryEditorRoute,
@@ -22,10 +22,10 @@ import { BaseQuerySetupStore } from './QuerySetupStore.js';
22
22
  import type { DepotServerClient } from '@finos/legend-server-depot';
23
23
  import { quantifyList } from '@finos/legend-shared';
24
24
  import { LegendQueryUserDataHelper } from '../__lib__/LegendQueryUserDataHelper.js';
25
+ import { buildQueryLoaderLifecycleTelemetryHandlers } from '../__lib__/LegendQueryLifecycleTelemetry.js';
25
26
  import type { LegendQueryApplicationStore } from './LegendQueryBaseStore.js';
26
27
  import { QuerySearchSpecification, type LightQuery } from '@finos/legend-graph';
27
28
  import { generateExistingQueryEditorRoute } from '../__lib__/LegendQueryNavigation.js';
28
- import { LegendQueryTelemetryHelper } from '../__lib__/LegendQueryTelemetryHelper.js';
29
29
 
30
30
  export class EditExistingQuerySetupStore extends BaseQuerySetupStore {
31
31
  readonly queryLoaderState: QueryLoaderState;
@@ -74,25 +74,13 @@ export class EditExistingQuerySetupStore extends BaseQuerySetupStore {
74
74
  'recently viewed queries',
75
75
  )}`
76
76
  : `No recently viewed queries`,
77
- onQueryDeleted: (queryId): void =>
78
- LegendQueryUserDataHelper.removeRecentlyViewedQuery(
79
- this.applicationStore.userDataService,
80
- queryId,
81
- ),
82
- onQueryRenamed: (query): void => {
83
- LegendQueryTelemetryHelper.logEvent_RenameQuerySucceeded(
84
- applicationStore.telemetryService,
85
- {
86
- query: {
87
- id: query.id,
88
- name: query.name,
89
- groupId: query.groupId,
90
- artifactId: query.artifactId,
91
- versionId: query.versionId,
92
- },
93
- },
94
- );
95
- },
77
+ ...buildQueryLoaderLifecycleTelemetryHandlers(this.applicationStore, {
78
+ onQueryDeleted: (queryId): void =>
79
+ LegendQueryUserDataHelper.removeRecentlyViewedQuery(
80
+ this.applicationStore.userDataService,
81
+ queryId,
82
+ ),
83
+ }),
96
84
  handleFetchDefaultQueriesFailure: (): void =>
97
85
  LegendQueryUserDataHelper.removeRecentlyViewedQueries(
98
86
  this.applicationStore.userDataService,