@cosmicdrift/kumiko-types 0.339.0 → 0.341.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.
@@ -16,6 +16,8 @@ export type AggregateSpec = {
16
16
  readonly measure: AggregateMeasure;
17
17
  readonly groupBy?: readonly AggregateDimension[];
18
18
  readonly orderByValue?: "asc" | "desc";
19
+ /** Direction of the group-key ordering (default asc). orderByValue stays the primary key when set. */
20
+ readonly orderByKeys?: "asc" | "desc";
19
21
  readonly limit?: number;
20
22
  };
21
23
  export type AggregateKey = string | number | boolean | null;
@@ -0,0 +1,8 @@
1
+ export type CacheSyncBus = {
2
+ publish(topic: string, message: unknown): void;
3
+ subscribe(topic: string, listener: (message: unknown) => void): () => void;
4
+ onResync(listener: () => void): () => void;
5
+ };
6
+ export type ClosableCacheSyncBus = CacheSyncBus & {
7
+ close(): Promise<void>;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  import type * as z from "zod";
2
2
  import type { ZodType } from "zod";
3
3
  import type { KumikoEventTypeMap } from "./event-type-map.js";
4
- import type { AccessRule, AgentHandlerHints, EscapeHatchDeclaration, HandlerContext, QueryEvent, RateLimitDeclaration, WriteEvent, WriteResult } from "./handlers.js";
4
+ import type { AccessRule, AgentHandlerHints, EscapeHatchDeclaration, HandlerContext, PayloadRateLimitOption, QueryEvent, RateLimitDeclaration, WriteEvent, WriteResult } from "./handlers.js";
5
5
  import type { PipelineDef } from "./step.js";
6
6
  export type WriteHandlerDefinition<TName extends string = string, TSchema extends ZodType = ZodType, TData = unknown, TMap extends object = KumikoEventTypeMap> = {
7
7
  readonly name: TName;
@@ -11,6 +11,7 @@ export type WriteHandlerDefinition<TName extends string = string, TSchema extend
11
11
  readonly agent?: AgentHandlerHints;
12
12
  readonly unsafeSkipTransitionGuard?: boolean;
13
13
  readonly rateLimit?: RateLimitDeclaration;
14
+ readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
14
15
  readonly escapeHatch?: EscapeHatchDeclaration;
15
16
  readonly tenantlessAnonymous?: boolean;
16
17
  readonly handler: (event: WriteEvent<z.infer<TSchema>>, context: HandlerContext<TMap>) => Promise<WriteResult<TData>>;
@@ -24,6 +25,7 @@ export type WriteHandlerInput<TName extends string = string, TSchema extends Zod
24
25
  readonly agent?: AgentHandlerHints;
25
26
  readonly unsafeSkipTransitionGuard?: boolean;
26
27
  readonly rateLimit?: RateLimitDeclaration;
28
+ readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
27
29
  readonly escapeHatch?: EscapeHatchDeclaration;
28
30
  readonly tenantlessAnonymous?: boolean;
29
31
  } & ({
package/dist/feature.d.ts CHANGED
@@ -6,7 +6,7 @@ import type { RegisterEntityCrudOptions } from "./entity-handlers.js";
6
6
  import type { EntityTableMeta } from "./entity-table-meta-types.js";
7
7
  import type { ExtensionOptionsArgs, ExtensionOptionsFor } from "./extension-options-map.js";
8
8
  import type { EntityDefinition } from "./fields.js";
9
- import type { AccessRule, AgentHandlerHints, AuthClaimsFn, AuthClaimsHookDef, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyType, DeclarativeEventMigration, EntityRef, EscapeHatchDeclaration, EventDef, EventMigrationDef, EventPiiStance, EventUpcastFn, HandlerRef, NameOrRef, QualifiedEventName, QueryHandlerDef, QueryHandlerFn, RateLimitDeclaration, StreamHandlerDef, StreamHandlerFn, WriteHandlerDef, WriteHandlerFn } from "./handlers.js";
9
+ import type { AccessRule, AgentHandlerHints, AuthClaimsFn, AuthClaimsHookDef, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyType, DeclarativeEventMigration, EntityRef, EscapeHatchDeclaration, EventDef, EventMigrationDef, EventPiiStance, EventUpcastFn, HandlerRef, NameOrRef, PayloadRateLimitOption, QualifiedEventName, QueryHandlerDef, QueryHandlerFn, RateLimitDeclaration, StreamHandlerDef, StreamHandlerFn, WriteHandlerDef, WriteHandlerFn } from "./handlers.js";
10
10
  import type { EntityHookMap, HookMap, HookPhase, OwnedFn, PostDeleteHookFn, PostQueryHookFn, PostSaveHookFn, PreDeleteHookFn, PreQueryHookFn, PreSaveHookFn, SearchPayloadContributorFn, ValidationHookFn } from "./hooks.js";
11
11
  import type { HttpRouteDefinition } from "./http-route.js";
12
12
  import type { ContentCollectionDefinition, NavDefinition } from "./nav.js";
@@ -40,6 +40,7 @@ export type SecretKeyDefinition = {
40
40
  readonly scope: "tenant";
41
41
  readonly required?: boolean;
42
42
  readonly writeRoles?: readonly string[];
43
+ readonly valueSchema?: ZodType<string>;
43
44
  };
44
45
  export type SecretOptions = Omit<SecretKeyDefinition, "shortName" | "qualifiedName">;
45
46
  export type SecretNamespaceDefinition = {
@@ -54,6 +55,7 @@ export type SecretNamespaceDefinition = {
54
55
  readonly scope: "tenant";
55
56
  readonly writeRoles?: readonly string[];
56
57
  readonly nameSchema?: ZodType<string>;
58
+ readonly valueSchema?: ZodType<string>;
57
59
  };
58
60
  export type SecretNamespaceOptions = Omit<SecretNamespaceDefinition, "shortName" | "qualifiedPrefix">;
59
61
  export type SecretNamespaceHandle = {
@@ -236,6 +238,7 @@ export type FeatureRegistrar<TFeature extends string = string> = {
236
238
  writeHandler<TSchema extends ZodType>(name: string, schema: TSchema, handler: WriteHandlerFn<z.infer<TSchema>>, options: {
237
239
  access: AccessRule;
238
240
  rateLimit?: RateLimitDeclaration;
241
+ additionalRateLimits?: readonly PayloadRateLimitOption[];
239
242
  description?: string;
240
243
  agent?: AgentHandlerHints;
241
244
  escapeHatch?: EscapeHatchDeclaration;
@@ -1,5 +1,6 @@
1
1
  import type { Redis } from "ioredis";
2
2
  import type { ZodType } from "zod";
3
+ import type { CacheSyncBus } from "./cache-sync-types.js";
3
4
  import type { ConfigAccessor, ConfigAccessorFactory, ConfigResolver } from "./config.js";
4
5
  import type { DbConnection } from "./db-connection.js";
5
6
  import type { DerivativesContext } from "./derivatives-types.js";
@@ -135,9 +136,27 @@ export type NotifyOptions = {
135
136
  readonly priority?: NotifyPriority;
136
137
  readonly idempotencyKey?: string;
137
138
  readonly recipientId?: string;
139
+ readonly immediate?: boolean;
140
+ readonly locale?: string;
141
+ };
142
+ export type NotifyDeliveryStatus = "queued" | "sent" | "failed" | "skipped";
143
+ export type NotifyDelivery = {
144
+ readonly channel: string;
145
+ readonly recipientId: string | null;
146
+ readonly status: NotifyDeliveryStatus;
147
+ readonly error: string | null;
148
+ readonly deliveryAttemptId?: string;
149
+ };
150
+ export type NotifyResult = {
151
+ readonly deliveries: readonly NotifyDelivery[];
138
152
  };
139
- export type NotifyFn = (notificationType: string, options: NotifyOptions) => Promise<void>;
140
- export type NotifyFactory = (user: SessionUser, tenantId: TenantId) => NotifyFn;
153
+ export type NotifyFn = (notificationType: string, options: NotifyOptions) => Promise<NotifyResult>;
154
+ export type NotifyJobDispatcher = {
155
+ dispatch(jobName: string, payload: Record<string, unknown>, meta?: {
156
+ readonly priority?: number;
157
+ }): Promise<unknown>;
158
+ };
159
+ export type NotifyFactory = (user: SessionUser, tenantId: TenantId, jobDispatcher?: NotifyJobDispatcher) => NotifyFn;
141
160
  export type EscapeHatchKind = "unsafe-raw" | "acknowledge-cross-tenant" | "global-write" | "identity-switch" | "unsafe-all-tenants";
142
161
  export type EscapeHatchTarget = {
143
162
  readonly id: string;
@@ -155,6 +174,7 @@ export type EscapeHatchAuditSink = (event: EscapeHatchUseEvent) => Promise<void>
155
174
  export type EscapeHatchReporter = (kind: EscapeHatchKind, reason: string, target?: EscapeHatchTarget) => void;
156
175
  type SharedContextFields = {
157
176
  readonly redis?: Redis;
177
+ readonly cacheSync?: CacheSyncBus;
158
178
  readonly jobRunner?: JobRunnerRef;
159
179
  readonly configResolver?: ConfigResolver;
160
180
  readonly config?: ConfigAccessor;
@@ -169,6 +189,7 @@ type SharedContextFields = {
169
189
  readonly _configAccessorFactory?: ConfigAccessorFactory;
170
190
  readonly configEncryption?: import("./envelope-cipher-types.js").EnvelopeCipher;
171
191
  readonly rateLimit?: import("./rate-limit-types.js").RateLimitResolver;
192
+ readonly _rateLimitPayloadDigest?: (value: string) => string;
172
193
  readonly searchAdapter?: SearchAdapter;
173
194
  readonly files?: FileContext;
174
195
  readonly derivatives?: DerivativesContext;
@@ -446,6 +467,15 @@ export type RateLimitOption = {
446
467
  readonly windowSeconds: number;
447
468
  readonly cost?: number;
448
469
  };
470
+ export type RateLimitPayloadBucket = {
471
+ readonly payloadField: string;
472
+ };
473
+ export type PayloadRateLimitOption = {
474
+ readonly per: RateLimitPayloadBucket;
475
+ readonly limit: number;
476
+ readonly windowSeconds: number;
477
+ readonly cost?: number;
478
+ };
449
479
  export type RateLimitDisabled = {
450
480
  readonly disabled: true;
451
481
  readonly reason: string;
@@ -472,6 +502,9 @@ export type WriteHandlerDef = {
472
502
  readonly agent?: AgentHandlerHints;
473
503
  readonly unsafeSkipTransitionGuard?: boolean;
474
504
  readonly rateLimit?: RateLimitDeclaration;
505
+ /** Per-payload-field limits, e.g. per recipient address. Complements
506
+ * `rateLimit`; anonymous handlers still need an ip-keyed `rateLimit`. */
507
+ readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
475
508
  readonly escapeHatch?: EscapeHatchDeclaration;
476
509
  /** Lets an anonymous `POST /api/write` for this handler proceed under
477
510
  * SYSTEM_TENANT_ID when the host resolves no tenant. Boot requires
@@ -1,4 +1,5 @@
1
1
  import type { Context } from "hono";
2
+ import type { RateLimitOption } from "./handlers.js";
2
3
  /** Subset von HTTP-Methoden den wir aktiv unterstützen. Hono spricht
3
4
  * alle, aber das hier sind die einzigen die ein Feature-Author
4
5
  * realistisch deklariert. */
@@ -36,6 +37,13 @@ export type HttpRouteHandlerDeps = {
36
37
  readonly clientIp: string;
37
38
  };
38
39
  export type HttpRouteHandler = (c: Context<any, any>, deps: HttpRouteHandlerDeps) => Response | Promise<Response>;
40
+ /** Same shape as a handler's `rateLimit`, restricted to the IP-keyed
41
+ * buckets: a route has no dispatcher identity to key on. `"ip+handler"`
42
+ * keeps one bucket per route ("METHOD path"), `"ip"` shares one across
43
+ * every route that declares it. */
44
+ export type HttpRouteRateLimit = Omit<RateLimitOption, "per"> & {
45
+ readonly per: "ip" | "ip+handler";
46
+ };
39
47
  export type HttpRouteDefinition = {
40
48
  /** HTTP-Methode — bei Hono-Mount via app.{get,post,...}(path). */
41
49
  readonly method: HttpRouteMethod;
@@ -49,4 +57,8 @@ export type HttpRouteDefinition = {
49
57
  /** Hono-Handler. Bekommt Hono-Context + Framework-Deps; returnt
50
58
  * Response (sync oder async). */
51
59
  readonly handler: HttpRouteHandler;
60
+ /** Enforced before the route's guards through the server's rate-limit
61
+ * resolver (fail-closed like the global L1 limiter: a limiter outage
62
+ * answers 503 instead of letting the request through). */
63
+ readonly rateLimit?: HttpRouteRateLimit;
52
64
  };
@@ -7,10 +7,12 @@ import type { SchemaTable } from "./schema-table-types.js";
7
7
  export type ProjectionTable = SchemaTable;
8
8
  export type SingleStreamApplyFn<TPayload = Record<string, unknown>> = (event: StoredEvent<TPayload>, tx: DbRunner, table: ProjectionTable) => Promise<void>;
9
9
  export type MultiStreamApplyFn<TPayload = Record<string, unknown>> = (event: StoredEvent<TPayload>, tx: DbRunner, ctx: MultiStreamApplyContext) => Promise<void>;
10
+ export type ProjectionRowIdOf = (source: Pick<StoredEvent, "tenantId" | "aggregateId">) => string;
10
11
  export type ProjectionDefinition = {
11
12
  readonly name: string;
12
13
  readonly source: string | readonly string[];
13
14
  readonly extraSources?: readonly string[];
15
+ readonly extraSourceRowIds?: Readonly<Record<string, ProjectionRowIdOf>>;
14
16
  readonly table: ProjectionTable;
15
17
  readonly entity?: EntityDefinition;
16
18
  readonly apply: Readonly<Record<string, SingleStreamApplyFn>>;
@@ -18,6 +20,7 @@ export type ProjectionDefinition = {
18
20
  };
19
21
  export type EntityProjectionExtension = {
20
22
  readonly sources?: readonly string[];
23
+ readonly rowIdOf?: ProjectionRowIdOf;
21
24
  readonly apply: Readonly<Record<string, SingleStreamApplyFn>>;
22
25
  };
23
26
  export type MspErrorPolicy = {
package/dist/step.js CHANGED
@@ -1,4 +1,4 @@
1
- // Step-Vocabulary Types — see docs/plans/architecture/intern/step-vocabulary.md
1
+ // Step-Vocabulary Types — see kumiko-platform/docs/archive/plans/architecture/intern/step-vocabulary.md
2
2
  //
3
3
  // M.1 minimal scope:
4
4
  // - Steps execute against the existing HandlerContext (no per-step subset).
@@ -1,3 +1,8 @@
1
+ export type JsonTextMatch = {
2
+ /** Top-level keys, tried in order; the first non-null text value is compared (COALESCE). */
3
+ readonly keys: readonly [string, ...string[]];
4
+ readonly eq: string;
5
+ };
1
6
  export type WhereOperator = {
2
7
  readonly gt?: unknown;
3
8
  readonly gte?: unknown;
@@ -6,6 +11,8 @@ export type WhereOperator = {
6
11
  readonly ne?: unknown;
7
12
  readonly in?: readonly unknown[];
8
13
  readonly like?: string;
14
+ /** jsonb columns only; cannot be combined with other operators in the same object. */
15
+ readonly jsonText?: JsonTextMatch | readonly JsonTextMatch[];
9
16
  };
10
17
  export type WherePrimitive = string | number | boolean | bigint | Date | null | undefined;
11
18
  export type WhereValue = WherePrimitive | readonly WherePrimitive[] | WhereOperator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.339.0",
3
+ "version": "0.341.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>",
@@ -222,6 +222,10 @@
222
222
  "types": "./dist/file-provider-resolver-types.d.ts",
223
223
  "default": "./dist/file-provider-resolver-types.js"
224
224
  },
225
+ "./cache-sync-types": {
226
+ "types": "./dist/cache-sync-types.d.ts",
227
+ "default": "./dist/cache-sync-types.js"
228
+ },
225
229
  "./derivatives-types": {
226
230
  "types": "./dist/derivatives-types.d.ts",
227
231
  "default": "./dist/derivatives-types.js"
@@ -481,6 +485,10 @@
481
485
  "types": "./dist/file-provider-resolver-types.d.ts",
482
486
  "default": "./dist/file-provider-resolver-types.js"
483
487
  },
488
+ "./cache-sync-types": {
489
+ "types": "./dist/cache-sync-types.d.ts",
490
+ "default": "./dist/cache-sync-types.js"
491
+ },
484
492
  "./derivatives-types": {
485
493
  "types": "./dist/derivatives-types.d.ts",
486
494
  "default": "./dist/derivatives-types.js"
package/src/changes.json CHANGED
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.340.0",
4
+ "type": "improvement",
5
+ "title": "Where clauses and aggregate options describe jsonb text matches and key ordering",
6
+ "detail": "`WhereOperator` gains `jsonText?: JsonTextMatch | readonly JsonTextMatch[]` with `JsonTextMatch = { keys: readonly [string, ...string[]]; eq: string }`, and the aggregate options gain `orderByKeys?: \"asc\" | \"desc\"`.",
7
+ "migration": "keine"
8
+ },
2
9
  {
3
10
  "version": "0.338.0",
4
11
  "type": "improvement",