@cosmicdrift/kumiko-types 0.237.2 → 0.239.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.237.2",
3
+ "version": "0.239.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>",
@@ -1,4 +1,5 @@
1
1
  import type { CursorResult } from "./cursor-types";
2
+ import type { EntityDefinition } from "./fields";
2
3
  import type { SessionUser, WriteResult } from "./handlers";
3
4
  import type { DeleteContext, SaveContext } from "./hooks";
4
5
  import type { EntityId } from "./identifiers";
@@ -93,6 +94,21 @@ export type EventStoreExecutor = {
93
94
  // — includeDeleted only relaxes the soft-delete predicate, never the
94
95
  // visibility ones, so it can ride untrusted query input safely.
95
96
  readonly includeDeleted?: boolean;
97
+ // fw#2660 — a text search also matches `searchable: true` reference
98
+ // fields (and the implicit tenantId→tenant.name row-meta reference) by
99
+ // their target row's labelField, not just the raw FK column. Only
100
+ // available at request time (registry access), so it rides the same
101
+ // runtime-override extension point as searchAdapter. `fields` and
102
+ // `resolveEntity` travel together — one without the other silently
103
+ // no-ops, so they're grouped instead of two independent optionals.
104
+ readonly referenceSearch?: {
105
+ readonly fields: ReadonlyArray<{
106
+ readonly fieldName: string;
107
+ readonly targetEntityName: string;
108
+ readonly labelField: string;
109
+ }>;
110
+ readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
111
+ };
96
112
  },
97
113
  ) => Promise<CursorResult<Record<string, unknown>>>;
98
114
 
package/src/feature.ts CHANGED
@@ -883,7 +883,11 @@ export type Registry = {
883
883
  getSearchableFields(entityName: string): readonly string[];
884
884
  getSortableFields(entityName: string): readonly string[];
885
885
  getRelations(entityName: string): EntityRelations;
886
- getSearchIncludes(entityName: string): ReadonlyMap<string, readonly string[]>;
886
+ getSearchableReferences(entityName: string): ReadonlyArray<{
887
+ fieldName: string;
888
+ targetEntityName: string;
889
+ labelField: string;
890
+ }>;
887
891
  getIncomingRelations(entityName: string): ReadonlyArray<{
888
892
  sourceEntity: string;
889
893
  relationName: string;
package/src/fields.ts CHANGED
@@ -471,6 +471,12 @@ export type ReferenceFieldDef = {
471
471
  * statt single UUID. Storage als jsonb-Array<uuid>. UI rendert
472
472
  * Multi-Select-Combobox mit Tag-Anzeige der gewählten Items. */
473
473
  readonly multiple?: boolean;
474
+ /** Include a row in this entity's result set on a text-search hit against
475
+ * the referenced entity's `labelField`, instead of only matching the UUID
476
+ * column itself (fw#2660). Requires an explicit `labelField` — the boot
477
+ * validator rejects it otherwise, since the default "id" is a UUID column
478
+ * and ILIKE against it would crash at runtime. */
479
+ readonly searchable?: true;
474
480
  } & ResolvedPiiFlags;
475
481
 
476
482
  // --- Currency ---
package/src/relations.ts CHANGED
@@ -9,7 +9,6 @@ export type BelongsToRelation = {
9
9
  readonly type: "belongsTo";
10
10
  readonly target: string;
11
11
  readonly foreignKey: string;
12
- readonly searchInclude?: readonly string[];
13
12
  // onDelete is declared on the parent-side (hasMany / manyToMany) because
14
13
  // that's where the "what happens to my children?" decision lives. A
15
14
  // belongsTo node just points at a parent — the parent's onDelete drives
@@ -45,7 +44,6 @@ export type ManyToManyRelation = {
45
44
  readonly sourceKey: string;
46
45
  readonly targetKey: string;
47
46
  };
48
- readonly searchInclude?: readonly string[];
49
47
  readonly onDelete?: OnDeleteStrategy;
50
48
  };
51
49
 
package/src/screen.ts CHANGED
@@ -117,6 +117,17 @@ export type ListColumnSpec =
117
117
  * label; without one it is rejected at boot as an unknown field. `field`
118
118
  * is then just a stable column key (pick any unique slug). */
119
119
  readonly label?: string;
120
+ /** Marks this column as a reference lookup instead of a plain value —
121
+ * for projectionList/relatedList columns, which have no
122
+ * `EntityDefinition` to carry a real `reference` field type. Same
123
+ * target convention as `parseRefTarget`: an entity name (same
124
+ * feature) or `feature:entity` (cross-feature). Ignored on
125
+ * `entityList` columns, where the field's own declared type always
126
+ * wins. */
127
+ readonly refEntity?: string;
128
+ /** Row field on the referenced entity shown as the label (default
129
+ * "id"). Only meaningful together with `refEntity`. */
130
+ readonly refLabelField?: string;
120
131
  };
121
132
 
122
133
  // Pagination-Modi für entityList:
@@ -665,6 +676,17 @@ export type EditFieldSpec =
665
676
  * `multiline` routes to a textarea (no icon slot), and other input
666
677
  * kinds (select, combobox, date, …) silently ignore the key. */
667
678
  readonly icon?: FieldIconKey;
679
+ /** Marks this field as a reference lookup instead of a plain value —
680
+ * for projectionDetail fields, which have no `EntityDefinition` to
681
+ * carry a real `reference` field type. Same target convention as
682
+ * `parseRefTarget` (and `ListColumnSpec.refEntity`): an entity name
683
+ * (same feature) or `feature:entity` (cross-feature). Ignored on
684
+ * `entityEdit` fields, where the field's own declared type always
685
+ * wins. */
686
+ readonly refEntity?: string;
687
+ /** Row field on the referenced entity shown as the label (default
688
+ * "id"). Only meaningful together with `refEntity`. */
689
+ readonly refLabelField?: string;
668
690
  };
669
691
 
670
692
  // A section is a normal field-grid (default — `kind` omitted keeps every