@cosmicdrift/kumiko-types 0.329.0 → 0.330.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.
@@ -0,0 +1,25 @@
1
+ export type AggregateMeasure = {
2
+ readonly fn: "count";
3
+ } | {
4
+ readonly fn: "countDistinct" | "sum" | "avg";
5
+ readonly field: string;
6
+ };
7
+ export type AggregateTimeBucket = "hour" | "day";
8
+ export type AggregateDimension = {
9
+ readonly field: string;
10
+ } | {
11
+ readonly field: string;
12
+ readonly bucket: AggregateTimeBucket;
13
+ readonly timeZone: string;
14
+ };
15
+ export type AggregateSpec = {
16
+ readonly measure: AggregateMeasure;
17
+ readonly groupBy?: readonly AggregateDimension[];
18
+ readonly orderByValue?: "asc" | "desc";
19
+ readonly limit?: number;
20
+ };
21
+ export type AggregateKey = string | number | boolean | null;
22
+ export type AggregateRow = {
23
+ readonly keys: readonly AggregateKey[];
24
+ readonly value: number | null;
25
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/screen.d.ts CHANGED
@@ -113,7 +113,15 @@ export type ListColumnSpec = string | {
113
113
  * `md` breakpoint (tables keep it). For columns that only make sense
114
114
  * next to the others, like a sort key. */
115
115
  readonly hideOnNarrow?: boolean;
116
+ /** Dashboard list panels only. "bar": field holds a 0..1 fraction, drawn
117
+ * as bar + percent. "badge": field holds a label, drawn as a pill whose
118
+ * tone comes from `badgeToneField`. Other list renderers ignore it. */
119
+ readonly display?: ListColumnDisplay;
120
+ /** Row field naming the badge tone; only with `display: "badge"`. */
121
+ readonly badgeToneField?: string;
116
122
  };
123
+ export type ListColumnDisplay = "bar" | "badge";
124
+ export type ListBadgeTone = "positive" | "warn" | "negative" | "neutral";
117
125
  export type ListPaginationMode = "pages" | "infinite" | false;
118
126
  export type ListSortDir = "asc" | "desc";
119
127
  export type ListSortSpec = {
@@ -322,6 +330,8 @@ export type EntityListScreenDefinition = {
322
330
  * app); exempts it from the nav-area boot check. */
323
331
  readonly dormant?: boolean;
324
332
  readonly entity: string;
333
+ /** Short screen id (same feature) the create button opens instead of the entity's default edit screen. */
334
+ readonly createScreen?: string;
325
335
  readonly columns: readonly ListColumnSpec[];
326
336
  readonly rowRenderer?: PlatformComponent;
327
337
  readonly cardRenderer?: PlatformComponent;
@@ -530,20 +540,39 @@ export type ProjectionDetailScreenDefinition = {
530
540
  * Set "form" to opt back into the disabled-Input look (fw#2245). */
531
541
  readonly valueDisplay?: "form" | "text";
532
542
  };
533
- export type DashboardStatPanel = {
543
+ export type DashboardPanelQueryOptions = {
544
+ /** Static, author-set query parameters merged on top of the screen's
545
+ * dynamic filterParams — lets a panel pin a value (e.g. a status facet)
546
+ * the screen-wide filter doesn't cover, without needing its own query.
547
+ * The panel wins over the screen filter and the time range. */
548
+ readonly params?: Readonly<Record<string, unknown>>;
549
+ /** The screen `filter` value is NOT merged into this panel's query (a tenant
550
+ * picker must not hit sources without a tenant column). The screen
551
+ * `timeRange` still is. */
552
+ readonly ignoreScreenFilter?: boolean;
553
+ };
554
+ export type DashboardPanelSpan = "half" | "full";
555
+ export type DashboardPanelEmptyState = {
556
+ readonly span?: DashboardPanelSpan;
557
+ readonly emptyLabel?: string;
558
+ /** Second line under `emptyLabel`. */
559
+ readonly emptyHint?: string;
560
+ };
561
+ export type DashboardStatPanel = DashboardPanelQueryOptions & {
534
562
  readonly kind: "stat";
535
- /** Stable id — kebab-case, eindeutig im Panel-Set. */
563
+ /** Stable id: kebab-case, unique within the panel set. */
536
564
  readonly id: string;
537
565
  /** Anzeige-Text (i18n-Key). */
538
566
  readonly label: string;
539
567
  readonly query: string;
540
- /** Static, author-set query parameters merged on top of the screen's
541
- * dynamic filterParams — lets a panel pin a value (e.g. a status facet)
542
- * the screen-wide filter doesn't cover, without needing its own query. */
543
- readonly params?: Readonly<Record<string, unknown>>;
544
568
  readonly valueField: string;
545
569
  readonly subField?: string;
546
570
  readonly toneField?: string;
571
+ /** Fixed tone when `toneField` is unset or yields none; not applied while the value is 0. */
572
+ readonly tone?: "default" | "positive" | "warn" | "negative";
573
+ /** Record field holding `{ atMs, value | null }[]` (MetricResult.points),
574
+ * drawn as a sparkline next to the value. */
575
+ readonly sparklineField?: string;
547
576
  /** Optionaler Delta-Chip (z.B. "↓23 %") neben dem Label. Nur wenn BEIDE
548
577
  * Felder gesetzt sind UND der Query-Handler sie liefert, rendert der Chip
549
578
  * — sonst bleibt die Kachel wie ohne Delta. `deltaToneField` fällt auf
@@ -564,15 +593,20 @@ export type DashboardStatPanel = {
564
593
  * Icon) — ohne icon wird der Wert still verworfen. */
565
594
  readonly accentColor?: string;
566
595
  };
567
- export type DashboardChartPanel = {
596
+ export type DashboardChartKind = "timeseries" | "stacked-bars" | "segment-bars" | "stacked-area";
597
+ export type DashboardChartTone = "positive" | "negative" | "active" | "neutral";
598
+ export type DashboardChartPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
568
599
  readonly kind: "chart";
569
600
  readonly id: string;
570
601
  readonly label: string;
571
- /** v1: geglättete Zeitreihe. Weitere Chart-Formen additiv. */
572
- readonly chart: "timeseries";
602
+ readonly chart: DashboardChartKind;
573
603
  readonly query: string;
604
+ /** i18n key under the title, e.g. "7 days, by creation day". */
605
+ readonly subtitle?: string;
606
+ /** Series/segment key -> tone; unmapped keys fall back to a palette. */
607
+ readonly seriesTones?: Readonly<Record<string, DashboardChartTone>>;
574
608
  };
575
- export type DashboardListPanel = {
609
+ export type DashboardListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
576
610
  readonly kind: "list";
577
611
  readonly id: string;
578
612
  readonly label: string;
@@ -582,17 +616,16 @@ export type DashboardListPanel = {
582
616
  export type DashboardStatGroupPanel = {
583
617
  readonly kind: "stat-group";
584
618
  readonly id: string;
585
- readonly label: string;
619
+ readonly label?: string;
586
620
  readonly stats: readonly DashboardStatPanel[];
587
621
  };
588
- export type DashboardFeedPanel = {
622
+ export type DashboardFeedPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
589
623
  readonly kind: "feed";
590
624
  readonly id: string;
591
625
  readonly label: string;
592
626
  readonly query: string;
593
- readonly emptyLabel?: string;
594
627
  };
595
- export type DashboardProgressListPanel = {
628
+ export type DashboardProgressListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & {
596
629
  readonly kind: "progress-list";
597
630
  readonly id: string;
598
631
  readonly label: string;
@@ -631,6 +664,19 @@ export type DashboardFilterDefinition = {
631
664
  /** Query-Result-Contract: `{ rows: { value: string; label: string }[] }`. */
632
665
  readonly optionsQuery?: string;
633
666
  };
667
+ export type DashboardTimeRangeDefinition = {
668
+ readonly id: string;
669
+ /** `label` is an i18n key. */
670
+ readonly options: readonly {
671
+ readonly value: string;
672
+ readonly label: string;
673
+ }[];
674
+ readonly default: string;
675
+ };
676
+ export type DashboardScopeDefinition = {
677
+ readonly badge: string;
678
+ readonly notice?: string;
679
+ };
634
680
  export type DashboardScreenDefinition = {
635
681
  readonly id: string;
636
682
  readonly type: "dashboard";
@@ -643,6 +689,11 @@ export type DashboardScreenDefinition = {
643
689
  readonly dormant?: boolean;
644
690
  readonly panels: readonly DashboardPanelDefinition[];
645
691
  readonly filter?: DashboardFilterDefinition;
692
+ /** Segmented control in the toolbar; the value lives in URL search param
693
+ * `id` and is merged into EVERY panel query (also ignoreScreenFilter ones). */
694
+ readonly timeRange?: DashboardTimeRangeDefinition;
695
+ /** Marks the screen as spanning more than the caller's own scope. */
696
+ readonly scope?: DashboardScopeDefinition;
646
697
  readonly slots?: ScreenSlots;
647
698
  readonly access?: AccessRule;
648
699
  };
@@ -905,6 +956,8 @@ export type EntityEditScreenDefinition = {
905
956
  * value is overwritten. */
906
957
  readonly urlPrefillFields?: readonly string[];
907
958
  readonly entity: string;
959
+ /** Entity field whose value names the loaded record in the header breadcrumb (edit mode only). */
960
+ readonly recordTitleField?: string;
908
961
  readonly layout: EditLayout;
909
962
  /** Optionaler i18n-Key (oder Roh-String) für den Submit-Button. Default
910
963
  * `kumiko.actions.save`. Lässt den Auto-Edit-Screen domain-spezifische
@@ -1179,6 +1232,9 @@ export type CustomScreenDefinition = {
1179
1232
  export type ConfigEditScreenDefinition = {
1180
1233
  readonly id: string;
1181
1234
  readonly type: "configEdit";
1235
+ /** Default true: the form fills the shell content height with a pinned
1236
+ * footer. `false` restores the card layout with the footer in the flow. */
1237
+ readonly fillHeight?: boolean;
1182
1238
  readonly nav?: ScreenNavSugar;
1183
1239
  readonly detailFor?: string;
1184
1240
  readonly description?: string;
@@ -1,3 +1,4 @@
1
+ import type { AggregateRow, AggregateSpec } from "./aggregate-types.js";
1
2
  import type { DbRunner } from "./db-connection.js";
2
3
  import type { EntityTableMeta } from "./entity-table-meta-types.js";
3
4
  import type { ExecutorOnly, NotExecutorOnly } from "./executor-brand.js";
@@ -44,6 +45,7 @@ export type TenantDb = {
44
45
  selectMany<T = Record<string, unknown>>(table: SchemaTable | EntityTableMeta, where?: WhereObject, options?: SelectOptions): Promise<readonly T[]>;
45
46
  fetchOne<T = Record<string, unknown>>(table: SchemaTable | EntityTableMeta, where: WhereObject): Promise<T | undefined>;
46
47
  count(table: SchemaTable | EntityTableMeta, where?: WhereObject): Promise<number>;
48
+ aggregate(table: SchemaTable | EntityTableMeta, spec: AggregateSpec, where?: WhereObject): Promise<readonly AggregateRow[]>;
47
49
  insertOne<T = Record<string, unknown>>(table: WritableTable, values: Record<string, unknown>): Promise<T | undefined>;
48
50
  updateMany<T = Record<string, unknown>>(table: WritableTable, set: Record<string, unknown>, where: WhereObject): Promise<readonly T[]>;
49
51
  deleteMany(table: WritableTable, where: WhereObject): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.329.0",
3
+ "version": "0.330.0",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -138,6 +138,10 @@
138
138
  "types": "./dist/where-clause-types.d.ts",
139
139
  "default": "./dist/where-clause-types.js"
140
140
  },
141
+ "./aggregate-types": {
142
+ "types": "./dist/aggregate-types.d.ts",
143
+ "default": "./dist/aggregate-types.js"
144
+ },
141
145
  "./tenant-db-types": {
142
146
  "types": "./dist/tenant-db-types.d.ts",
143
147
  "default": "./dist/tenant-db-types.js"
@@ -393,6 +397,10 @@
393
397
  "types": "./dist/where-clause-types.d.ts",
394
398
  "default": "./dist/where-clause-types.js"
395
399
  },
400
+ "./aggregate-types": {
401
+ "types": "./dist/aggregate-types.d.ts",
402
+ "default": "./dist/aggregate-types.js"
403
+ },
396
404
  "./tenant-db-types": {
397
405
  "types": "./dist/tenant-db-types.d.ts",
398
406
  "default": "./dist/tenant-db-types.js"