@cosmicdrift/kumiko-types 0.395.0 → 0.397.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/dist/event-store-executor-types.d.ts +7 -4
- package/dist/fields-derived.d.ts +27 -0
- package/dist/fields-derived.js +20 -0
- package/dist/fields.d.ts +20 -27
- package/package.json +1 -1
|
@@ -9,6 +9,9 @@ import type { TenantDb } from "./tenant-db-types.ts";
|
|
|
9
9
|
export type ParentVisibilityOption = {
|
|
10
10
|
readonly entities: ReadonlyMap<string, EntityDefinition>;
|
|
11
11
|
};
|
|
12
|
+
export type ParentVisibilityGateOption = {
|
|
13
|
+
readonly parentVisibility?: ParentVisibilityOption;
|
|
14
|
+
};
|
|
12
15
|
export type PreSaveRunner = (changes: Record<string, unknown>, previous: Readonly<Record<string, unknown>>, isNew: boolean) => Promise<Record<string, unknown>>;
|
|
13
16
|
export type StreamTenantOption = {
|
|
14
17
|
readonly streamTenantId?: TenantId | undefined;
|
|
@@ -62,7 +65,7 @@ export type EventStoreExecutor<Row extends Record<string, unknown> = Record<stri
|
|
|
62
65
|
id: EntityId;
|
|
63
66
|
version?: number | undefined;
|
|
64
67
|
changes: Record<string, unknown>;
|
|
65
|
-
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & LockGuardOption & {
|
|
68
|
+
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & LockGuardOption & ParentVisibilityGateOption & {
|
|
66
69
|
skipOptimisticLock?: boolean;
|
|
67
70
|
skipUnchanged?: boolean;
|
|
68
71
|
includeDeleted?: boolean;
|
|
@@ -71,13 +74,13 @@ export type EventStoreExecutor<Row extends Record<string, unknown> = Record<stri
|
|
|
71
74
|
}) => Promise<WriteResult<SaveContext>>;
|
|
72
75
|
delete: (payload: {
|
|
73
76
|
id: EntityId;
|
|
74
|
-
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & LockGuardOption) => Promise<WriteResult<DeleteContext>>;
|
|
77
|
+
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & LockGuardOption & ParentVisibilityGateOption) => Promise<WriteResult<DeleteContext>>;
|
|
75
78
|
forget: (payload: {
|
|
76
79
|
id: EntityId;
|
|
77
|
-
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption) => Promise<WriteResult<DeleteContext>>;
|
|
80
|
+
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & ParentVisibilityGateOption) => Promise<WriteResult<DeleteContext>>;
|
|
78
81
|
restore: (payload: {
|
|
79
82
|
id: EntityId;
|
|
80
|
-
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption) => Promise<WriteResult<SaveContext>>;
|
|
83
|
+
}, user: SessionUser, db: TenantDb, options?: StreamTenantOption & ParentVisibilityGateOption) => Promise<WriteResult<SaveContext>>;
|
|
81
84
|
list: (payload: {
|
|
82
85
|
cursor?: string | undefined;
|
|
83
86
|
limit?: number | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
|
+
/** Display type a derived value formats as — drives the column's renderer
|
|
3
|
+
* choice in the view-model, parallel to FieldDefinition["type"]. Single-column
|
|
4
|
+
* types only: `money` is excluded because it needs a `<name>Currency`
|
|
5
|
+
* companion column a derived field has no place to put — use `number`/
|
|
6
|
+
* `decimal` plus a `{ format: "currency" }` column renderer instead. */
|
|
7
|
+
export type DerivedValueType = "text" | "number" | "decimal" | "boolean" | "date" | "timestamp";
|
|
8
|
+
/** Clock injected into `derive` — never read `Temporal.Now`/`Date` inside a
|
|
9
|
+
* derive body (no-date-api guard + testability). The list-query handler passes
|
|
10
|
+
* the read-time instant; unit tests pass a fixed one. */
|
|
11
|
+
export type DeriveContext = {
|
|
12
|
+
readonly asOf: Temporal.Instant;
|
|
13
|
+
};
|
|
14
|
+
export type DerivedFieldDef = {
|
|
15
|
+
readonly valueType: DerivedValueType;
|
|
16
|
+
/** Pure function of the stored row + clock. Returns the JSON-safe display
|
|
17
|
+
* value (e.g. integer minor units for a currency column, ISO string for a
|
|
18
|
+
* `date`). */
|
|
19
|
+
readonly derive: (row: Readonly<Record<string, unknown>>, ctx: DeriveContext) => unknown;
|
|
20
|
+
};
|
|
21
|
+
export type DerivedFieldsMap = Readonly<Record<string, DerivedFieldDef>>;
|
|
22
|
+
/** Client-facing projection of DerivedFieldDef — `derive` is server-only and
|
|
23
|
+
* not JSON-safe (would trip the output-walk guard), so the browser schema
|
|
24
|
+
* only ever carries `valueType`. A real `Pick`, not a same-shape cast: TS
|
|
25
|
+
* itself proves `derive` isn't there instead of a `{ valueType } as
|
|
26
|
+
* DerivedFieldDef` cast lying about a field that's actually missing. */
|
|
27
|
+
export type ClientDerivedFieldDef = Pick<DerivedFieldDef, "valueType">;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
|
+
// --- Derived (computed) fields ---
|
|
3
|
+
//
|
|
4
|
+
// A derived field is read-time only: its value is computed from the stored row
|
|
5
|
+
// (and the clock) when an entityList query runs (676/2 — NOT detail; only the
|
|
6
|
+
// "list" case in entity-handlers.ts calls augmentDerivedFields), never
|
|
7
|
+
// persisted. It lives in
|
|
8
|
+
// `EntityDefinition.derivedFields` — deliberately NOT in `fields`, so it
|
|
9
|
+
// produces no DB column, never enters a write schema, and can't be the target
|
|
10
|
+
// of an entityEdit. A declarative `entityList` can name it like any column and
|
|
11
|
+
// the view-model renders the appended value.
|
|
12
|
+
//
|
|
13
|
+
// LIMIT: derived columns are DISPLAY ONLY. A declarative `entityList` loads its
|
|
14
|
+
// rows server-side and a column-header sort round-trips to the server, where
|
|
15
|
+
// `executor.list` sorts/filters/searches over real SQL columns — so a derived
|
|
16
|
+
// field (no column) silently no-ops. There is no client-side sort path. Need a
|
|
17
|
+
// derived value sortable/searchable? Materialize it as a stored field; it then
|
|
18
|
+
// rides the existing `searchable`/`sortable` machinery. Time-dependent values
|
|
19
|
+
// (as-of-today) can't be materialized without a daily re-index anyway.
|
|
20
|
+
export {};
|
package/dist/fields.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
2
|
import type { VariantSpec } from "./derivatives-types.ts";
|
|
3
|
+
import type { DerivedFieldsMap } from "./fields-derived.ts";
|
|
3
4
|
import type { EventUpcastCtx } from "./handlers.ts";
|
|
4
5
|
import type { OwnershipMap } from "./ownership.ts";
|
|
5
6
|
import type { EntityTenancy } from "./tenancy-brand.ts";
|
|
7
|
+
export type { ClientDerivedFieldDef, DeriveContext, DerivedFieldDef, DerivedFieldsMap, DerivedValueType, } from "./fields-derived.ts";
|
|
6
8
|
export type FieldAccess = {
|
|
7
9
|
readonly read?: OwnershipMap | readonly string[];
|
|
8
10
|
readonly write?: OwnershipMap | readonly string[];
|
|
@@ -78,6 +80,9 @@ export type RetentionDef = {
|
|
|
78
80
|
readonly strategy: "hardDelete" | "softDelete" | "anonymize" | "blockDelete";
|
|
79
81
|
readonly reference?: string;
|
|
80
82
|
};
|
|
83
|
+
/** Where rows without a value sort in a list, in both directions. Without it Postgres decides:
|
|
84
|
+
* last ascending, first descending. */
|
|
85
|
+
export type SortNulls = "first" | "last";
|
|
81
86
|
export type TextFieldDef = {
|
|
82
87
|
readonly type: "text";
|
|
83
88
|
/** Optional free-text semantics for the AI agent manifest — never rendered;
|
|
@@ -93,6 +98,7 @@ export type TextFieldDef = {
|
|
|
93
98
|
readonly required?: boolean;
|
|
94
99
|
readonly searchable?: boolean;
|
|
95
100
|
readonly sortable?: boolean;
|
|
101
|
+
readonly sortNulls?: SortNulls;
|
|
96
102
|
/** Allows screen filters on this field.
|
|
97
103
|
* The boot validator rejects filters with `filterable !== true`.
|
|
98
104
|
* Default: false, analogous to `sortable`, and therefore opt-in. */
|
|
@@ -176,6 +182,7 @@ export type BooleanFieldDef = {
|
|
|
176
182
|
readonly description?: string;
|
|
177
183
|
readonly required?: boolean;
|
|
178
184
|
readonly sortable?: boolean;
|
|
185
|
+
readonly sortNulls?: SortNulls;
|
|
179
186
|
readonly filterable?: boolean;
|
|
180
187
|
readonly sensitive?: boolean;
|
|
181
188
|
readonly default?: boolean;
|
|
@@ -217,6 +224,7 @@ export type SelectFieldDef<TOptions extends readonly string[] = readonly string[
|
|
|
217
224
|
readonly options: TOptions;
|
|
218
225
|
readonly required?: boolean;
|
|
219
226
|
readonly sortable?: boolean;
|
|
227
|
+
readonly sortNulls?: SortNulls;
|
|
220
228
|
readonly filterable?: boolean;
|
|
221
229
|
readonly sensitive?: boolean;
|
|
222
230
|
readonly default?: TOptions[number];
|
|
@@ -297,6 +305,7 @@ export type NumberFieldDef = {
|
|
|
297
305
|
readonly description?: string;
|
|
298
306
|
readonly required?: boolean;
|
|
299
307
|
readonly sortable?: boolean;
|
|
308
|
+
readonly sortNulls?: SortNulls;
|
|
300
309
|
readonly filterable?: boolean;
|
|
301
310
|
readonly sensitive?: boolean;
|
|
302
311
|
readonly default?: number;
|
|
@@ -333,6 +342,7 @@ export type BigIntFieldDef = {
|
|
|
333
342
|
readonly description?: string;
|
|
334
343
|
readonly required?: boolean;
|
|
335
344
|
readonly sortable?: boolean;
|
|
345
|
+
readonly sortNulls?: SortNulls;
|
|
336
346
|
readonly filterable?: boolean;
|
|
337
347
|
readonly sensitive?: boolean;
|
|
338
348
|
readonly default?: number;
|
|
@@ -357,6 +367,7 @@ export type DecimalFieldDef = {
|
|
|
357
367
|
readonly scale: number;
|
|
358
368
|
readonly required?: boolean;
|
|
359
369
|
readonly sortable?: boolean;
|
|
370
|
+
readonly sortNulls?: SortNulls;
|
|
360
371
|
readonly filterable?: boolean;
|
|
361
372
|
readonly sensitive?: boolean;
|
|
362
373
|
readonly default?: number;
|
|
@@ -385,6 +396,7 @@ export type MoneyFieldDef = {
|
|
|
385
396
|
readonly description?: string;
|
|
386
397
|
readonly required?: boolean;
|
|
387
398
|
readonly sortable?: boolean;
|
|
399
|
+
readonly sortNulls?: SortNulls;
|
|
388
400
|
readonly filterable?: boolean;
|
|
389
401
|
readonly sensitive?: boolean;
|
|
390
402
|
readonly access?: FieldAccess;
|
|
@@ -421,6 +433,7 @@ export type ReferenceFieldDef = {
|
|
|
421
433
|
* boot validator rejects it otherwise, since ordering by a UUID produces a
|
|
422
434
|
* sequence that looks meaningful to the user but is arbitrary. */
|
|
423
435
|
readonly sortable?: true;
|
|
436
|
+
readonly sortNulls?: SortNulls;
|
|
424
437
|
/** Fill the picker from this query handler instead of the referenced
|
|
425
438
|
* entity's own list handler — for targets whose identity is
|
|
426
439
|
* composed from joined rows, where no single column of the referenced
|
|
@@ -537,6 +550,9 @@ export type EmbeddedFieldDef = {
|
|
|
537
550
|
export type JsonbFieldDef = {
|
|
538
551
|
readonly type: "jsonb";
|
|
539
552
|
readonly description?: string;
|
|
553
|
+
/** `"array"`: the field holds a JSON array, so a row that never wrote it reads `[]` and writes
|
|
554
|
+
* take an array. Default `"object"` (`{}`, writes take a plain object). */
|
|
555
|
+
readonly emptyValue?: JsonbEmptyValue;
|
|
540
556
|
readonly sensitive?: boolean;
|
|
541
557
|
/** A later run reads this field's value as an instruction — prompt, rule,
|
|
542
558
|
* template. Every create/update whose payload writes it requires agent.risk
|
|
@@ -545,11 +561,13 @@ export type JsonbFieldDef = {
|
|
|
545
561
|
readonly readAsInstruction?: boolean;
|
|
546
562
|
readonly access?: FieldAccess;
|
|
547
563
|
} & ResolvedPiiFlags;
|
|
564
|
+
export type JsonbEmptyValue = "object" | "array";
|
|
548
565
|
export type DateFieldDef = {
|
|
549
566
|
readonly type: "date";
|
|
550
567
|
readonly description?: string;
|
|
551
568
|
readonly required?: boolean;
|
|
552
569
|
readonly sortable?: boolean;
|
|
570
|
+
readonly sortNulls?: SortNulls;
|
|
553
571
|
readonly filterable?: boolean;
|
|
554
572
|
readonly sensitive?: boolean;
|
|
555
573
|
readonly access?: FieldAccess;
|
|
@@ -567,6 +585,7 @@ export type TimestampFieldDef = {
|
|
|
567
585
|
readonly description?: string;
|
|
568
586
|
readonly required?: boolean;
|
|
569
587
|
readonly sortable?: boolean;
|
|
588
|
+
readonly sortNulls?: SortNulls;
|
|
570
589
|
readonly filterable?: boolean;
|
|
571
590
|
readonly sensitive?: boolean;
|
|
572
591
|
readonly access?: FieldAccess;
|
|
@@ -599,6 +618,7 @@ export type LocatedTimestampFieldDef = {
|
|
|
599
618
|
readonly description?: string;
|
|
600
619
|
readonly required?: boolean;
|
|
601
620
|
readonly sortable?: boolean;
|
|
621
|
+
readonly sortNulls?: SortNulls;
|
|
602
622
|
readonly filterable?: boolean;
|
|
603
623
|
readonly sensitive?: boolean;
|
|
604
624
|
readonly access?: FieldAccess;
|
|
@@ -675,32 +695,6 @@ export type FormFieldDefinition = Exclude<FieldDefinition, MoneyFieldDef> | (Mon
|
|
|
675
695
|
});
|
|
676
696
|
export type AnyFileFieldDef = FileFieldDef | ImageFieldDef | FilesFieldDef | ImagesFieldDef;
|
|
677
697
|
export declare const NO_WIDGET_FIELD_TYPES: readonly FieldDefinition["type"][];
|
|
678
|
-
/** Display type a derived value formats as — drives the column's renderer
|
|
679
|
-
* choice in the view-model, parallel to FieldDefinition["type"]. Single-column
|
|
680
|
-
* types only: `money` is excluded because it needs a `<name>Currency`
|
|
681
|
-
* companion column a derived field has no place to put — use `number`/
|
|
682
|
-
* `decimal` plus a `{ format: "currency" }` column renderer instead. */
|
|
683
|
-
export type DerivedValueType = "text" | "number" | "decimal" | "boolean" | "date" | "timestamp";
|
|
684
|
-
/** Clock injected into `derive` — never read `Temporal.Now`/`Date` inside a
|
|
685
|
-
* derive body (no-date-api guard + testability). The list-query handler passes
|
|
686
|
-
* the read-time instant; unit tests pass a fixed one. */
|
|
687
|
-
export type DeriveContext = {
|
|
688
|
-
readonly asOf: Temporal.Instant;
|
|
689
|
-
};
|
|
690
|
-
export type DerivedFieldDef = {
|
|
691
|
-
readonly valueType: DerivedValueType;
|
|
692
|
-
/** Pure function of the stored row + clock. Returns the JSON-safe display
|
|
693
|
-
* value (e.g. integer minor units for a currency column, ISO string for a
|
|
694
|
-
* `date`). */
|
|
695
|
-
readonly derive: (row: Readonly<Record<string, unknown>>, ctx: DeriveContext) => unknown;
|
|
696
|
-
};
|
|
697
|
-
export type DerivedFieldsMap = Readonly<Record<string, DerivedFieldDef>>;
|
|
698
|
-
/** Client-facing projection of DerivedFieldDef — `derive` is server-only and
|
|
699
|
-
* not JSON-safe (would trip the output-walk guard), so the browser schema
|
|
700
|
-
* only ever carries `valueType`. A real `Pick`, not a same-shape cast: TS
|
|
701
|
-
* itself proves `derive` isn't there instead of a `{ valueType } as
|
|
702
|
-
* DerivedFieldDef` cast lying about a field that's actually missing. */
|
|
703
|
-
export type ClientDerivedFieldDef = Pick<DerivedFieldDef, "valueType">;
|
|
704
698
|
export type TransitionMap = Readonly<Record<string, readonly string[]>>;
|
|
705
699
|
/** Composite index on an entity. Columns are referenced by field name
|
|
706
700
|
* (camelCase). `buildEntityTable` maps them to snake_case column names and
|
|
@@ -867,4 +861,3 @@ export type EntityDefinition<F extends FieldsMap = FieldsMap, T extends EntityTe
|
|
|
867
861
|
* privilegedRoles do not bypass it, the uploader check stays. */
|
|
868
862
|
readonly attachedFileAccess?: "record-only";
|
|
869
863
|
};
|
|
870
|
-
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.397.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": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|