@adminforth/dashboard 1.3.0 → 1.4.1

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 (80) hide show
  1. package/README.md +103 -15
  2. package/custom/api/dashboardApi.ts +9 -8
  3. package/custom/model/dashboard.types.ts +63 -270
  4. package/custom/model/dashboardTopics.ts +5 -0
  5. package/custom/runtime/DashboardGroup.vue +2 -2
  6. package/custom/runtime/DashboardPage.vue +17 -7
  7. package/custom/runtime/DashboardRuntime.vue +20 -8
  8. package/custom/runtime/WidgetRenderer.vue +1 -2
  9. package/custom/runtime/WidgetShell.vue +3 -3
  10. package/custom/skills/adminforth-dashboard/SKILL.md +110 -3
  11. package/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  12. package/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  13. package/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  14. package/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  15. package/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  16. package/custom/widgets/chart/ChartWidget.vue +24 -18
  17. package/{dist/custom/widgets/chart/funnel → custom/widgets/chart}/FunnelChart.vue +80 -78
  18. package/{dist/custom/widgets/chart/line → custom/widgets/chart}/LineChart.vue +2 -2
  19. package/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  20. package/{dist/custom/widgets/chart/stacked-bar → custom/widgets/chart}/StackedBarChart.vue +97 -95
  21. package/custom/widgets/chart/chart.types.ts +0 -28
  22. package/dist/custom/api/dashboardApi.d.ts +4 -7
  23. package/dist/custom/api/dashboardApi.js +5 -0
  24. package/dist/custom/api/dashboardApi.ts +9 -8
  25. package/dist/custom/model/dashboard.types.d.ts +40 -31
  26. package/dist/custom/model/dashboard.types.js +13 -152
  27. package/dist/custom/model/dashboard.types.ts +63 -270
  28. package/dist/custom/model/dashboardTopics.d.ts +2 -0
  29. package/dist/custom/model/dashboardTopics.js +8 -0
  30. package/dist/custom/model/dashboardTopics.ts +5 -0
  31. package/dist/custom/queries/useDashboardConfig.d.ts +116 -96
  32. package/dist/custom/queries/useWidgetData.d.ts +116 -96
  33. package/dist/custom/runtime/DashboardGroup.vue +2 -2
  34. package/dist/custom/runtime/DashboardPage.vue +17 -7
  35. package/dist/custom/runtime/DashboardRuntime.vue +20 -8
  36. package/dist/custom/runtime/WidgetRenderer.vue +1 -2
  37. package/dist/custom/runtime/WidgetShell.vue +3 -3
  38. package/dist/custom/skills/adminforth-dashboard/SKILL.md +110 -3
  39. package/dist/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  40. package/dist/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  41. package/dist/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  42. package/dist/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  43. package/dist/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  44. package/dist/custom/widgets/chart/ChartWidget.vue +24 -18
  45. package/{custom/widgets/chart/funnel → dist/custom/widgets/chart}/FunnelChart.vue +80 -78
  46. package/{custom/widgets/chart/line → dist/custom/widgets/chart}/LineChart.vue +2 -2
  47. package/dist/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  48. package/{custom/widgets/chart/stacked-bar → dist/custom/widgets/chart}/StackedBarChart.vue +97 -95
  49. package/dist/custom/widgets/chart/chart.types.d.ts +0 -2
  50. package/dist/custom/widgets/chart/chart.types.js +0 -23
  51. package/dist/custom/widgets/chart/chart.types.ts +0 -28
  52. package/dist/endpoint/dashboard.d.ts +6 -2
  53. package/dist/endpoint/dashboard.js +29 -5
  54. package/dist/endpoint/groups.d.ts +2 -21
  55. package/dist/endpoint/groups.js +18 -16
  56. package/dist/endpoint/widgets.d.ts +2 -4
  57. package/dist/endpoint/widgets.js +28 -74
  58. package/dist/index.js +1 -3
  59. package/dist/schema/api.d.ts +2172 -500
  60. package/dist/schema/api.js +21 -13
  61. package/dist/schema/widget.d.ts +1076 -263
  62. package/dist/schema/widget.js +108 -49
  63. package/dist/services/dashboardConfigService.d.ts +0 -10
  64. package/dist/services/dashboardConfigService.js +6 -21
  65. package/dist/services/widgetDataService.d.ts +2 -1
  66. package/dist/services/widgetDataService.js +266 -206
  67. package/endpoint/dashboard.ts +47 -7
  68. package/endpoint/groups.ts +25 -42
  69. package/endpoint/widgets.ts +41 -96
  70. package/index.ts +0 -3
  71. package/package.json +3 -3
  72. package/schema/api.ts +23 -13
  73. package/schema/widget.ts +119 -55
  74. package/services/dashboardConfigService.ts +6 -25
  75. package/services/widgetDataService.ts +350 -237
  76. package/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  77. package/dist/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  78. package/dist/services/widgetConfigValidator.d.ts +0 -8
  79. package/dist/services/widgetConfigValidator.js +0 -27
  80. package/services/widgetConfigValidator.ts +0 -61
package/schema/widget.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  import { z } from 'zod'
2
-
3
- export type DashboardWidgetConfigValidationError = {
4
- field: string
5
- message: string
6
- }
7
-
2
+ export type { DashboardWidgetConfigValidationError } from '../custom/model/dashboard.types.js'
8
3
  const DashboardWidgetSizeSchema = z.enum([
9
4
  'small',
10
5
  'medium',
@@ -38,6 +33,15 @@ const FieldRefSchema = z.union([
38
33
  }).strict(),
39
34
  ])
40
35
 
36
+ const JsonValueSchema: z.ZodType = z.lazy(() => z.union([
37
+ z.string(),
38
+ z.number(),
39
+ z.boolean(),
40
+ z.null(),
41
+ z.array(JsonValueSchema),
42
+ z.record(z.string(), JsonValueSchema),
43
+ ]))
44
+
41
45
  const FilterExpressionSchema: z.ZodType = z.lazy(() => z.union([
42
46
  z.array(FilterExpressionSchema),
43
47
  z.object({
@@ -48,16 +52,16 @@ const FilterExpressionSchema: z.ZodType = z.lazy(() => z.union([
48
52
  }).strict(),
49
53
  z.object({
50
54
  field: z.string(),
51
- eq: z.unknown().optional(),
52
- neq: z.unknown().optional(),
53
- gt: z.unknown().optional(),
54
- gte: z.unknown().optional(),
55
- lt: z.unknown().optional(),
56
- lte: z.unknown().optional(),
57
- in: z.array(z.unknown()).optional(),
58
- not_in: z.array(z.unknown()).optional(),
59
- like: z.unknown().optional(),
60
- ilike: z.unknown().optional(),
55
+ eq: JsonValueSchema.optional(),
56
+ neq: JsonValueSchema.optional(),
57
+ gt: JsonValueSchema.optional(),
58
+ gte: JsonValueSchema.optional(),
59
+ lt: JsonValueSchema.optional(),
60
+ lte: JsonValueSchema.optional(),
61
+ in: z.array(JsonValueSchema).optional(),
62
+ not_in: z.array(JsonValueSchema).optional(),
63
+ like: JsonValueSchema.optional(),
64
+ ilike: JsonValueSchema.optional(),
61
65
  }).strict(),
62
66
  ]))
63
67
 
@@ -74,7 +78,7 @@ const QueryAggregateOperationSchema = z.enum([
74
78
  const QueryFieldSelectItemSchema = z.object({
75
79
  field: z.string(),
76
80
  as: z.string().optional(),
77
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']).optional(),
81
+ grain: z.enum(['day', 'week', 'month', 'year']).optional(),
78
82
  }).strict()
79
83
 
80
84
  const QueryAggregateSelectItemSchema = z.object({
@@ -85,7 +89,7 @@ const QueryAggregateSelectItemSchema = z.object({
85
89
  }).strict().superRefine((item, ctx) => {
86
90
  if (!['count'].includes(item.agg) && !item.field) {
87
91
  ctx.addIssue({
88
- code: z.ZodIssueCode.custom,
92
+ code: 'custom',
89
93
  path: ['field'],
90
94
  message: `field is required for ${item.agg}`,
91
95
  })
@@ -108,7 +112,7 @@ const QueryGroupByItemSchema = z.union([
108
112
  z.object({
109
113
  field: z.string(),
110
114
  as: z.string().optional(),
111
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']).optional(),
115
+ grain: z.enum(['day', 'week', 'month', 'year']).optional(),
112
116
  timezone: z.string().optional(),
113
117
  }).strict(),
114
118
  ])
@@ -120,14 +124,14 @@ const QueryOrderByItemSchema = z.object({
120
124
 
121
125
  const TimeSeriesConfigSchema = z.object({
122
126
  field: z.string(),
123
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']),
127
+ grain: z.enum(['day', 'week', 'month', 'year']),
124
128
  timezone: z.string().optional(),
125
129
  }).strict()
126
130
 
127
131
  const PeriodConfigSchema = z.object({
128
132
  field: z.string(),
129
- gte: z.unknown().optional(),
130
- lt: z.unknown().optional(),
133
+ gte: JsonValueSchema.optional(),
134
+ lt: JsonValueSchema.optional(),
131
135
  }).strict()
132
136
 
133
137
  const BucketConfigSchema = z.object({
@@ -144,17 +148,18 @@ const QueryCalcItemSchema = z.object({
144
148
  as: z.string(),
145
149
  }).strict()
146
150
 
147
- const FormattingConfigSchema = z.record(z.string(), z.unknown())
151
+ const FormattingConfigSchema = z.record(z.string(), JsonValueSchema)
152
+ const VariablesConfigSchema = z.record(z.string(), JsonValueSchema)
148
153
 
149
154
  export const QueryConfigSchema = z.object({
150
155
  resource: z.string(),
151
156
  select: z.array(QuerySelectItemSchema).optional(),
152
157
  filters: FilterExpressionSchema.optional(),
153
- groupBy: z.array(QueryGroupByItemSchema).optional(),
154
- orderBy: z.array(QueryOrderByItemSchema).optional(),
158
+ group_by: z.array(QueryGroupByItemSchema).optional(),
159
+ order_by: z.array(QueryOrderByItemSchema).optional(),
155
160
  limit: z.number().int().positive().optional(),
156
161
  offset: z.number().int().nonnegative().optional(),
157
- timeSeries: TimeSeriesConfigSchema.optional(),
162
+ time_series: TimeSeriesConfigSchema.optional(),
158
163
  period: PeriodConfigSchema.optional(),
159
164
  bucket: BucketConfigSchema.optional(),
160
165
  calcs: z.array(QueryCalcItemSchema).optional(),
@@ -170,29 +175,34 @@ const FunnelQueryStepSchema = z.object({
170
175
 
171
176
  export const FunnelQueryConfigSchema = z.object({
172
177
  steps: z.array(FunnelQueryStepSchema).min(1),
178
+ calcs: z.array(QueryCalcItemSchema).optional(),
173
179
  }).strict()
174
180
 
175
- const WidgetBaseSchema = z.object({
176
- id: z.string().optional(),
177
- group_id: z.string().optional(),
181
+ const EditableWidgetBaseSchema = z.object({
178
182
  label: z.string().optional(),
183
+ variables: VariablesConfigSchema.optional(),
179
184
  size: DashboardWidgetSizeSchema.optional(),
180
185
  width: z.number().positive('Width must be greater than 0').optional(),
181
186
  height: z.number().positive('Height must be greater than 0').optional(),
182
- minWidth: z.number().nonnegative('Min width must be a non-negative number').optional(),
183
- maxWidth: z.number().nonnegative('Max width must be a non-negative number').nullable().optional(),
184
- order: z.number().optional(),
187
+ min_width: z.number().nonnegative('Min width must be a non-negative number').optional(),
188
+ max_width: z.number().nonnegative('Max width must be a non-negative number').nullable().optional(),
189
+ }).strict()
190
+
191
+ const StoredWidgetBaseSchema = EditableWidgetBaseSchema.extend({
192
+ id: z.string(),
193
+ group_id: z.string(),
194
+ order: z.number(),
185
195
  })
186
196
 
187
197
  const TableViewConfigSchema = z.object({
188
198
  columns: z.array(FieldRefSchema).optional(),
189
199
  pagination: z.boolean().optional(),
190
- pageSize: z.number().int().positive().optional(),
200
+ page_size: z.number().int().positive().optional(),
191
201
  }).strict()
192
202
 
193
203
  const ChartBaseSchema = z.object({
194
204
  title: z.string().optional(),
195
- })
205
+ }).strict()
196
206
 
197
207
  const ChartBucketSchema = z.object({
198
208
  label: z.string().min(1, 'Bucket label is required'),
@@ -224,8 +234,8 @@ const BarChartSchema = ChartBaseSchema.extend({
224
234
  const StackedBarChartSchema = ChartBaseSchema.extend({
225
235
  type: z.literal('stacked_bar'),
226
236
  x: ChartFieldRefSchema,
227
- y: ChartFieldRefSchema,
228
- series: ChartSeriesRefSchema,
237
+ y: z.union([ChartFieldRefSchema, z.array(ChartFieldRefSchema).min(1)]),
238
+ series: ChartSeriesRefSchema.optional(),
229
239
  colors: z.array(z.string()).optional(),
230
240
  })
231
241
 
@@ -272,8 +282,8 @@ const KpiCardViewConfigSchema = z.object({
272
282
  text: z.string().optional(),
273
283
  field: z.string().optional(),
274
284
  }).strict().optional(),
275
- comparison: z.unknown().optional(),
276
- sparkline: z.unknown().optional(),
285
+ comparison: JsonValueSchema.optional(),
286
+ sparkline: JsonValueSchema.optional(),
277
287
  }).strict()
278
288
 
279
289
  const GaugeCardViewConfigSchema = z.object({
@@ -290,9 +300,9 @@ const GaugeCardViewConfigSchema = z.object({
290
300
  label: z.string().optional(),
291
301
  }).strict().optional(),
292
302
  progress: z.object({
293
- valueField: z.string(),
294
- targetValue: z.number().optional(),
295
- targetField: z.string().optional(),
303
+ value_field: z.string(),
304
+ target_value: z.number().optional(),
305
+ target_field: z.string().optional(),
296
306
  format: ValueFormatSchema,
297
307
  }).strict().optional(),
298
308
  color: z.string().optional(),
@@ -309,17 +319,27 @@ const PivotTableViewConfigSchema = z.object({
309
319
  }).strict()).min(1),
310
320
  }).strict()
311
321
 
312
- export const EmptyWidgetConfigSchema = WidgetBaseSchema.extend({
322
+ const EditableEmptyWidgetConfigSchema = EditableWidgetBaseSchema.extend({
323
+ target: z.literal('empty'),
324
+ })
325
+
326
+ export const EmptyWidgetConfigSchema = StoredWidgetBaseSchema.extend({
313
327
  target: z.literal('empty'),
314
328
  })
315
329
 
316
- const TableWidgetConfigSchema = WidgetBaseSchema.extend({
330
+ const EditableTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
317
331
  target: z.literal('table'),
318
332
  table: TableViewConfigSchema.optional(),
319
333
  query: QueryConfigSchema,
320
334
  })
321
335
 
322
- const ChartWidgetTargetConfigSchema = WidgetBaseSchema.extend({
336
+ const TableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
337
+ target: z.literal('table'),
338
+ table: TableViewConfigSchema.optional(),
339
+ query: QueryConfigSchema,
340
+ })
341
+
342
+ const EditableChartWidgetTargetConfigSchema = EditableWidgetBaseSchema.extend({
323
343
  target: z.literal('chart'),
324
344
  chart: ChartConfigSchema,
325
345
  query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
@@ -327,39 +347,83 @@ const ChartWidgetTargetConfigSchema = WidgetBaseSchema.extend({
327
347
  const isFunnelChart = widget.chart.type === 'funnel'
328
348
  const isFunnelQuery = 'steps' in widget.query
329
349
 
330
- if (isFunnelChart !== isFunnelQuery) {
350
+ if (isFunnelChart && !isFunnelQuery) {
331
351
  ctx.addIssue({
332
- code: z.ZodIssueCode.custom,
352
+ code: 'custom',
333
353
  path: ['query'],
334
- message: 'Funnel charts must use steps query, other charts must use resource query',
354
+ message: 'Funnel charts must use steps query',
335
355
  })
336
356
  }
337
357
  })
338
358
 
339
- const KpiCardWidgetConfigSchema = WidgetBaseSchema.extend({
359
+ const ChartWidgetTargetConfigSchema = StoredWidgetBaseSchema.extend({
360
+ target: z.literal('chart'),
361
+ chart: ChartConfigSchema,
362
+ query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
363
+ }).superRefine((widget, ctx) => {
364
+ const isFunnelChart = widget.chart.type === 'funnel'
365
+ const isFunnelQuery = 'steps' in widget.query
366
+
367
+ if (isFunnelChart && !isFunnelQuery) {
368
+ ctx.addIssue({
369
+ code: 'custom',
370
+ path: ['query'],
371
+ message: 'Funnel charts must use steps query',
372
+ })
373
+ }
374
+ })
375
+
376
+ const EditableKpiCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
377
+ target: z.literal('kpi_card'),
378
+ card: KpiCardViewConfigSchema,
379
+ query: QueryConfigSchema,
380
+ })
381
+
382
+ const KpiCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
340
383
  target: z.literal('kpi_card'),
341
384
  card: KpiCardViewConfigSchema,
342
385
  query: QueryConfigSchema,
343
386
  })
344
387
 
345
- const GaugeCardWidgetConfigSchema = WidgetBaseSchema.extend({
388
+ const EditableGaugeCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
346
389
  target: z.literal('gauge_card'),
347
390
  card: GaugeCardViewConfigSchema,
348
391
  query: QueryConfigSchema,
349
392
  })
350
393
 
351
- const PivotTableWidgetConfigSchema = WidgetBaseSchema.extend({
394
+ const GaugeCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
395
+ target: z.literal('gauge_card'),
396
+ card: GaugeCardViewConfigSchema,
397
+ query: QueryConfigSchema,
398
+ })
399
+
400
+ const EditablePivotTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
352
401
  target: z.literal('pivot_table'),
353
402
  pivot: PivotTableViewConfigSchema,
354
403
  query: QueryConfigSchema,
355
404
  })
356
405
 
406
+ const PivotTableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
407
+ target: z.literal('pivot_table'),
408
+ pivot: PivotTableViewConfigSchema,
409
+ query: QueryConfigSchema,
410
+ })
411
+
412
+ export const EditableDashboardWidgetConfigSchema = z.discriminatedUnion('target', [
413
+ EditableEmptyWidgetConfigSchema,
414
+ EditableTableWidgetConfigSchema,
415
+ EditableChartWidgetTargetConfigSchema,
416
+ EditableKpiCardWidgetConfigSchema,
417
+ EditableGaugeCardWidgetConfigSchema,
418
+ EditablePivotTableWidgetConfigSchema,
419
+ ])
420
+
357
421
  export const WidgetConfigSchema = z.discriminatedUnion('target', [
358
- TableWidgetConfigSchema,
359
- ChartWidgetTargetConfigSchema,
360
- KpiCardWidgetConfigSchema,
361
- GaugeCardWidgetConfigSchema,
362
- PivotTableWidgetConfigSchema,
422
+ EditableTableWidgetConfigSchema,
423
+ EditableChartWidgetTargetConfigSchema,
424
+ EditableKpiCardWidgetConfigSchema,
425
+ EditableGaugeCardWidgetConfigSchema,
426
+ EditablePivotTableWidgetConfigSchema,
363
427
  ])
364
428
 
365
429
  export const StoredWidgetConfigSchema = z.discriminatedUnion('target', [
@@ -1,9 +1,8 @@
1
1
  import { Filters } from 'adminforth';
2
2
  import type { IAdminForth } from 'adminforth';
3
- import { normalizeDashboardConfig } from '../custom/model/dashboard.types.js';
4
3
  import type { DashboardConfig, DashboardWidgetConfig } from '../custom/model/dashboard.types.js';
5
-
6
- const DASHBOARD_CONFIG_UPDATED_TOPIC_PREFIX = '/opentopic/dashboard-config-updated';
4
+ import { getDashboardConfigUpdatedTopic } from '../custom/model/dashboardTopics.js';
5
+ import { DashboardConfigZodSchema } from '../schema/api.js';
7
6
 
8
7
  export type DashboardRecord = {
9
8
  id: string;
@@ -14,21 +13,9 @@ export type DashboardRecord = {
14
13
  };
15
14
 
16
15
  export function parseStoredDashboardConfig(config: unknown): DashboardConfig {
17
- if (typeof config === 'string') {
18
- return normalizeDashboardConfig(JSON.parse(config));
19
- }
16
+ const parsedConfig = typeof config === 'string' ? JSON.parse(config) : config;
20
17
 
21
- return normalizeDashboardConfig(config);
22
- }
23
-
24
- export function buildDashboardResponse(dashboard: DashboardRecord) {
25
- return {
26
- id: dashboard.id,
27
- slug: dashboard.slug,
28
- label: dashboard.label,
29
- revision: dashboard.revision,
30
- config: parseStoredDashboardConfig(dashboard.config),
31
- };
18
+ return DashboardConfigZodSchema.parse(parsedConfig) as DashboardConfig;
32
19
  }
33
20
 
34
21
  export type PersistedDashboardResponse = {
@@ -39,11 +26,7 @@ export type PersistedDashboardResponse = {
39
26
  config: DashboardConfig;
40
27
  };
41
28
 
42
- export function dashboardConfigUpdatedTopic(slug: string) {
43
- return `${DASHBOARD_CONFIG_UPDATED_TOPIC_PREFIX}/${slug}`;
44
- }
45
-
46
- export function normalizeDashboardOrder(config: DashboardConfig): DashboardConfig {
29
+ function normalizeDashboardOrder(config: DashboardConfig): DashboardConfig {
47
30
  const widgetsByGroupId = new Map<string, DashboardWidgetConfig[]>();
48
31
 
49
32
  for (const widget of config.widgets) {
@@ -93,7 +76,7 @@ export async function persistDashboardConfig(
93
76
  revision: dashboard.revision + 1,
94
77
  });
95
78
 
96
- await adminforth.websocket.publish(dashboardConfigUpdatedTopic(dashboard.slug), {
79
+ await adminforth.websocket.publish(getDashboardConfigUpdatedTopic(dashboard.slug), {
97
80
  id: dashboard.id,
98
81
  slug: dashboard.slug,
99
82
  revision: dashboard.revision + 1,
@@ -115,7 +98,6 @@ export type DashboardConfigService = {
115
98
  dashboard: DashboardRecord,
116
99
  config: DashboardConfig,
117
100
  ) => Promise<PersistedDashboardResponse>;
118
- buildDashboardResponse: typeof buildDashboardResponse;
119
101
  };
120
102
 
121
103
  export function createDashboardConfigService(
@@ -131,6 +113,5 @@ export function createDashboardConfigService(
131
113
  dashboard,
132
114
  config,
133
115
  ),
134
- buildDashboardResponse,
135
116
  };
136
117
  }