@cosmicdrift/kumiko-types 0.354.1 → 0.355.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.
@@ -9,6 +9,8 @@ export type WriteHandlerDefinition<TName extends string = string, TSchema extend
9
9
  readonly access: AccessRule;
10
10
  readonly description?: string;
11
11
  readonly agent?: AgentHandlerHints;
12
+ /** Set by the entity convention create/update handlers; see WriteHandlerDef.excludedFields. */
13
+ readonly excludedFields?: readonly string[];
12
14
  readonly unsafeSkipTransitionGuard?: boolean;
13
15
  readonly rateLimit?: RateLimitDeclaration;
14
16
  readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
@@ -2,13 +2,16 @@ import type { CursorResult } from "./cursor-types.js";
2
2
  import type { EntityDefinition } from "./fields.js";
3
3
  import type { SessionUser, WriteResult } from "./handlers.js";
4
4
  import type { DeleteContext, SaveContext } from "./hooks.js";
5
- import type { EntityId } from "./identifiers.js";
5
+ import type { EntityId, TenantId } from "./identifiers.js";
6
6
  import type { SearchAdapter } from "./search-adapter.js";
7
7
  import type { TenantDb } from "./tenant-db-types.js";
8
8
  export type ParentVisibilityOption = {
9
9
  readonly entities: ReadonlyMap<string, EntityDefinition>;
10
10
  };
11
11
  export type PreSaveRunner = (changes: Record<string, unknown>, previous: Readonly<Record<string, unknown>>, isNew: boolean) => Promise<Record<string, unknown>>;
12
+ export type StreamTenantOption = {
13
+ readonly streamTenantId?: TenantId | undefined;
14
+ };
12
15
  export type EventStoreExecutor = {
13
16
  create: (payload: Record<string, unknown>, user: SessionUser, db: TenantDb, options?: {
14
17
  preSave?: PreSaveRunner;
@@ -17,7 +20,7 @@ export type EventStoreExecutor = {
17
20
  id: EntityId;
18
21
  version?: number | undefined;
19
22
  changes: Record<string, unknown>;
20
- }, user: SessionUser, db: TenantDb, options?: {
23
+ }, user: SessionUser, db: TenantDb, options?: StreamTenantOption & {
21
24
  skipOptimisticLock?: boolean;
22
25
  skipUnchanged?: boolean;
23
26
  preSave?: PreSaveRunner;
@@ -25,13 +28,13 @@ export type EventStoreExecutor = {
25
28
  }) => Promise<WriteResult<SaveContext>>;
26
29
  delete: (payload: {
27
30
  id: EntityId;
28
- }, user: SessionUser, db: TenantDb) => Promise<WriteResult<DeleteContext>>;
31
+ }, user: SessionUser, db: TenantDb, options?: StreamTenantOption) => Promise<WriteResult<DeleteContext>>;
29
32
  forget: (payload: {
30
33
  id: EntityId;
31
- }, user: SessionUser, db: TenantDb) => Promise<WriteResult<DeleteContext>>;
34
+ }, user: SessionUser, db: TenantDb, options?: StreamTenantOption) => Promise<WriteResult<DeleteContext>>;
32
35
  restore: (payload: {
33
36
  id: EntityId;
34
- }, user: SessionUser, db: TenantDb) => Promise<WriteResult<SaveContext>>;
37
+ }, user: SessionUser, db: TenantDb, options?: StreamTenantOption) => Promise<WriteResult<SaveContext>>;
35
38
  list: (payload: {
36
39
  cursor?: string | undefined;
37
40
  limit?: number | undefined;
package/dist/fields.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference types="temporal-polyfill/global" preserve="true" />
2
2
  import type { VariantSpec } from "./derivatives-types.js";
3
+ import type { EventUpcastCtx } from "./handlers.js";
3
4
  import type { OwnershipMap } from "./ownership.js";
4
5
  import type { EntityTenancy } from "./tenancy-brand.js";
5
6
  export type FieldAccess = {
@@ -713,6 +714,11 @@ export type ParentRefDef = {
713
714
  * registered entity is a candidate, which also widens the read-gate's SQL. */
714
715
  readonly allowedTypes?: readonly string[];
715
716
  };
717
+ export type EntityEventMigration = {
718
+ readonly fromVersion: number;
719
+ readonly toVersion: number;
720
+ readonly transform: (fields: Readonly<Record<string, unknown>>, ctx: EventUpcastCtx) => Record<string, unknown> | Promise<Record<string, unknown>>;
721
+ };
716
722
  export type EntityDefinition<F extends FieldsMap = FieldsMap, T extends EntityTenancy = EntityTenancy> = {
717
723
  readonly table?: string;
718
724
  readonly fields: F;
@@ -725,6 +731,10 @@ export type EntityDefinition<F extends FieldsMap = FieldsMap, T extends EntityTe
725
731
  * only for genuinely tenant-independent aggregates like `user`. The first
726
732
  * event (create) is what's routed; updates resolve the stream tenant upstream. */
727
733
  readonly systemStream?: boolean;
734
+ /** Schema version stamped on every lifecycle event (default 1, integer 1..999). Bump it together with a step in `eventMigrations`. */
735
+ readonly eventVersion?: number;
736
+ /** One step per version, fromVersion → fromVersion+1. Transforms run on row-shaped field records; the record may be partial, touch only keys that are present. */
737
+ readonly eventMigrations?: readonly EntityEventMigration[];
728
738
  readonly searchWeight?: number;
729
739
  readonly defaultCurrency?: string;
730
740
  /** Allowed state transitions per field. Boot validates against select options. */
@@ -178,6 +178,7 @@ export type EscapeHatchUseEvent = {
178
178
  readonly reason: string;
179
179
  readonly tenantId: TenantId;
180
180
  readonly actor: string;
181
+ readonly caller?: string;
181
182
  readonly target?: EscapeHatchTarget;
182
183
  };
183
184
  export type EscapeHatchAuditSink = (event: EscapeHatchUseEvent) => Promise<void>;
@@ -534,6 +535,9 @@ export type WriteHandlerDef = {
534
535
  readonly access: AccessRule;
535
536
  readonly description?: string;
536
537
  readonly agent?: AgentHandlerHints;
538
+ /** Fields a generic create/update handler never writes (`excludeFields`).
539
+ * Set only when non-empty; the renderer and the agent manifest read it from here. */
540
+ readonly excludedFields?: readonly string[];
537
541
  readonly unsafeSkipTransitionGuard?: boolean;
538
542
  readonly rateLimit?: RateLimitDeclaration;
539
543
  /** Per-payload-field limits, e.g. per recipient address. Complements
package/dist/screen.d.ts CHANGED
@@ -1205,6 +1205,10 @@ export type EditLayout = {
1205
1205
  };
1206
1206
  };
1207
1207
  };
1208
+ export type EntityWriteExcludedFields = {
1209
+ readonly create?: readonly string[];
1210
+ readonly update?: readonly string[];
1211
+ };
1208
1212
  export type EntityEditScreenDefinition = {
1209
1213
  readonly id: string;
1210
1214
  readonly type: "entityEdit";
@@ -1228,6 +1232,10 @@ export type EntityEditScreenDefinition = {
1228
1232
  * screen — the only URL query keys the create form prefills. An authored
1229
1233
  * value is overwritten. */
1230
1234
  readonly urlPrefillFields?: readonly string[];
1235
+ /** Derived by buildAppSchema from the entity's create/update write handlers
1236
+ * (`excludeFields`): create hides these fields, update shows them read-only.
1237
+ * An authored value is overwritten. */
1238
+ readonly writeExcludedFields?: EntityWriteExcludedFields;
1231
1239
  readonly entity: string;
1232
1240
  /** Entity field whose value names the loaded record in the header breadcrumb (edit mode only). */
1233
1241
  readonly recordTitleField?: string;
@@ -10,4 +10,5 @@ export type LoadAggregateWithSnapshotOptions = {
10
10
  readonly upcastEvent?: (event: StoredEvent) => Promise<StoredEvent>;
11
11
  readonly snapshotEvery?: number;
12
12
  readonly snapshotVersion?: number;
13
+ readonly entityEventVersionOf?: (aggregateType: string) => number | undefined;
13
14
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.354.1",
3
+ "version": "0.355.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>",