@cosmicdrift/kumiko-types 0.304.0 → 0.306.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.304.0",
3
+ "version": "0.306.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>",
@@ -34,6 +34,10 @@
34
34
  "types": "./src/event-type-map.ts",
35
35
  "default": "./src/event-type-map.ts"
36
36
  },
37
+ "./extension-options-map": {
38
+ "types": "./src/extension-options-map.ts",
39
+ "default": "./src/extension-options-map.ts"
40
+ },
37
41
  "./http-route": {
38
42
  "types": "./src/http-route.ts",
39
43
  "default": "./src/http-route.ts"
package/src/config.ts CHANGED
@@ -358,6 +358,14 @@ export type JobTrigger =
358
358
  | { readonly cron: string }
359
359
  | { readonly manual: true };
360
360
 
361
+ export type JobBackoffStrategy = "fixed" | "exponential";
362
+ // String form uses the framework's default base delay; the object form's
363
+ // `delayMs` is the base BullMQ multiplies: "fixed" keeps it constant,
364
+ // "exponential" scales it delayMs * 2^(attemptsMade-1) per retry.
365
+ export type JobBackoff =
366
+ | JobBackoffStrategy
367
+ | { readonly type: JobBackoffStrategy; readonly delayMs?: number | undefined };
368
+
361
369
  export type JobDefinition = {
362
370
  readonly name: string;
363
371
  readonly handler: JobHandlerFn;
@@ -366,14 +374,16 @@ export type JobDefinition = {
366
374
  readonly maxPerTenant?: number | undefined;
367
375
  readonly debounceMs?: number | undefined;
368
376
  readonly retries?: number | undefined;
369
- readonly backoff?: "fixed" | "exponential" | undefined;
377
+ readonly backoff?: JobBackoff | undefined;
370
378
  readonly timeout?: number | undefined;
371
379
  readonly schema?: ZodType | undefined;
372
380
  // Enqueue this job once when a runner for its lane starts. Fire-and-forget:
373
381
  // the enqueue is awaited, the run is not, so a throwing handler only fails
374
382
  // the queue job — the process keeps booting and reports ready.
375
- // Deduped on a fixed job id, so it runs at most once per Redis dataset: a
376
- // boot job that already ran (or failed) is not retried on a later deploy.
383
+ // Deduped via a persistent per-queue marker set at enqueue time (not the
384
+ // fixed job id alone, which BullMQ's bounded retention can evict), so it
385
+ // runs at most once per Redis dataset: a boot job that already ran (or
386
+ // failed) is not retried on a later deploy.
377
387
  // Never a deploy gate — use `bootGate` for that.
378
388
  readonly runOnBoot?: boolean | undefined;
379
389
  // Run this job inline while the runner for its lane starts, before cron
@@ -0,0 +1,21 @@
1
+ // Cross-Feature Compile-Time-Type-Map for `r.useExtension(name, entity, options)`.
2
+ // Augmented per extension point via `declare module "@cosmicdrift/kumiko-framework/engine"`,
3
+ // mirroring event-type-map.ts; names without augmentation stay untyped.
4
+
5
+ import type { EscapeHatchDeclaration } from "./handlers";
6
+
7
+ // MUST be `interface` (not `type`): only interfaces support TS declaration-
8
+ // merging. See event-type-map.ts for the same constraint.
9
+
10
+ // biome-ignore lint/suspicious/noEmptyInterface: declaration-merging marker — augmented per extension point
11
+ export interface KumikoExtensionOptionsMap {}
12
+
13
+ /** Options shape for an extension name: the augmented hook shape plus `escapeHatch`, or an untyped bag if unaugmented. */
14
+ export type ExtensionOptionsFor<N extends string> = N extends keyof KumikoExtensionOptionsMap
15
+ ? KumikoExtensionOptionsMap[N] & { readonly escapeHatch?: EscapeHatchDeclaration }
16
+ : Record<string, unknown>;
17
+
18
+ /** Rest-tuple for useExtension's positional options arg: required for an augmented name, optional otherwise. */
19
+ export type ExtensionOptionsArgs<N extends string> = N extends keyof KumikoExtensionOptionsMap
20
+ ? [options: ExtensionOptionsFor<N>]
21
+ : [options?: Record<string, unknown>];
package/src/feature.ts CHANGED
@@ -24,6 +24,7 @@ import type {
24
24
  } from "./define-handler";
25
25
  import type { RegisterEntityCrudOptions } from "./entity-handlers";
26
26
  import type { EntityTableMeta } from "./entity-table-meta-types";
27
+ import type { ExtensionOptionsArgs, ExtensionOptionsFor } from "./extension-options-map";
27
28
  import type { EntityDefinition } from "./fields";
28
29
  import type {
29
30
  AccessRule,
@@ -653,9 +654,13 @@ export type FeatureRegistrar<TFeature extends string = string> = {
653
654
 
654
655
  extendsRegistrar(name: string, def: RegistrarExtensionDef): void;
655
656
 
656
- useExtension(extensionName: string, entity: NameOrRef, options?: Record<string, unknown>): void;
657
- useExtension(
658
- definition: { readonly name: string; readonly entity: NameOrRef } & Record<string, unknown>,
657
+ useExtension<N extends string>(
658
+ extensionName: N,
659
+ entity: NameOrRef,
660
+ ...options: ExtensionOptionsArgs<N>
661
+ ): void;
662
+ useExtension<N extends string>(
663
+ definition: { readonly name: N; readonly entity: NameOrRef } & ExtensionOptionsFor<N>,
659
664
  ): void;
660
665
 
661
666
  /**
package/src/fields.ts CHANGED
@@ -836,6 +836,38 @@ export type FieldDefinition =
836
836
  | FilesFieldDef
837
837
  | ImagesFieldDef;
838
838
 
839
+ // Exhaustive catalogue of `FieldDefinition["type"]` values, derived from a
840
+ // `Record` so an added/removed union member fails to compile here instead of
841
+ // silently drifting out of sync with the runtime validator that consults
842
+ // this list (feature-ast's pattern-change-schema). Plain array, not a Set —
843
+ // same rationale as NO_WIDGET_FIELD_TYPES (guard-types-class-free.test.ts).
844
+ const FIELD_TYPE_NAME_FLAGS: Record<FieldDefinition["type"], true> = {
845
+ text: true,
846
+ longText: true,
847
+ boolean: true,
848
+ select: true,
849
+ multiSelect: true,
850
+ number: true,
851
+ bigInt: true,
852
+ decimal: true,
853
+ money: true,
854
+ reference: true,
855
+ embedded: true,
856
+ jsonb: true,
857
+ date: true,
858
+ timestamp: true,
859
+ tz: true,
860
+ locatedTimestamp: true,
861
+ file: true,
862
+ image: true,
863
+ files: true,
864
+ images: true,
865
+ };
866
+
867
+ export const FIELD_TYPE_NAMES: readonly FieldDefinition["type"][] = Object.keys(
868
+ FIELD_TYPE_NAME_FLAGS,
869
+ ) as FieldDefinition["type"][];
870
+
839
871
  /** FieldDefinition as an entity-less inline form screen (actionForm,
840
872
  * secretMint) may declare it: a `money` field there has no entity to borrow
841
873
  * `defaultCurrency` from, so it must name its own currency source, or the
@@ -108,7 +108,7 @@ export type UncheckedSystemDb = {
108
108
  // durability writes that must survive a rollback of the handler's own
109
109
  // transaction. Throws if the dispatch has no outside-transaction source
110
110
  // configured (e.g. a hand-built UncheckedSystemDb that only ever passed
111
- // the in-tx db to createUncheckedSystemDb).
111
+ // the in-tx db, as createSystemDbView callers do).
112
112
  readonly outsideTransaction: {
113
113
  assertTenantMatch(tenantId: TenantId): TenantDb;
114
114
  acknowledgeCrossTenant(reason: string): TenantDb;