@cosmicdrift/kumiko-types 0.305.0 → 0.307.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 +5 -1
- package/src/config.ts +4 -2
- package/src/event-store-types.ts +15 -0
- package/src/extension-options-map.ts +21 -0
- package/src/feature.ts +8 -3
- package/src/fields.ts +32 -0
- package/src/handlers.ts +15 -2
- package/src/tenant-db-types.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.307.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
|
@@ -380,8 +380,10 @@ export type JobDefinition = {
|
|
|
380
380
|
// Enqueue this job once when a runner for its lane starts. Fire-and-forget:
|
|
381
381
|
// the enqueue is awaited, the run is not, so a throwing handler only fails
|
|
382
382
|
// the queue job — the process keeps booting and reports ready.
|
|
383
|
-
// Deduped
|
|
384
|
-
//
|
|
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.
|
|
385
387
|
// Never a deploy gate — use `bootGate` for that.
|
|
386
388
|
readonly runOnBoot?: boolean | undefined;
|
|
387
389
|
// Run this job inline while the runner for its lane starts, before cron
|
package/src/event-store-types.ts
CHANGED
|
@@ -45,8 +45,23 @@ export type EventMetadata = {
|
|
|
45
45
|
// every new row carries both, falling back to UNATTRIBUTED_ORIGIN.
|
|
46
46
|
readonly feature?: string;
|
|
47
47
|
readonly handler?: string;
|
|
48
|
+
// Only set under an anonymous root without public-intake, so event-triggered
|
|
49
|
+
// jobs keep the personal-data gate.
|
|
50
|
+
readonly writeOrigin?: WriteOrigin;
|
|
48
51
|
};
|
|
49
52
|
|
|
53
|
+
export type WriteOrigin = {
|
|
54
|
+
readonly rootHandler: string;
|
|
55
|
+
readonly anonymousRoot: boolean;
|
|
56
|
+
// Only a write-handler root can declare public-intake; a query/stream root never does.
|
|
57
|
+
readonly publicIntake: boolean;
|
|
58
|
+
readonly viaJob?: string;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function isPersonalDataGated(origin: WriteOrigin): boolean {
|
|
62
|
+
return origin.anonymousRoot && !origin.publicIntake;
|
|
63
|
+
}
|
|
64
|
+
|
|
50
65
|
// Stamped when an append runs outside any attributed scope (seed scripts,
|
|
51
66
|
// tests, direct event-store use). A distinct value, not an omission —
|
|
52
67
|
// omitted would be indistinguishable from a pre-#3043 row.
|
|
@@ -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
|
|
657
|
-
|
|
658
|
-
|
|
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
|
package/src/handlers.ts
CHANGED
|
@@ -4,6 +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
8
|
import type { KumikoEventTypeMap } from "./event-type-map";
|
|
8
9
|
import type { FileContext } from "./file-handle-types";
|
|
9
10
|
import type { FileProviderResolver } from "./file-provider-resolver-types";
|
|
@@ -260,8 +261,20 @@ export type JobRunnerRef = {
|
|
|
260
261
|
// singleton, not bound to one caller's identity. Only write+queryAs — no
|
|
261
262
|
// .query/.stream/.command/.batch/.resolveAuthClaims, that stays Dispatcher-only.
|
|
262
263
|
export type DispatchWriteRef = {
|
|
263
|
-
|
|
264
|
-
|
|
264
|
+
// A job under a gated anonymous origin passes it, else the target would
|
|
265
|
+
// reset to the job's own non-anonymous root.
|
|
266
|
+
readonly write: (
|
|
267
|
+
user: SessionUser,
|
|
268
|
+
qn: string,
|
|
269
|
+
payload: unknown,
|
|
270
|
+
inheritedOrigin?: WriteOrigin,
|
|
271
|
+
) => Promise<WriteResult>;
|
|
272
|
+
readonly queryAs: (
|
|
273
|
+
user: SessionUser,
|
|
274
|
+
qn: string,
|
|
275
|
+
payload: unknown,
|
|
276
|
+
inheritedOrigin?: WriteOrigin,
|
|
277
|
+
) => Promise<unknown>;
|
|
265
278
|
// Builds a tenant-scoped MemberReader — one per JobContext.queryAsMember
|
|
266
279
|
// caller (job-runner.ts lazily creates one per job run).
|
|
267
280
|
readonly createMemberReader: (tenantId: TenantId) => MemberReader;
|
package/src/tenant-db-types.ts
CHANGED
|
@@ -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
|
|
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;
|