datajunction-ui 0.0.43 → 0.0.45

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.
@@ -172,6 +172,12 @@ export const DataJunctionAPI = {
172
172
  cubeDimensions {
173
173
  name
174
174
  }
175
+ availability {
176
+ catalog
177
+ schema_
178
+ table
179
+ validThroughTs
180
+ }
175
181
  materializations {
176
182
  name
177
183
  config
@@ -195,6 +201,11 @@ export const DataJunctionAPI = {
195
201
  })
196
202
  ).json();
197
203
 
204
+ if (result.errors) {
205
+ console.error('GraphQL errors:', result.errors);
206
+ return null;
207
+ }
208
+
198
209
  const node = result?.data?.findNodes?.[0];
199
210
  if (!node) {
200
211
  return null;
@@ -228,6 +239,7 @@ export const DataJunctionAPI = {
228
239
  cube_node_metrics: cubeMetrics,
229
240
  cube_node_dimensions: cubeDimensions,
230
241
  cubeMaterialization, // Included so we don't need a second fetch
242
+ availability: current.availability || null,
231
243
  };
232
244
  } catch (err) {
233
245
  console.error('Failed to fetch cube via GraphQL:', err);
@@ -1169,15 +1181,26 @@ export const DataJunctionAPI = {
1169
1181
  ).json();
1170
1182
  },
1171
1183
 
1172
- data: async function (metricSelection, dimensionSelection) {
1184
+ data: async function (metricSelection, dimensionSelection, filters = []) {
1173
1185
  const params = new URLSearchParams();
1174
1186
  metricSelection.map(metric => params.append('metrics', metric));
1175
1187
  dimensionSelection.map(dimension => params.append('dimensions', dimension));
1176
- return await (
1177
- await fetch(`${DJ_URL}/data/?` + params + '&limit=10000', {
1178
- credentials: 'include',
1179
- })
1180
- ).json();
1188
+ if (filters && filters.length > 0) {
1189
+ filters.forEach(f => params.append('filters', f));
1190
+ }
1191
+ params.append('limit', '10000');
1192
+ const response = await fetch(`${DJ_URL}/data/?${params}`, {
1193
+ credentials: 'include',
1194
+ });
1195
+ if (!response.ok) {
1196
+ const errorData = await response.json().catch(() => ({}));
1197
+ throw new Error(
1198
+ errorData.message ||
1199
+ errorData.detail ||
1200
+ `Query failed: ${response.status}`,
1201
+ );
1202
+ }
1203
+ return await response.json();
1181
1204
  },
1182
1205
 
1183
1206
  nodeData: async function (nodeName, selection = null) {
@@ -2278,6 +2278,7 @@ describe('DataJunctionAPI', () => {
2278
2278
  timestampColumn: 'ts',
2279
2279
  timestampFormat: 'yyyy-MM-dd',
2280
2280
  },
2281
+ availability: null,
2281
2282
  });
2282
2283
  });
2283
2284
 
@@ -2773,4 +2774,166 @@ describe('DataJunctionAPI', () => {
2773
2774
  expect(result._error).toBe(true);
2774
2775
  expect(result.message).toBeDefined();
2775
2776
  });
2777
+
2778
+ // Namespace sources tests
2779
+ it('calls namespaceSources correctly', async () => {
2780
+ fetch.mockResponseOnce(
2781
+ JSON.stringify({ primary_source: { type: 'git', repository: 'repo' } }),
2782
+ );
2783
+ const result = await DataJunctionAPI.namespaceSources('default');
2784
+ expect(fetch).toHaveBeenCalledWith(
2785
+ 'http://localhost:8000/namespaces/default/sources',
2786
+ { credentials: 'include' },
2787
+ );
2788
+ expect(result.primary_source.type).toBe('git');
2789
+ });
2790
+
2791
+ it('calls namespaceSourcesBulk correctly', async () => {
2792
+ fetch.mockResponseOnce(
2793
+ JSON.stringify({
2794
+ default: { primary_source: { type: 'git' } },
2795
+ other: { primary_source: { type: 'local' } },
2796
+ }),
2797
+ );
2798
+ const result = await DataJunctionAPI.namespaceSourcesBulk([
2799
+ 'default',
2800
+ 'other',
2801
+ ]);
2802
+ expect(fetch).toHaveBeenCalledWith(
2803
+ 'http://localhost:8000/namespaces/sources/bulk',
2804
+ {
2805
+ method: 'POST',
2806
+ headers: { 'Content-Type': 'application/json' },
2807
+ body: JSON.stringify({ namespaces: ['default', 'other'] }),
2808
+ credentials: 'include',
2809
+ },
2810
+ );
2811
+ });
2812
+
2813
+ it('calls listDeployments correctly', async () => {
2814
+ fetch.mockResponseOnce(
2815
+ JSON.stringify([{ uuid: '123', status: 'success' }]),
2816
+ );
2817
+ const result = await DataJunctionAPI.listDeployments('default', 10);
2818
+ expect(fetch).toHaveBeenCalledWith(
2819
+ 'http://localhost:8000/deployments?namespace=default&limit=10',
2820
+ { credentials: 'include' },
2821
+ );
2822
+ });
2823
+
2824
+ it('calls listDeployments without namespace', async () => {
2825
+ fetch.mockResponseOnce(JSON.stringify([]));
2826
+ await DataJunctionAPI.listDeployments(null, 5);
2827
+ expect(fetch).toHaveBeenCalledWith(
2828
+ 'http://localhost:8000/deployments?limit=5',
2829
+ { credentials: 'include' },
2830
+ );
2831
+ });
2832
+
2833
+ // Notification/history tests
2834
+ it('calls getSubscribedHistory correctly', async () => {
2835
+ fetch.mockResponseOnce(
2836
+ JSON.stringify([{ id: 1, activity_type: 'create' }]),
2837
+ );
2838
+ const result = await DataJunctionAPI.getSubscribedHistory(20);
2839
+ expect(fetch).toHaveBeenCalledWith(
2840
+ 'http://localhost:8000/history/?only_subscribed=true&limit=20',
2841
+ { credentials: 'include' },
2842
+ );
2843
+ });
2844
+
2845
+ it('calls getSubscribedHistory with default limit', async () => {
2846
+ fetch.mockResponseOnce(JSON.stringify([]));
2847
+ await DataJunctionAPI.getSubscribedHistory();
2848
+ expect(fetch).toHaveBeenCalledWith(
2849
+ 'http://localhost:8000/history/?only_subscribed=true&limit=10',
2850
+ { credentials: 'include' },
2851
+ );
2852
+ });
2853
+
2854
+ it('calls markNotificationsRead correctly', async () => {
2855
+ fetch.mockResponseOnce(JSON.stringify({ marked: 5 }));
2856
+ const result = await DataJunctionAPI.markNotificationsRead();
2857
+ expect(fetch).toHaveBeenCalledWith(
2858
+ 'http://localhost:8000/notifications/mark-read',
2859
+ { method: 'POST', credentials: 'include' },
2860
+ );
2861
+ expect(result.marked).toBe(5);
2862
+ });
2863
+
2864
+ // Service account tests
2865
+ it('calls listServiceAccounts correctly', async () => {
2866
+ fetch.mockResponseOnce(
2867
+ JSON.stringify([{ client_id: 'abc', name: 'test-account' }]),
2868
+ );
2869
+ const result = await DataJunctionAPI.listServiceAccounts();
2870
+ expect(fetch).toHaveBeenCalledWith(
2871
+ 'http://localhost:8000/service-accounts',
2872
+ { credentials: 'include' },
2873
+ );
2874
+ expect(result[0].name).toBe('test-account');
2875
+ });
2876
+
2877
+ it('calls createServiceAccount correctly', async () => {
2878
+ fetch.mockResponseOnce(
2879
+ JSON.stringify({ client_id: 'new-id', name: 'new-account' }),
2880
+ );
2881
+ const result = await DataJunctionAPI.createServiceAccount('new-account');
2882
+ expect(fetch).toHaveBeenCalledWith(
2883
+ 'http://localhost:8000/service-accounts',
2884
+ {
2885
+ method: 'POST',
2886
+ headers: { 'Content-Type': 'application/json' },
2887
+ credentials: 'include',
2888
+ body: JSON.stringify({ name: 'new-account' }),
2889
+ },
2890
+ );
2891
+ expect(result.client_id).toBe('new-id');
2892
+ });
2893
+
2894
+ it('calls deleteServiceAccount correctly', async () => {
2895
+ fetch.mockResponseOnce(JSON.stringify({ deleted: true }));
2896
+ const result = await DataJunctionAPI.deleteServiceAccount('client-123');
2897
+ expect(fetch).toHaveBeenCalledWith(
2898
+ 'http://localhost:8000/service-accounts/client-123',
2899
+ { method: 'DELETE', credentials: 'include' },
2900
+ );
2901
+ expect(result.deleted).toBe(true);
2902
+ });
2903
+
2904
+ // Bulk deactivate preagg workflows tests
2905
+ it('calls bulkDeactivatePreaggWorkflows correctly', async () => {
2906
+ fetch.mockResponseOnce(JSON.stringify({ deactivated: 3 }));
2907
+ const result = await DataJunctionAPI.bulkDeactivatePreaggWorkflows(
2908
+ 'default.metric1',
2909
+ );
2910
+ expect(fetch).toHaveBeenCalledWith(
2911
+ 'http://localhost:8000/preaggs/workflows?node_name=default.metric1',
2912
+ { method: 'DELETE', credentials: 'include' },
2913
+ );
2914
+ expect(result.deactivated).toBe(3);
2915
+ });
2916
+
2917
+ it('calls bulkDeactivatePreaggWorkflows with staleOnly', async () => {
2918
+ fetch.mockResponseOnce(JSON.stringify({ deactivated: 1 }));
2919
+ const result = await DataJunctionAPI.bulkDeactivatePreaggWorkflows(
2920
+ 'default.metric1',
2921
+ true,
2922
+ );
2923
+ expect(fetch).toHaveBeenCalledWith(
2924
+ 'http://localhost:8000/preaggs/workflows?node_name=default.metric1&stale_only=true',
2925
+ { method: 'DELETE', credentials: 'include' },
2926
+ );
2927
+ });
2928
+
2929
+ it('handles bulkDeactivatePreaggWorkflows error', async () => {
2930
+ fetch.mockResponseOnce(JSON.stringify({ detail: 'Not found' }), {
2931
+ status: 404,
2932
+ });
2933
+ const result = await DataJunctionAPI.bulkDeactivatePreaggWorkflows(
2934
+ 'default.metric1',
2935
+ );
2936
+ expect(result._error).toBe(true);
2937
+ expect(result._status).toBe(404);
2938
+ });
2776
2939
  });