@cosmicdrift/kumiko-types 0.311.0 → 0.313.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.311.0",
3
+ "version": "0.313.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>",
package/src/config.ts CHANGED
@@ -354,7 +354,12 @@ export type JobTrigger =
354
354
  // event-consumer (createJobTriggerEventConsumer, pipeline/system-
355
355
  // hooks.ts) — cursor delivery, at-least-once. Handlers triggered on an
356
356
  // r.defineEvent QN must be idempotent.
357
- | { readonly on: import("./handlers").NameOrRef | readonly import("./handlers").NameOrRef[] }
357
+ | {
358
+ readonly on: import("./handlers").NameOrRef | readonly import("./handlers").NameOrRef[];
359
+ // Equality filter on top-level payload fields, checked before enqueue —
360
+ // lets N jobs share one broad event QN, partitioned by a discriminant.
361
+ readonly where?: Readonly<Record<string, string | number | boolean>>;
362
+ }
358
363
  | { readonly cron: string }
359
364
  | { readonly manual: true };
360
365
 
package/src/handlers.ts CHANGED
@@ -4,7 +4,7 @@ import type { ConfigAccessor, ConfigAccessorFactory, ConfigResolver } from "./co
4
4
  import type { DbConnection } from "./db-connection";
5
5
  import type { DerivativesContext } from "./derivatives-types";
6
6
  import type { EntityCache } from "./entity-cache";
7
- import type { WriteOrigin } from "./event-store-types";
7
+ import type { EventMetadata, WriteOrigin } from "./event-store-types";
8
8
  import type { KumikoEventTypeMap } from "./event-type-map";
9
9
  import type { FileContext } from "./file-handle-types";
10
10
  import type { FileProviderResolver } from "./file-provider-resolver-types";
@@ -245,12 +245,21 @@ import type { UncheckedSystemDb } from "./tenant-db-types";
245
245
  // The framework resolves the member internally, so no hand-built SessionUser reaches app code.
246
246
  export type MemberReader = (userId: string, qn: string, payload: unknown) => Promise<unknown>;
247
247
 
248
+ // The stored event that made an r.job trigger fire, carried through so the
249
+ // job handler can key an idempotency check on it (at-least-once delivery via
250
+ // the job-trigger event consumer, see pipeline/system-hooks.ts).
251
+ export type JobTriggerEvent = {
252
+ readonly id: string;
253
+ readonly headers: NonNullable<EventMetadata["headers"]>;
254
+ };
255
+
248
256
  // Minimal interface for job event triggers (framework-owned, concrete type in jobs/)
249
257
  export type JobRunnerRef = {
250
258
  handleEvent(
251
259
  eventName: string,
252
260
  payload: Record<string, unknown>,
253
261
  user?: SessionUser,
262
+ triggerEvent?: JobTriggerEvent,
254
263
  ): Promise<void>;
255
264
  };
256
265
 
@@ -754,6 +763,13 @@ export type JobContext = SharedContextFields & {
754
763
  // Multi-trigger jobs (`on: [...]`) use this to tell which trigger fired —
755
764
  // undefined for cron/manual jobs. Mirrors AppContext.triggerName.
756
765
  readonly triggerName?: string;
766
+ // The stored event that triggered this job run, when reached via the
767
+ // job-trigger event consumer (async, at-least-once). Undefined for
768
+ // cron/manual jobs and for the synchronous handler-QN dispatch path, which
769
+ // has no stored event to hand over. Use triggerEvent.id (or a header) as
770
+ // an idempotency key — at-least-once delivery can run the same trigger
771
+ // more than once.
772
+ readonly triggerEvent?: JobTriggerEvent;
757
773
  // Fallback tenant/user when systemUser doesn't carry it (tenant-less cron
758
774
  // jobs). Mirrors AppContext._tenantId/_userId — see the tenant-scoping
759
775
  // footgun above.
@@ -1,6 +1,7 @@
1
1
  import type { DerivativesContext } from "./derivatives-types";
2
2
  import type { StoredEvent } from "./event-store-types";
3
3
  import type { KumikoEventTypeMap } from "./event-type-map";
4
+ import type { Registry } from "./feature";
4
5
  import type { FileContext } from "./file-handle-types";
5
6
  import type { AppendEventFn, UnsafeAppendEventFn } from "./handlers";
6
7
 
@@ -30,6 +31,10 @@ export type MultiStreamApplyContext<TMap extends object = KumikoEventTypeMap> =
30
31
  aggregateId: string,
31
32
  options?: { readonly asOf?: Temporal.Instant },
32
33
  ) => Promise<readonly StoredEvent[]>;
34
+ // The app registry — same instance HandlerContext/JobContext expose. Lets
35
+ // an apply resolve extension-point usages (registry.getExtensionUsages),
36
+ // e.g. a provider-routed MSP picking a handler by payload discriminant.
37
+ readonly registry: Registry;
33
38
  // Binary storage handle factory, mirrors AppContext.files. Present when
34
39
  // the app booted with `files.storageProvider`; undefined otherwise.
35
40
  // Post-processing MSPs (resize, EXIF-strip, virus-scan) read bytes via