@cosmicdrift/kumiko-types 0.163.3 → 0.165.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 +1 -1
- package/src/config.ts +11 -12
- package/src/event-store-errors.ts +19 -0
- package/src/event-store-types.ts +8 -0
- package/src/observability/index.ts +1 -2
- package/src/tz-context.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.165.0",
|
|
4
4
|
"description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types, ohne Runtime-Code. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
package/src/config.ts
CHANGED
|
@@ -202,8 +202,8 @@ export type ConfigStoredRow = {
|
|
|
202
202
|
readonly userId: string | null;
|
|
203
203
|
};
|
|
204
204
|
|
|
205
|
-
// Extended row
|
|
206
|
-
//
|
|
205
|
+
// Extended row with resolution source so the UI can display where each
|
|
206
|
+
// value came from.
|
|
207
207
|
export type ConfigStoredRowWithSource = ConfigStoredRow & {
|
|
208
208
|
readonly source: ConfigValueSource;
|
|
209
209
|
};
|
|
@@ -280,16 +280,6 @@ export type ConfigResolver = {
|
|
|
280
280
|
db: DbConnection | TenantDb,
|
|
281
281
|
): Promise<ReadonlyMap<string, ConfigStoredRow>>;
|
|
282
282
|
|
|
283
|
-
// Like getAll() but also reports the resolution source for each key.
|
|
284
|
-
// Use when the caller needs to display the cascade origin (e.g. the
|
|
285
|
-
// values.query handler serves the UI's hierarchy badge). Hot-path
|
|
286
|
-
// callers should prefer getAll() for the narrower return type.
|
|
287
|
-
getAllWithSource(
|
|
288
|
-
tenantId: TenantId,
|
|
289
|
-
userId: string,
|
|
290
|
-
db: DbConnection | TenantDb,
|
|
291
|
-
): Promise<ReadonlyMap<string, ConfigStoredRowWithSource>>;
|
|
292
|
-
|
|
293
283
|
// Returns ALL cascade levels for a single key — not just the winner.
|
|
294
284
|
// Each level shows its value (or undefined if not set) and whether it
|
|
295
285
|
// is the active/winning level. Levels are ordered by specificity
|
|
@@ -354,6 +344,15 @@ export type JobTrigger =
|
|
|
354
344
|
// maintenance.start) statt N r.job-Calls mit demselben Handler-Body.
|
|
355
345
|
// Im Handler-payload landet `_triggerName: string` damit der Code
|
|
356
346
|
// weiß, welcher Trigger gefeuert hat.
|
|
347
|
+
//
|
|
348
|
+
// Two delivery semantics depending on what `on` resolves to (kumiko-
|
|
349
|
+
// framework#1505): a write/query-handler QN dispatches synchronously
|
|
350
|
+
// from dispatch-write.ts's afterCommitHooks — effectively once. An
|
|
351
|
+
// r.defineEvent QN (e.g. one an r.multiStreamProjection appends via
|
|
352
|
+
// ctx.unsafeAppendEvent) dispatches async via the job-trigger
|
|
353
|
+
// event-consumer (createJobTriggerEventConsumer, pipeline/system-
|
|
354
|
+
// hooks.ts) — cursor delivery, at-least-once. Handlers triggered on an
|
|
355
|
+
// r.defineEvent QN must be idempotent.
|
|
357
356
|
| { readonly on: import("./handlers").NameOrRef | readonly import("./handlers").NameOrRef[] }
|
|
358
357
|
| { readonly cron: string }
|
|
359
358
|
| { readonly manual: true };
|
|
@@ -15,6 +15,25 @@ export class VersionConflictError extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// Thrown when append() collides on the partial unique index over
|
|
19
|
+
// metadata.idempotencyKey (tenant-scoped). Distinct from VersionConflictError:
|
|
20
|
+
// a version conflict means two writers raced the same predecessor; this
|
|
21
|
+
// means the same idempotency key was used twice, which is a caller-side
|
|
22
|
+
// retry that must have already appended once. Callers that set
|
|
23
|
+
// idempotencyKey should treat this as "already applied" rather than retry.
|
|
24
|
+
export class IdempotentAppendConflictError extends Error {
|
|
25
|
+
public readonly tenantId: string;
|
|
26
|
+
public readonly idempotencyKey: string;
|
|
27
|
+
constructor(tenantId: string, idempotencyKey: string) {
|
|
28
|
+
super(
|
|
29
|
+
`Idempotency conflict on tenant ${tenantId}: an event with idempotencyKey "${idempotencyKey}" was already appended.`,
|
|
30
|
+
);
|
|
31
|
+
this.name = "IdempotentAppendConflictError";
|
|
32
|
+
this.tenantId = tenantId;
|
|
33
|
+
this.idempotencyKey = idempotencyKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
18
37
|
// Thrown when ctx.appendEvent targets an archived stream. Archived aggregates
|
|
19
38
|
// are read-only — restoreStream() makes them writable again. The archive
|
|
20
39
|
// state is not carried on the events themselves; it lives on the sparse
|
package/src/event-store-types.ts
CHANGED
|
@@ -12,6 +12,14 @@ export type EventMetadata = {
|
|
|
12
12
|
// set to event.id when an MSP-apply runs ctx.appendEvent. Together with
|
|
13
13
|
// correlationId forms a causation DAG across aggregate streams.
|
|
14
14
|
readonly causationId?: string;
|
|
15
|
+
// Opt-in second line of defense against duplicate appends when the
|
|
16
|
+
// Redis-backed HTTP idempotency guard (pipeline/idempotency.ts) misses a
|
|
17
|
+
// retry window (Redis unreachable, TTL race). Callers that want a hard
|
|
18
|
+
// per-event uniqueness guarantee set a stable key derived from the
|
|
19
|
+
// triggering request; the event-store enforces it via a tenant-scoped
|
|
20
|
+
// partial unique index and throws IdempotentAppendConflictError on a
|
|
21
|
+
// repeat. Unset by default — no uniqueness constraint applies.
|
|
22
|
+
readonly idempotencyKey?: string;
|
|
15
23
|
// Marten-conform free key/value space for app-specific metadata that
|
|
16
24
|
// doesn't deserve its own EventMetadata field. Examples: A/B-test bucket,
|
|
17
25
|
// feature-flag snapshot, geo-region, client SDK version. Persisted into
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
// Barrel for observability types. Split into span/metric/provider
|
|
2
|
-
// each module stays focused; consumers still import from "./types".
|
|
1
|
+
// Barrel for observability types. Split into span/metric/provider so each module stays focused.
|
|
3
2
|
|
|
4
3
|
export type {
|
|
5
4
|
Counter,
|
package/src/tz-context.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { GeoAddress, GeoCoordinates, GeoTzProvider } from "./geo-tz";
|
|
8
8
|
|
|
9
9
|
// JSON form for wall-clock + TZ — see createLocatedTimestampField() in
|
|
10
|
-
// engine/factories.ts. Two fields, foolproof.
|
|
10
|
+
// @cosmicdrift/kumiko-framework, engine/factories.ts. Two fields, foolproof.
|
|
11
11
|
export type LocatedTimestampJson = {
|
|
12
12
|
/** Wall-clock ISO without offset, e.g. "2026-04-03T10:00:00" */
|
|
13
13
|
readonly at: string;
|