@stellaris/metrics-shared 0.1.0

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/index.d.ts ADDED
@@ -0,0 +1,874 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ export type ReportStatus = "draft" | "published" | "archived";
4
+ declare const app: import("hono/hono-base").HonoBase<{}, ({
5
+ "*": {};
6
+ } & {
7
+ "/health": {
8
+ $get: {
9
+ input: {};
10
+ output: {
11
+ status: string;
12
+ };
13
+ outputFormat: "json";
14
+ status: import("hono/utils/http-status").ContentfulStatusCode;
15
+ };
16
+ };
17
+ }) | import("hono/types").MergeSchemaPath<{
18
+ "*": {};
19
+ } & {
20
+ "/": {
21
+ $post: {
22
+ input: {
23
+ json: {
24
+ name: string;
25
+ description?: string | undefined;
26
+ };
27
+ };
28
+ output: {
29
+ id: string;
30
+ name: string;
31
+ description: string | null;
32
+ createdAt: string;
33
+ updatedAt: string;
34
+ };
35
+ outputFormat: "json";
36
+ status: 201;
37
+ };
38
+ };
39
+ } & {
40
+ "/": {
41
+ $get: {
42
+ input: {
43
+ query: {
44
+ search?: string | string[] | undefined;
45
+ skip?: string | string[] | undefined;
46
+ take?: string | string[] | undefined;
47
+ };
48
+ };
49
+ output: {
50
+ id: string;
51
+ name: string;
52
+ description: string | null;
53
+ createdAt: string;
54
+ updatedAt: string;
55
+ }[];
56
+ outputFormat: "json";
57
+ status: import("hono/utils/http-status").ContentfulStatusCode;
58
+ };
59
+ };
60
+ } & {
61
+ "/:id": {
62
+ $get: {
63
+ input: {
64
+ param: {
65
+ id: string;
66
+ };
67
+ };
68
+ output: {
69
+ error: string;
70
+ };
71
+ outputFormat: "json";
72
+ status: 404;
73
+ } | {
74
+ input: {
75
+ param: {
76
+ id: string;
77
+ };
78
+ };
79
+ output: {
80
+ id: string;
81
+ name: string;
82
+ description: string | null;
83
+ createdAt: string;
84
+ updatedAt: string;
85
+ };
86
+ outputFormat: "json";
87
+ status: import("hono/utils/http-status").ContentfulStatusCode;
88
+ };
89
+ };
90
+ } & {
91
+ "/by-name/:name": {
92
+ $get: {
93
+ input: {
94
+ param: {
95
+ name: string;
96
+ };
97
+ };
98
+ output: {
99
+ id: string;
100
+ name: string;
101
+ description: string | null;
102
+ createdAt: string;
103
+ updatedAt: string;
104
+ };
105
+ outputFormat: "json";
106
+ status: import("hono/utils/http-status").ContentfulStatusCode;
107
+ } | {
108
+ input: {
109
+ param: {
110
+ name: string;
111
+ };
112
+ };
113
+ output: {
114
+ error: string;
115
+ };
116
+ outputFormat: "json";
117
+ status: 404;
118
+ };
119
+ };
120
+ } & {
121
+ "/:id": {
122
+ $patch: {
123
+ input: {
124
+ json: {
125
+ name?: string | undefined;
126
+ description?: string | null | undefined;
127
+ };
128
+ } & {
129
+ param: {
130
+ id: string;
131
+ };
132
+ };
133
+ output: {
134
+ id: string;
135
+ name: string;
136
+ description: string | null;
137
+ createdAt: string;
138
+ updatedAt: string;
139
+ };
140
+ outputFormat: "json";
141
+ status: import("hono/utils/http-status").ContentfulStatusCode;
142
+ };
143
+ };
144
+ } & {
145
+ "/:id": {
146
+ $delete: {
147
+ input: {
148
+ param: {
149
+ id: string;
150
+ };
151
+ };
152
+ output: {
153
+ success: true;
154
+ };
155
+ outputFormat: "json";
156
+ status: import("hono/utils/http-status").ContentfulStatusCode;
157
+ };
158
+ };
159
+ }, "/api/categories"> | import("hono/types").MergeSchemaPath<{
160
+ "*": {};
161
+ } & {
162
+ "/": {
163
+ $post: {
164
+ input: {
165
+ json: {
166
+ name: string;
167
+ queryConfig: Record<string, unknown>;
168
+ visualConfig: Record<string, unknown>;
169
+ description?: string | undefined;
170
+ categoryId?: string | undefined;
171
+ };
172
+ };
173
+ output: {
174
+ id: string;
175
+ name: string;
176
+ description: string | null;
177
+ categoryId: string | null;
178
+ ownerId: string;
179
+ isArchived: boolean;
180
+ queryConfig: {
181
+ [x: string]: import("hono/utils/types").JSONValue;
182
+ };
183
+ visualConfig: {
184
+ [x: string]: import("hono/utils/types").JSONValue;
185
+ };
186
+ version: number;
187
+ createdAt: string;
188
+ updatedAt: string;
189
+ category?: {
190
+ id: string;
191
+ name: string;
192
+ description: string | null;
193
+ createdAt: string;
194
+ updatedAt: string;
195
+ } | null | undefined;
196
+ };
197
+ outputFormat: "json";
198
+ status: 201;
199
+ };
200
+ };
201
+ } & {
202
+ "/": {
203
+ $get: {
204
+ input: {
205
+ query: {
206
+ ownerId?: string | string[] | undefined;
207
+ categoryId?: string | string[] | undefined;
208
+ isArchived?: string | string[] | undefined;
209
+ search?: string | string[] | undefined;
210
+ skip?: string | string[] | undefined;
211
+ take?: string | string[] | undefined;
212
+ };
213
+ };
214
+ output: {
215
+ id: string;
216
+ name: string;
217
+ description: string | null;
218
+ categoryId: string | null;
219
+ ownerId: string;
220
+ isArchived: boolean;
221
+ queryConfig: {
222
+ [x: string]: import("hono/utils/types").JSONValue;
223
+ };
224
+ visualConfig: {
225
+ [x: string]: import("hono/utils/types").JSONValue;
226
+ };
227
+ version: number;
228
+ createdAt: string;
229
+ updatedAt: string;
230
+ category?: {
231
+ id: string;
232
+ name: string;
233
+ description: string | null;
234
+ createdAt: string;
235
+ updatedAt: string;
236
+ } | null | undefined;
237
+ }[];
238
+ outputFormat: "json";
239
+ status: import("hono/utils/http-status").ContentfulStatusCode;
240
+ };
241
+ };
242
+ } & {
243
+ "/:id": {
244
+ $get: {
245
+ input: {
246
+ param: {
247
+ id: string;
248
+ };
249
+ };
250
+ output: {
251
+ error: string;
252
+ };
253
+ outputFormat: "json";
254
+ status: 404;
255
+ } | {
256
+ input: {
257
+ param: {
258
+ id: string;
259
+ };
260
+ };
261
+ output: {
262
+ id: string;
263
+ name: string;
264
+ description: string | null;
265
+ categoryId: string | null;
266
+ ownerId: string;
267
+ isArchived: boolean;
268
+ queryConfig: {
269
+ [x: string]: import("hono/utils/types").JSONValue;
270
+ };
271
+ visualConfig: {
272
+ [x: string]: import("hono/utils/types").JSONValue;
273
+ };
274
+ version: number;
275
+ createdAt: string;
276
+ updatedAt: string;
277
+ category?: {
278
+ id: string;
279
+ name: string;
280
+ description: string | null;
281
+ createdAt: string;
282
+ updatedAt: string;
283
+ } | null | undefined;
284
+ };
285
+ outputFormat: "json";
286
+ status: import("hono/utils/http-status").ContentfulStatusCode;
287
+ };
288
+ };
289
+ } & {
290
+ "/:id": {
291
+ $patch: {
292
+ input: {
293
+ json: {
294
+ name?: string | undefined;
295
+ description?: string | null | undefined;
296
+ categoryId?: string | null | undefined;
297
+ queryConfig?: Record<string, unknown> | undefined;
298
+ visualConfig?: Record<string, unknown> | undefined;
299
+ expectedVersion?: number | undefined;
300
+ };
301
+ } & {
302
+ param: {
303
+ id: string;
304
+ };
305
+ };
306
+ output: {
307
+ id: string;
308
+ name: string;
309
+ description: string | null;
310
+ categoryId: string | null;
311
+ ownerId: string;
312
+ isArchived: boolean;
313
+ queryConfig: {
314
+ [x: string]: import("hono/utils/types").JSONValue;
315
+ };
316
+ visualConfig: {
317
+ [x: string]: import("hono/utils/types").JSONValue;
318
+ };
319
+ version: number;
320
+ createdAt: string;
321
+ updatedAt: string;
322
+ category?: {
323
+ id: string;
324
+ name: string;
325
+ description: string | null;
326
+ createdAt: string;
327
+ updatedAt: string;
328
+ } | null | undefined;
329
+ };
330
+ outputFormat: "json";
331
+ status: import("hono/utils/http-status").ContentfulStatusCode;
332
+ };
333
+ };
334
+ } & {
335
+ "/:id": {
336
+ $delete: {
337
+ input: {
338
+ param: {
339
+ id: string;
340
+ };
341
+ };
342
+ output: {
343
+ success: true;
344
+ };
345
+ outputFormat: "json";
346
+ status: import("hono/utils/http-status").ContentfulStatusCode;
347
+ };
348
+ };
349
+ } & {
350
+ "/:id/archive": {
351
+ $post: {
352
+ input: {
353
+ param: {
354
+ id: string;
355
+ };
356
+ };
357
+ output: {
358
+ id: string;
359
+ name: string;
360
+ description: string | null;
361
+ categoryId: string | null;
362
+ ownerId: string;
363
+ isArchived: boolean;
364
+ queryConfig: {
365
+ [x: string]: import("hono/utils/types").JSONValue;
366
+ };
367
+ visualConfig: {
368
+ [x: string]: import("hono/utils/types").JSONValue;
369
+ };
370
+ version: number;
371
+ createdAt: string;
372
+ updatedAt: string;
373
+ category?: {
374
+ id: string;
375
+ name: string;
376
+ description: string | null;
377
+ createdAt: string;
378
+ updatedAt: string;
379
+ } | null | undefined;
380
+ };
381
+ outputFormat: "json";
382
+ status: import("hono/utils/http-status").ContentfulStatusCode;
383
+ };
384
+ };
385
+ } & {
386
+ "/:id/unarchive": {
387
+ $post: {
388
+ input: {
389
+ param: {
390
+ id: string;
391
+ };
392
+ };
393
+ output: {
394
+ id: string;
395
+ name: string;
396
+ description: string | null;
397
+ categoryId: string | null;
398
+ ownerId: string;
399
+ isArchived: boolean;
400
+ queryConfig: {
401
+ [x: string]: import("hono/utils/types").JSONValue;
402
+ };
403
+ visualConfig: {
404
+ [x: string]: import("hono/utils/types").JSONValue;
405
+ };
406
+ version: number;
407
+ createdAt: string;
408
+ updatedAt: string;
409
+ category?: {
410
+ id: string;
411
+ name: string;
412
+ description: string | null;
413
+ createdAt: string;
414
+ updatedAt: string;
415
+ } | null | undefined;
416
+ };
417
+ outputFormat: "json";
418
+ status: import("hono/utils/http-status").ContentfulStatusCode;
419
+ };
420
+ };
421
+ }, "/api/metrics"> | import("hono/types").MergeSchemaPath<{
422
+ "*": {};
423
+ } & {
424
+ "/": {
425
+ $post: {
426
+ input: {
427
+ json: {
428
+ title: string;
429
+ layout: Record<string, unknown>;
430
+ description?: string | undefined;
431
+ slug?: string | undefined;
432
+ globalConfig?: Record<string, unknown> | undefined;
433
+ };
434
+ };
435
+ output: {
436
+ id: string;
437
+ slug: string | null;
438
+ title: string;
439
+ description: string | null;
440
+ status: ReportStatus;
441
+ ownerId: string;
442
+ globalConfig: {
443
+ [x: string]: import("hono/utils/types").JSONValue;
444
+ };
445
+ layout: {
446
+ [x: string]: import("hono/utils/types").JSONValue;
447
+ };
448
+ version: number;
449
+ lockOwnerId: string | null;
450
+ lockExpiration: string | null;
451
+ createdAt: string;
452
+ updatedAt: string;
453
+ };
454
+ outputFormat: "json";
455
+ status: 201;
456
+ };
457
+ };
458
+ } & {
459
+ "/": {
460
+ $get: {
461
+ input: {
462
+ query: {
463
+ ownerId?: string | string[] | undefined;
464
+ status?: string | string[] | undefined;
465
+ search?: string | string[] | undefined;
466
+ skip?: string | string[] | undefined;
467
+ take?: string | string[] | undefined;
468
+ };
469
+ };
470
+ output: {
471
+ id: string;
472
+ slug: string | null;
473
+ title: string;
474
+ description: string | null;
475
+ status: ReportStatus;
476
+ ownerId: string;
477
+ globalConfig: {
478
+ [x: string]: import("hono/utils/types").JSONValue;
479
+ };
480
+ layout: {
481
+ [x: string]: import("hono/utils/types").JSONValue;
482
+ };
483
+ version: number;
484
+ lockOwnerId: string | null;
485
+ lockExpiration: string | null;
486
+ createdAt: string;
487
+ updatedAt: string;
488
+ }[];
489
+ outputFormat: "json";
490
+ status: import("hono/utils/http-status").ContentfulStatusCode;
491
+ };
492
+ };
493
+ } & {
494
+ "/:id": {
495
+ $get: {
496
+ input: {
497
+ param: {
498
+ id: string;
499
+ };
500
+ };
501
+ output: {
502
+ id: string;
503
+ slug: string | null;
504
+ title: string;
505
+ description: string | null;
506
+ status: ReportStatus;
507
+ ownerId: string;
508
+ globalConfig: {
509
+ [x: string]: import("hono/utils/types").JSONValue;
510
+ };
511
+ layout: {
512
+ [x: string]: import("hono/utils/types").JSONValue;
513
+ };
514
+ version: number;
515
+ lockOwnerId: string | null;
516
+ lockExpiration: string | null;
517
+ createdAt: string;
518
+ updatedAt: string;
519
+ };
520
+ outputFormat: "json";
521
+ status: import("hono/utils/http-status").ContentfulStatusCode;
522
+ } | {
523
+ input: {
524
+ param: {
525
+ id: string;
526
+ };
527
+ };
528
+ output: {
529
+ error: string;
530
+ };
531
+ outputFormat: "json";
532
+ status: 404;
533
+ };
534
+ };
535
+ } & {
536
+ "/:id": {
537
+ $patch: {
538
+ input: {
539
+ json: {
540
+ title?: string | undefined;
541
+ description?: string | null | undefined;
542
+ slug?: string | null | undefined;
543
+ globalConfig?: Record<string, unknown> | undefined;
544
+ layout?: Record<string, unknown> | undefined;
545
+ expectedVersion?: number | undefined;
546
+ };
547
+ } & {
548
+ param: {
549
+ id: string;
550
+ };
551
+ };
552
+ output: {
553
+ id: string;
554
+ slug: string | null;
555
+ title: string;
556
+ description: string | null;
557
+ status: ReportStatus;
558
+ ownerId: string;
559
+ globalConfig: {
560
+ [x: string]: import("hono/utils/types").JSONValue;
561
+ };
562
+ layout: {
563
+ [x: string]: import("hono/utils/types").JSONValue;
564
+ };
565
+ version: number;
566
+ lockOwnerId: string | null;
567
+ lockExpiration: string | null;
568
+ createdAt: string;
569
+ updatedAt: string;
570
+ };
571
+ outputFormat: "json";
572
+ status: import("hono/utils/http-status").ContentfulStatusCode;
573
+ } | {
574
+ input: {
575
+ json: {
576
+ title?: string | undefined;
577
+ description?: string | null | undefined;
578
+ slug?: string | null | undefined;
579
+ globalConfig?: Record<string, unknown> | undefined;
580
+ layout?: Record<string, unknown> | undefined;
581
+ expectedVersion?: number | undefined;
582
+ };
583
+ } & {
584
+ param: {
585
+ id: string;
586
+ };
587
+ };
588
+ output: {
589
+ error: string;
590
+ };
591
+ outputFormat: "json";
592
+ status: 404;
593
+ };
594
+ };
595
+ } & {
596
+ "/:id": {
597
+ $delete: {
598
+ input: {
599
+ param: {
600
+ id: string;
601
+ };
602
+ };
603
+ output: {
604
+ success: true;
605
+ };
606
+ outputFormat: "json";
607
+ status: import("hono/utils/http-status").ContentfulStatusCode;
608
+ } | {
609
+ input: {
610
+ param: {
611
+ id: string;
612
+ };
613
+ };
614
+ output: {
615
+ error: string;
616
+ };
617
+ outputFormat: "json";
618
+ status: 404;
619
+ };
620
+ };
621
+ } & {
622
+ "/:id/publish": {
623
+ $post: {
624
+ input: {
625
+ param: {
626
+ id: string;
627
+ };
628
+ };
629
+ output: {
630
+ id: string;
631
+ slug: string | null;
632
+ title: string;
633
+ description: string | null;
634
+ status: ReportStatus;
635
+ ownerId: string;
636
+ globalConfig: {
637
+ [x: string]: import("hono/utils/types").JSONValue;
638
+ };
639
+ layout: {
640
+ [x: string]: import("hono/utils/types").JSONValue;
641
+ };
642
+ version: number;
643
+ lockOwnerId: string | null;
644
+ lockExpiration: string | null;
645
+ createdAt: string;
646
+ updatedAt: string;
647
+ };
648
+ outputFormat: "json";
649
+ status: import("hono/utils/http-status").ContentfulStatusCode;
650
+ } | {
651
+ input: {
652
+ param: {
653
+ id: string;
654
+ };
655
+ };
656
+ output: {
657
+ error: string;
658
+ };
659
+ outputFormat: "json";
660
+ status: 404;
661
+ };
662
+ };
663
+ } & {
664
+ "/:id/archive": {
665
+ $post: {
666
+ input: {
667
+ param: {
668
+ id: string;
669
+ };
670
+ };
671
+ output: {
672
+ id: string;
673
+ slug: string | null;
674
+ title: string;
675
+ description: string | null;
676
+ status: ReportStatus;
677
+ ownerId: string;
678
+ globalConfig: {
679
+ [x: string]: import("hono/utils/types").JSONValue;
680
+ };
681
+ layout: {
682
+ [x: string]: import("hono/utils/types").JSONValue;
683
+ };
684
+ version: number;
685
+ lockOwnerId: string | null;
686
+ lockExpiration: string | null;
687
+ createdAt: string;
688
+ updatedAt: string;
689
+ };
690
+ outputFormat: "json";
691
+ status: import("hono/utils/http-status").ContentfulStatusCode;
692
+ } | {
693
+ input: {
694
+ param: {
695
+ id: string;
696
+ };
697
+ };
698
+ output: {
699
+ error: string;
700
+ };
701
+ outputFormat: "json";
702
+ status: 404;
703
+ };
704
+ };
705
+ } & {
706
+ "/:id/lock": {
707
+ $post: {
708
+ input: {
709
+ json: {
710
+ ttlSeconds?: number | undefined;
711
+ };
712
+ } & {
713
+ param: {
714
+ id: string;
715
+ };
716
+ };
717
+ output: {
718
+ success: boolean;
719
+ };
720
+ outputFormat: "json";
721
+ status: import("hono/utils/http-status").ContentfulStatusCode;
722
+ } | {
723
+ input: {
724
+ json: {
725
+ ttlSeconds?: number | undefined;
726
+ };
727
+ } & {
728
+ param: {
729
+ id: string;
730
+ };
731
+ };
732
+ output: {
733
+ error: string;
734
+ };
735
+ outputFormat: "json";
736
+ status: 409;
737
+ };
738
+ };
739
+ } & {
740
+ "/:id/heartbeat": {
741
+ $post: {
742
+ input: {
743
+ json: {
744
+ ttlSeconds?: number | undefined;
745
+ };
746
+ } & {
747
+ param: {
748
+ id: string;
749
+ };
750
+ };
751
+ output: {
752
+ success: boolean;
753
+ };
754
+ outputFormat: "json";
755
+ status: import("hono/utils/http-status").ContentfulStatusCode;
756
+ };
757
+ };
758
+ } & {
759
+ "/:id/unlock": {
760
+ $post: {
761
+ input: {
762
+ param: {
763
+ id: string;
764
+ };
765
+ };
766
+ output: {
767
+ success: true;
768
+ };
769
+ outputFormat: "json";
770
+ status: import("hono/utils/http-status").ContentfulStatusCode;
771
+ };
772
+ };
773
+ } & {
774
+ "/:id/layout": {
775
+ $patch: {
776
+ input: {
777
+ json: {
778
+ layout: Record<string, unknown>;
779
+ expectedVersion?: number | undefined;
780
+ };
781
+ } & {
782
+ param: {
783
+ id: string;
784
+ };
785
+ };
786
+ output: {
787
+ id: string;
788
+ slug: string | null;
789
+ title: string;
790
+ description: string | null;
791
+ status: ReportStatus;
792
+ ownerId: string;
793
+ globalConfig: {
794
+ [x: string]: import("hono/utils/types").JSONValue;
795
+ };
796
+ layout: {
797
+ [x: string]: import("hono/utils/types").JSONValue;
798
+ };
799
+ version: number;
800
+ lockOwnerId: string | null;
801
+ lockExpiration: string | null;
802
+ createdAt: string;
803
+ updatedAt: string;
804
+ };
805
+ outputFormat: "json";
806
+ status: import("hono/utils/http-status").ContentfulStatusCode;
807
+ } | {
808
+ input: {
809
+ json: {
810
+ layout: Record<string, unknown>;
811
+ expectedVersion?: number | undefined;
812
+ };
813
+ } & {
814
+ param: {
815
+ id: string;
816
+ };
817
+ };
818
+ output: {
819
+ error: string;
820
+ };
821
+ outputFormat: "json";
822
+ status: 403;
823
+ };
824
+ };
825
+ }, "/api/reports"> | import("hono/types").MergeSchemaPath<{
826
+ "/customer-report": {
827
+ $post: {
828
+ input: {
829
+ json: {
830
+ shopId: number;
831
+ watchedNames: string[];
832
+ webhookUrl: string;
833
+ conversionRateApiUrl: string;
834
+ serviceEvaluationApiUrl: string;
835
+ conversionDate?: string | undefined;
836
+ conversionDelay?: number | undefined;
837
+ evaluationDate?: string | undefined;
838
+ };
839
+ };
840
+ output: {
841
+ success: true;
842
+ message: string;
843
+ };
844
+ outputFormat: "json";
845
+ status: import("hono/utils/http-status").ContentfulStatusCode;
846
+ } | {
847
+ input: {
848
+ json: {
849
+ shopId: number;
850
+ watchedNames: string[];
851
+ webhookUrl: string;
852
+ conversionRateApiUrl: string;
853
+ serviceEvaluationApiUrl: string;
854
+ conversionDate?: string | undefined;
855
+ conversionDelay?: number | undefined;
856
+ evaluationDate?: string | undefined;
857
+ };
858
+ };
859
+ output: {
860
+ success: false;
861
+ error: string;
862
+ };
863
+ outputFormat: "json";
864
+ status: 500;
865
+ };
866
+ };
867
+ }, "/api/notifications">, "/">;
868
+ export type AppType = typeof app;
869
+
870
+ export {
871
+ app as default,
872
+ };
873
+
874
+ export {};
package/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type { AppType } from ".";
2
+ export * from "./schemas";
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@stellaris/metrics-shared",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./index.ts",
6
+ "types": "./index.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./index.ts",
10
+ "import": "./index.ts"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "hono": "^4.11.4",
15
+ "zod": "^4.0.0"
16
+ }
17
+ }
@@ -0,0 +1,84 @@
1
+ import { z } from "zod";
2
+
3
+ export const filterOperatorSchema = z.enum([
4
+ "equals",
5
+ "notEquals",
6
+ "contains",
7
+ "gt",
8
+ "lt",
9
+ "gte",
10
+ "lte",
11
+ "between",
12
+ "inDateRange",
13
+ ]);
14
+
15
+ export type FilterOperator = z.infer<typeof filterOperatorSchema>;
16
+
17
+ export const FILTER_OPERATOR_LABELS: Record<FilterOperator, string> = {
18
+ equals: "等于",
19
+ notEquals: "不等于",
20
+ contains: "包含",
21
+ gt: "大于",
22
+ lt: "小于",
23
+ gte: "大于等于",
24
+ lte: "小于等于",
25
+ between: "范围内",
26
+ inDateRange: "在时间范围内",
27
+ };
28
+
29
+ const baseFilterSchema = z.object({
30
+ id: z.string(),
31
+ member: z.string(),
32
+ });
33
+
34
+ export const equalsFilterSchema = baseFilterSchema.extend({
35
+ operator: z.enum(["equals", "notEquals"]),
36
+ value: z.union([z.string(), z.number()]),
37
+ });
38
+
39
+ export type EqualsFilter = z.infer<typeof equalsFilterSchema>;
40
+
41
+ export const compareFilterSchema = baseFilterSchema.extend({
42
+ operator: z.enum(["gt", "lt", "gte", "lte"]),
43
+ value: z.number(),
44
+ });
45
+
46
+ export type CompareFilter = z.infer<typeof compareFilterSchema>;
47
+
48
+ export const containsFilterSchema = baseFilterSchema.extend({
49
+ operator: z.literal("contains"),
50
+ values: z.array(z.string()),
51
+ });
52
+
53
+ export type ContainsFilter = z.infer<typeof containsFilterSchema>;
54
+
55
+ export const betweenFilterSchema = baseFilterSchema.extend({
56
+ operator: z.literal("between"),
57
+ range: z.tuple([z.number(), z.number()]),
58
+ });
59
+
60
+ export type BetweenFilter = z.infer<typeof betweenFilterSchema>;
61
+
62
+ export const dateRangeFilterSchema = baseFilterSchema.extend({
63
+ operator: z.literal("inDateRange"),
64
+ dateRange: z.tuple([z.string(), z.string()]),
65
+ });
66
+
67
+ export type DateRangeFilter = z.infer<typeof dateRangeFilterSchema>;
68
+
69
+ export const filterConditionSchema = z.discriminatedUnion("operator", [
70
+ equalsFilterSchema,
71
+ compareFilterSchema,
72
+ containsFilterSchema,
73
+ betweenFilterSchema,
74
+ dateRangeFilterSchema,
75
+ ]);
76
+
77
+ export type FilterCondition = z.infer<typeof filterConditionSchema>;
78
+
79
+ export const createEmptyFilter = (id: string): EqualsFilter => ({
80
+ id,
81
+ member: "",
82
+ operator: "equals",
83
+ value: "",
84
+ });
@@ -0,0 +1,3 @@
1
+ export * from "./filter";
2
+ export * from "./metric";
3
+ export * from "./time";
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ import { filterConditionSchema } from "./filter";
3
+ import { timeGrainSchema } from "./time";
4
+
5
+ export const metricQueryConfigSchema = z.object({
6
+ table: z.string(),
7
+ distinctOn: z.string().optional(),
8
+ timeDimension: z.string().optional(),
9
+ dimensions: z.array(z.string()),
10
+ filters: z.array(filterConditionSchema),
11
+ timeGrain: timeGrainSchema,
12
+ });
13
+
14
+ export type MetricQueryConfig = z.infer<typeof metricQueryConfigSchema>;
15
+
16
+ export const DEFAULT_QUERY_CONFIG: MetricQueryConfig = {
17
+ table: "",
18
+ distinctOn: "",
19
+ timeDimension: "",
20
+ dimensions: [],
21
+ filters: [],
22
+ timeGrain: "day",
23
+ };
24
+
25
+ export const metricVisualConfigSchema = z.record(z.string(), z.unknown());
26
+
27
+ export type MetricVisualConfig = z.infer<typeof metricVisualConfigSchema>;
28
+
29
+ export function parseMetricQueryConfig(
30
+ data: unknown,
31
+ ): MetricQueryConfig | null {
32
+ const result = metricQueryConfigSchema.safeParse(data);
33
+ if (result.success) {
34
+ return result.data;
35
+ }
36
+ return null;
37
+ }
38
+
39
+ export function parseMetricQueryConfigOrDefault(
40
+ data: unknown,
41
+ ): MetricQueryConfig {
42
+ return parseMetricQueryConfig(data) ?? DEFAULT_QUERY_CONFIG;
43
+ }
@@ -0,0 +1,56 @@
1
+ import { z } from "zod";
2
+
3
+ export const timeGrainSchema = z.enum([
4
+ "all",
5
+ "day",
6
+ "week",
7
+ "month",
8
+ "quarter",
9
+ "year",
10
+ ]);
11
+
12
+ export type TimeGrain = z.infer<typeof timeGrainSchema>;
13
+
14
+ export const TIME_GRAIN_OPTIONS: { value: TimeGrain; label: string }[] = [
15
+ { value: "all", label: "全部" },
16
+ { value: "day", label: "天" },
17
+ { value: "week", label: "周" },
18
+ { value: "month", label: "月" },
19
+ { value: "quarter", label: "季" },
20
+ { value: "year", label: "年" },
21
+ ];
22
+
23
+ export const timeRangePresetSchema = z.enum([
24
+ "today",
25
+ "yesterday",
26
+ "last7days",
27
+ "last30days",
28
+ "last90days",
29
+ "thisMonth",
30
+ "lastMonth",
31
+ "thisQuarter",
32
+ "thisYear",
33
+ ]);
34
+
35
+ export type TimeRangePreset = z.infer<typeof timeRangePresetSchema>;
36
+
37
+ export const dateRangeSchema = z.object({
38
+ preset: timeRangePresetSchema.optional(),
39
+ startDate: z.string().optional(),
40
+ endDate: z.string().optional(),
41
+ });
42
+
43
+ export type DateRange = z.infer<typeof dateRangeSchema>;
44
+
45
+ export const TIME_RANGE_OPTIONS: {
46
+ value: TimeRangePreset;
47
+ label: string;
48
+ days: number;
49
+ }[] = [
50
+ { value: "last7days", label: "近 7 天", days: 7 },
51
+ { value: "last30days", label: "近 30 天", days: 30 },
52
+ { value: "last90days", label: "近 90 天", days: 90 },
53
+ { value: "thisMonth", label: "本月", days: 30 },
54
+ { value: "thisQuarter", label: "本季度", days: 90 },
55
+ { value: "thisYear", label: "本年", days: 365 },
56
+ ];