@cosmicdrift/kumiko-types 0.164.0 → 2.0.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/LICENSE CHANGED
@@ -4,7 +4,7 @@ Parameters
4
4
 
5
5
  Licensor: Marc Frost
6
6
 
7
- Licensed Work: @cosmicdrift/kumiko-framework
7
+ Licensed Work: @cosmicdrift/kumiko-types
8
8
  The Licensed Work is © 2026 Marc Frost.
9
9
 
10
10
  Additional Use Grant:
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @cosmicdrift/kumiko-types
2
+
3
+ [![License: BUSL-1.1](https://img.shields.io/badge/License-BUSL--1.1-blue.svg)](../../LICENSE)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)](https://www.typescriptlang.org/)
5
+
6
+ Framework type definitions for Kumiko — `FeatureDefinition`, boot-check types,
7
+ and the pure engine types. Lets downstream consumers build against the type
8
+ contracts without importing the whole framework package.
9
+
10
+ Also contains the identity-sensitive error classes (`event-store-errors.ts`,
11
+ `kms-adapter-types.ts`) as runtime code — `kumiko-framework`/
12
+ `kumiko-bundled-features` declare this package as a `peerDependency`
13
+ (single-copy constraint), not a plain dependency.
14
+
15
+ See the [monorepo root README](../../README.md) for the broader pitch.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.164.0",
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.",
3
+ "version": "2.0.0",
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 auch die identitaets-sensitiven Error-Klassen (event-store-errors.ts, kms-adapter-types.ts) als Runtime-Code — kumiko-framework/kumiko-bundled-features deklarieren dieses Package deshalb als peerDependency (Single-Copy-Zwang), nicht als plain dependency.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
7
7
  "repository": {
@@ -227,9 +227,15 @@
227
227
  "default": "./src/snapshot-types.ts"
228
228
  }
229
229
  },
230
- "dependencies": {
230
+ "devDependencies": {
231
231
  "hono": "^4.12.18",
232
- "postgres": "^3.4.9"
232
+ "postgres": "^3.4.9",
233
+ "temporal-polyfill": "^0.3.2"
234
+ },
235
+ "peerDependencies": {
236
+ "hono": "^4.12.18",
237
+ "postgres": "^3.4.9",
238
+ "temporal-polyfill": "^0.3.2"
233
239
  },
234
240
  "publishConfig": {
235
241
  "registry": "https://registry.npmjs.org",
@@ -1,2 +1,5 @@
1
- // Keep in sync with ConcurrencyModes in packages/framework/src/engine/constants.ts.
1
+ // Canonical source packages/framework/src/engine/constants.ts's
2
+ // ConcurrencyModes value object is `satisfies Record<string, ConcurrencyMode>`
3
+ // against this type, so adding a mode only here (or only there) is a compile
4
+ // error instead of silent drift (#1423/#1439).
2
5
  export type ConcurrencyMode = "parallel" | "skip" | "replace" | "sequential" | "debounce";
@@ -1,2 +1,5 @@
1
- // Keep in sync with ConfigScopes in packages/framework/src/engine/constants.ts.
1
+ // Canonical source packages/framework/src/engine/constants.ts's
2
+ // ConfigScopes value object is `satisfies Record<string, ConfigScope>`
3
+ // against this type, so adding a scope only here (or only there) is a
4
+ // compile error instead of silent drift (#1423/#1439).
2
5
  export type ConfigScope = "system" | "tenant" | "user";
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 returned by ConfigResolver.getAllWithSource includes the
206
- // resolution source so the UI can display where each value came from.
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 };
@@ -1,9 +1,23 @@
1
1
  import type postgres from "postgres";
2
2
 
3
- // biome-ignore lint/suspicious/noExplicitAny: Bun.SQL global type
4
- export type DbConnection = ReturnType<typeof postgres> | any;
5
- // biome-ignore lint/suspicious/noExplicitAny: postgres-js namespace lookup
6
- export type DbTx = postgres.TransactionSql<any> | any;
3
+ // Minimal structural surface both postgres-js and Bun.SQL satisfy for
4
+ // asRawClient() / query helpers. Avoid `| any` — TS unions with `any`
5
+ // collapse to `any` and erase the postgres side entirely.
6
+ export type RawDbClient = {
7
+ // Signatures are intentionally loose: postgres-js uses (string, values?),
8
+ // Bun.SQL uses tagged templates / unsafe(string). Call sites go through
9
+ // asRawClient() which normalizes at runtime.
10
+ // biome-ignore lint/suspicious/noExplicitAny: cross-provider unsafe arity
11
+ unsafe: (...args: any[]) => any;
12
+ // biome-ignore lint/suspicious/noExplicitAny: cross-provider begin arity
13
+ begin: (...args: any[]) => any;
14
+ end?: (options?: { timeout?: number }) => Promise<void>;
15
+ };
16
+
17
+ // Raw SQL client (postgres-js instance or Bun.SQL). Distinct from the
18
+ // framework's structural pool handle (`DbPoolHandle` in db/api.ts).
19
+ export type DbConnection = ReturnType<typeof postgres> | RawDbClient;
20
+ export type DbTx = postgres.TransactionSql<Record<string, unknown>> | RawDbClient;
7
21
  export type DbRunner = DbConnection | DbTx;
8
22
  export type DbRow = Record<string, unknown>;
9
23
  export type PgClient = ReturnType<typeof postgres>;
@@ -81,7 +81,7 @@ export type EntityTableMeta = {
81
81
  export type BuildEntityTableMetaOptions = {
82
82
  readonly featureName?: string;
83
83
  readonly relations?: EntityRelations;
84
- readonly source?: "managed" | "unmanaged";
84
+ readonly source?: EntityTableMeta["source"];
85
85
  };
86
86
 
87
87
  export type UnmanagedTableInput = {
package/src/fields.ts CHANGED
@@ -220,6 +220,8 @@ export type NumberFieldDef = {
220
220
  readonly default?: number;
221
221
  readonly access?: FieldAccess;
222
222
  readonly min?: number;
223
+ /** Upper bound at the write boundary (Zod `.max`). */
224
+ readonly max?: number;
223
225
  /** `true` → `integer` column + `.int()` Zod validation. Omitted/`false` →
224
226
  * `double precision` column, fractional values allowed. */
225
227
  readonly integer?: boolean;
@@ -20,6 +20,12 @@ export type WriteStreamOptions = {
20
20
  // shuttle bytes. `mimeType` on write() is a hint for providers that need a
21
21
  // Content-Type header (S3/R2/…); local filesystems can ignore it.
22
22
  //
23
+ // writeStream/readStream are required, not optional: user-data-export jobs
24
+ // need streams for large files, and providers can satisfy the contract with
25
+ // a single-chunk yield if they don't have a native stream API — an optional
26
+ // type here would let a provider skip them and fail silently in production
27
+ // the first time an export job hits it.
28
+ //
23
29
  // getSignedUrl is optional — providers without native presigned-URL support
24
30
  // (filesystem) leave it undefined; the route then returns 501 and the
25
31
  // client falls back to streaming via GET /files/:id. Callers must
package/src/handlers.ts CHANGED
@@ -272,6 +272,12 @@ type SharedContextFields = {
272
272
  // the same process. Returns the Set of feature names effectively
273
273
  // enabled for that tenant. Absent = all features on (back-compat).
274
274
  readonly effectiveFeatures?: (tenantId: TenantId) => ReadonlySet<string>;
275
+ // Queue a side-effect to run after the outermost write transaction commits
276
+ // (same sink as ctx.write / dispatch-write lifecycle afterCommit). Seed
277
+ // helpers and other mid-tx callers use this instead of firing afterCommit
278
+ // hooks synchronously (kumiko-framework#1566). Absent outside a write
279
+ // pipeline — callers fall back to immediate fire (fixture / no-tx paths).
280
+ readonly scheduleAfterCommit?: (hook: () => Promise<void>) => void;
275
281
  };
276
282
 
277
283
  // All optional — used at pipeline/system boundaries.
@@ -1,5 +1,4 @@
1
- // Barrel for observability types. Split into span/metric/provider files so
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,
@@ -1,3 +1,5 @@
1
+ import type { Temporal } from "temporal-polyfill";
2
+
1
3
  export type RateLimitDecision = {
2
4
  readonly allowed: boolean;
3
5
  readonly limit: number;
package/src/relations.ts CHANGED
@@ -1,5 +1,7 @@
1
- // Keep in sync with OnDeleteStrategies in packages/framework/src/engine/constants.ts.
2
- type OnDeleteStrategy = "cascade" | "restrict" | "setNull" | "nothing";
1
+ // Canonical definition packages/framework/src/engine/constants.ts imports
2
+ // this type and binds its OnDeleteStrategies runtime object to it via
3
+ // `satisfies`, so a drift between the two fails to compile.
4
+ export type OnDeleteStrategy = "cascade" | "restrict" | "setNull" | "nothing";
3
5
 
4
6
  // --- Relations ---
5
7
 
@@ -5,6 +5,11 @@ import type { EntityTableMeta, PgType } from "./entity-table-meta-types";
5
5
  // exactly the same unique-symbol type as the one used to construct the table.
6
6
  export const KUMIKO_NAME_SYMBOL = Symbol.for("kumiko:schema:Name");
7
7
  export const KUMIKO_COLUMNS_SYMBOL = Symbol.for("kumiko:schema:Columns");
8
+ // Shadow-proof handle on the canonical EntityTableMeta — SchemaTable also
9
+ // spreads these fields as enumerable string-keyed props, which an entity
10
+ // field named `source`/`columns`/`tableName`/… could shadow; readers that
11
+ // need the canonical meta regardless of shadowing use this symbol instead.
12
+ export const KUMIKO_META_SYMBOL = Symbol.for("kumiko:schema:Meta");
8
13
 
9
14
  // Column handle exposed on the SchemaTable. The `name` is the SQL column
10
15
  // name (snake_case); legacy code accesses `table.fieldName.name` to
@@ -20,5 +25,6 @@ export type ColumnHandle = {
20
25
  export type SchemaTable = EntityTableMeta & {
21
26
  readonly [KUMIKO_NAME_SYMBOL]: string;
22
27
  readonly [KUMIKO_COLUMNS_SYMBOL]: Record<string, ColumnHandle>;
28
+ readonly [KUMIKO_META_SYMBOL]: EntityTableMeta;
23
29
  readonly [field: string]: unknown;
24
30
  };
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;
@@ -1,5 +1,8 @@
1
1
  // WhereValue: primitive for eq, array for IN, null for IS NULL, or an
2
- // operator-object for range/comparisons.
2
+ // operator-object for range/comparisons. Deliberately NOT `unknown |
3
+ // WhereOperator` — that union collapses to `unknown` and erases the
4
+ // operator form at every call site (a typo like `{ gtee: x }` would
5
+ // type-check, then bind as eq at runtime).
3
6
  export type WhereOperator = {
4
7
  readonly gt?: unknown;
5
8
  readonly gte?: unknown;
@@ -9,8 +12,11 @@ export type WhereOperator = {
9
12
  readonly in?: readonly unknown[];
10
13
  readonly like?: string;
11
14
  };
12
- export type WhereValue = unknown | WhereOperator;
13
- export type WhereObject = Record<string, WhereValue>;
15
+ export type WherePrimitive = string | number | boolean | bigint | Date | null | undefined;
16
+ export type WhereValue = WherePrimitive | readonly WherePrimitive[] | WhereOperator;
17
+ // Wider index so dynamic Record<string, unknown> builders still typecheck;
18
+ // annotate literals as WhereValue / satisfies WhereValue to catch typos.
19
+ export type WhereObject = Record<string, WhereValue | unknown>;
14
20
 
15
21
  export type OrderByClause = {
16
22
  readonly col: string;
@@ -12,10 +12,8 @@ export type WriteErrorInfo = {
12
12
  readonly details?: unknown;
13
13
  };
14
14
 
15
- // The failure half of WriteResult — `{ isSuccess: false } + error`. Named
16
- // so the write-failure factories in write-error-info.ts and WriteResult
17
- // share one shape instead of restating it. Not generic: the error carries
18
- // zero data, so there's nothing for the caller to narrow.
15
+ // The failure half of WriteResult — `{ isSuccess: false } + error`. Not
16
+ // generic: the error carries zero data, so there's nothing to narrow.
19
17
  export type WriteFailure = {
20
18
  readonly isSuccess: false;
21
19
  readonly error: WriteErrorInfo;