@cosmicdrift/kumiko-types 0.354.1 → 0.356.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/define-handler.d.ts +2 -0
- package/dist/event-store-executor-types.d.ts +9 -6
- package/dist/fields.d.ts +10 -0
- package/dist/handlers.d.ts +17 -0
- package/dist/screen.d.ts +19 -3
- package/dist/snapshot-types.d.ts +1 -0
- package/package.json +1 -1
package/dist/define-handler.d.ts
CHANGED
|
@@ -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,22 +2,25 @@ 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
|
-
create: (payload: Record<string, unknown>, user: SessionUser, db: TenantDb, options?: {
|
|
16
|
+
create: (payload: Record<string, unknown>, user: SessionUser, db: TenantDb, options?: StreamTenantOption & {
|
|
14
17
|
preSave?: PreSaveRunner;
|
|
15
18
|
}) => Promise<WriteResult<SaveContext>>;
|
|
16
19
|
update: (payload: {
|
|
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. */
|
package/dist/handlers.d.ts
CHANGED
|
@@ -178,10 +178,15 @@ 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>;
|
|
184
185
|
export type EscapeHatchReporter = (kind: EscapeHatchKind, reason: string, target?: EscapeHatchTarget) => void;
|
|
186
|
+
export type TenantWriteTarget = {
|
|
187
|
+
readonly db: TenantDb;
|
|
188
|
+
readonly streamTenantId: TenantId | undefined;
|
|
189
|
+
};
|
|
185
190
|
type SharedContextFields = {
|
|
186
191
|
readonly redis?: Redis;
|
|
187
192
|
readonly cacheSync?: CacheSyncBus;
|
|
@@ -196,6 +201,15 @@ type SharedContextFields = {
|
|
|
196
201
|
* the config feature wired its accessor factory.
|
|
197
202
|
*/
|
|
198
203
|
readonly configFor?: (tenantId: TenantId) => ConfigAccessor;
|
|
204
|
+
/**
|
|
205
|
+
* Write target for ANOTHER tenant: a tenant-mode db bound to it plus the
|
|
206
|
+
* `streamTenantId` to hand the executor, so the event actor stays the
|
|
207
|
+
* operator. Cross-tenant calls throw AccessDeniedError unless the caller is
|
|
208
|
+
* SystemAdmin (the tenantIdOverride gate); the caller's own tenant needs no
|
|
209
|
+
* privilege and yields `streamTenantId: undefined`. Write handlers only;
|
|
210
|
+
* absent for r.systemScope() handlers and without a db.
|
|
211
|
+
*/
|
|
212
|
+
readonly forTenant?: (tenantId: TenantId) => TenantWriteTarget;
|
|
199
213
|
readonly _configAccessorFactory?: ConfigAccessorFactory;
|
|
200
214
|
readonly configEncryption?: import("./envelope-cipher-types.js").EnvelopeCipher;
|
|
201
215
|
readonly rateLimit?: import("./rate-limit-types.js").RateLimitResolver;
|
|
@@ -534,6 +548,9 @@ export type WriteHandlerDef = {
|
|
|
534
548
|
readonly access: AccessRule;
|
|
535
549
|
readonly description?: string;
|
|
536
550
|
readonly agent?: AgentHandlerHints;
|
|
551
|
+
/** Fields a generic create/update handler never writes (`excludeFields`).
|
|
552
|
+
* Set only when non-empty; the renderer and the agent manifest read it from here. */
|
|
553
|
+
readonly excludedFields?: readonly string[];
|
|
537
554
|
readonly unsafeSkipTransitionGuard?: boolean;
|
|
538
555
|
readonly rateLimit?: RateLimitDeclaration;
|
|
539
556
|
/** 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;
|
|
@@ -1291,16 +1299,24 @@ export type EntityEditScreenDefinition = {
|
|
|
1291
1299
|
* das `mask.title`-Label des Config-Keys. Fehlt ein Eintrag, gilt die
|
|
1292
1300
|
* Konvention. */
|
|
1293
1301
|
readonly fieldLabels?: Readonly<Record<string, string>>;
|
|
1294
|
-
/**
|
|
1302
|
+
/** Record actions. Reuses `RowAction` — analogous to
|
|
1295
1303
|
* `ProjectionDetailScreenDefinition.actions` (the loaded record stands
|
|
1296
1304
|
* in for the "row"). `rowClick` has no target here and is rejected by
|
|
1297
1305
|
* the boot-validator, same as on projectionDetail. Not rendered in
|
|
1298
1306
|
* create mode — every action targets an existing record, which the
|
|
1299
|
-
* create branch doesn't have yet.
|
|
1300
|
-
|
|
1307
|
+
* create branch doesn't have yet. By default an action renders with the
|
|
1308
|
+
* secondary form actions (footer, next to copy-link/delete/cancel);
|
|
1309
|
+
* `placement: "menu"` moves it into the header "…" menu, ahead of
|
|
1310
|
+
* copy-link/delete. Without a header menu (drawer, card form, shell
|
|
1311
|
+
* without a header slot) a "menu" action falls back to inline. */
|
|
1312
|
+
readonly actions?: readonly EntityEditAction[];
|
|
1301
1313
|
readonly slots?: ScreenSlots;
|
|
1302
1314
|
readonly access?: AccessRule;
|
|
1303
1315
|
};
|
|
1316
|
+
export type EntityEditActionPlacement = "inline" | "menu";
|
|
1317
|
+
export type EntityEditAction = RowAction & {
|
|
1318
|
+
readonly placement?: EntityEditActionPlacement;
|
|
1319
|
+
};
|
|
1304
1320
|
export type ActionFormScreenDefinition = {
|
|
1305
1321
|
readonly id: string;
|
|
1306
1322
|
readonly type: "actionForm";
|
package/dist/snapshot-types.d.ts
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.356.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>",
|