@cosmicdrift/kumiko-types 0.327.0 → 0.328.1

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.
Files changed (174) hide show
  1. package/dist/action-icon.d.ts +3 -0
  2. package/dist/action-icon.js +51 -0
  3. package/{src/agent-exposure.ts → dist/agent-exposure.d.ts} +8 -15
  4. package/dist/agent-exposure.js +16 -0
  5. package/dist/concurrency-mode.d.ts +1 -0
  6. package/dist/config-scope.d.ts +1 -0
  7. package/dist/config-scope.js +1 -0
  8. package/dist/config.d.ts +234 -0
  9. package/dist/config.js +1 -0
  10. package/dist/cursor-types.d.ts +16 -0
  11. package/dist/cursor-types.js +1 -0
  12. package/dist/db-connection.d.ts +14 -0
  13. package/dist/db-connection.js +1 -0
  14. package/dist/define-handler.d.ts +58 -0
  15. package/dist/define-handler.js +1 -0
  16. package/dist/derivatives-types.d.ts +53 -0
  17. package/dist/derivatives-types.js +3 -0
  18. package/dist/entity-cache.d.ts +16 -0
  19. package/dist/entity-cache.js +1 -0
  20. package/dist/entity-handlers.d.ts +54 -0
  21. package/dist/entity-handlers.js +1 -0
  22. package/dist/entity-table-meta-types.d.ts +44 -0
  23. package/dist/entity-table-meta-types.js +6 -0
  24. package/dist/envelope-cipher-types.d.ts +5 -0
  25. package/dist/envelope-cipher-types.js +1 -0
  26. package/dist/event-store-executor-types.d.ts +86 -0
  27. package/dist/event-store-executor-types.js +1 -0
  28. package/dist/event-store-types.d.ts +37 -0
  29. package/dist/event-store-types.js +7 -0
  30. package/dist/event-type-map.d.ts +8 -0
  31. package/{src/event-type-map.ts → dist/event-type-map.js} +1 -16
  32. package/dist/executor-brand.d.ts +8 -0
  33. package/dist/executor-brand.js +1 -0
  34. package/dist/extension-options-map.d.ts +9 -0
  35. package/dist/extension-options-map.js +4 -0
  36. package/dist/feature.d.ts +518 -0
  37. package/dist/feature.js +1 -0
  38. package/dist/field-icon.d.ts +1 -0
  39. package/dist/field-icon.js +1 -0
  40. package/dist/fields.d.ts +729 -0
  41. package/dist/fields.js +50 -0
  42. package/dist/file-handle-types.d.ts +12 -0
  43. package/dist/file-handle-types.js +1 -0
  44. package/dist/file-provider-resolver-types.d.ts +3 -0
  45. package/dist/file-provider-resolver-types.js +1 -0
  46. package/dist/file-storage-provider-types.d.ts +17 -0
  47. package/dist/file-storage-provider-types.js +1 -0
  48. package/dist/geo-tz.d.ts +17 -0
  49. package/{src/geo-tz.ts → dist/geo-tz.js} +1 -20
  50. package/dist/handlers.d.ts +493 -0
  51. package/dist/handlers.js +49 -0
  52. package/dist/hook-phase.d.ts +1 -0
  53. package/dist/hook-phase.js +1 -0
  54. package/dist/hooks.d.ts +75 -0
  55. package/dist/hooks.js +1 -0
  56. package/dist/http-route.d.ts +52 -0
  57. package/dist/http-route.js +13 -0
  58. package/dist/identifiers.d.ts +8 -0
  59. package/{src/identifiers.ts → dist/identifiers.js} +7 -24
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +1 -0
  62. package/dist/kms-adapter-types.d.ts +68 -0
  63. package/dist/kms-adapter-types.js +49 -0
  64. package/dist/logger.d.ts +7 -0
  65. package/dist/logger.js +1 -0
  66. package/dist/multi-stream-apply-context-types.d.ts +18 -0
  67. package/dist/multi-stream-apply-context-types.js +1 -0
  68. package/dist/nav-icon.d.ts +3 -0
  69. package/dist/nav-icon.js +100 -0
  70. package/dist/nav.d.ts +39 -0
  71. package/dist/nav.js +1 -0
  72. package/dist/observability/index.d.ts +3 -0
  73. package/dist/observability/index.js +2 -0
  74. package/dist/observability/metric.d.ts +34 -0
  75. package/dist/observability/metric.js +3 -0
  76. package/dist/observability/provider.d.ts +24 -0
  77. package/dist/observability/provider.js +4 -0
  78. package/dist/observability/span.d.ts +32 -0
  79. package/dist/observability/span.js +4 -0
  80. package/dist/ownership.d.ts +33 -0
  81. package/dist/ownership.js +5 -0
  82. package/dist/projection.d.ts +38 -0
  83. package/dist/projection.js +1 -0
  84. package/dist/rate-limit-types.d.ts +19 -0
  85. package/dist/rate-limit-types.js +1 -0
  86. package/dist/relations.d.ts +25 -0
  87. package/dist/relations.js +1 -0
  88. package/dist/schema-table-types.d.ts +15 -0
  89. package/{src/schema-table-types.ts → dist/schema-table-types.js} +0 -20
  90. package/dist/screen.d.ts +1265 -0
  91. package/dist/screen.js +3 -0
  92. package/dist/search-adapter.d.ts +32 -0
  93. package/dist/search-adapter.js +1 -0
  94. package/dist/secrets-types.d.ts +52 -0
  95. package/dist/secrets-types.js +30 -0
  96. package/dist/snapshot-types.d.ts +13 -0
  97. package/dist/snapshot-types.js +1 -0
  98. package/dist/step.d.ts +304 -0
  99. package/dist/step.js +11 -0
  100. package/dist/target-ref.d.ts +5 -0
  101. package/{src/target-ref.ts → dist/target-ref.js} +1 -6
  102. package/dist/tenancy-brand.d.ts +6 -0
  103. package/dist/tenancy-brand.js +1 -0
  104. package/dist/tenant-db-types.d.ts +67 -0
  105. package/dist/tenant-db-types.js +5 -0
  106. package/dist/tree-node.d.ts +26 -0
  107. package/dist/tree-node.js +22 -0
  108. package/dist/tz-context.d.ts +48 -0
  109. package/dist/tz-context.js +6 -0
  110. package/dist/websocket-route.d.ts +46 -0
  111. package/dist/websocket-route.js +10 -0
  112. package/dist/where-clause-types.d.ts +20 -0
  113. package/dist/where-clause-types.js +1 -0
  114. package/dist/workspace.d.ts +10 -0
  115. package/dist/workspace.js +1 -0
  116. package/dist/write-error-info-types.d.ts +12 -0
  117. package/dist/write-error-info-types.js +1 -0
  118. package/package.json +372 -124
  119. package/src/changes.json +18 -0
  120. package/src/__tests__/handlers.test.ts +0 -40
  121. package/src/__tests__/plural-forms.test.ts +0 -18
  122. package/src/action-icon.ts +0 -57
  123. package/src/concurrency-mode.ts +0 -5
  124. package/src/config-scope.ts +0 -5
  125. package/src/config.ts +0 -563
  126. package/src/cursor-types.ts +0 -18
  127. package/src/db-connection.ts +0 -25
  128. package/src/define-handler.ts +0 -138
  129. package/src/derivatives-types.ts +0 -106
  130. package/src/entity-cache.ts +0 -35
  131. package/src/entity-handlers.ts +0 -68
  132. package/src/entity-table-meta-types.ts +0 -101
  133. package/src/envelope-cipher-types.ts +0 -6
  134. package/src/event-store-executor-types.ts +0 -163
  135. package/src/event-store-types.ts +0 -85
  136. package/src/executor-brand.ts +0 -19
  137. package/src/extension-options-map.ts +0 -21
  138. package/src/feature.ts +0 -1141
  139. package/src/field-icon.ts +0 -23
  140. package/src/fields.ts +0 -1114
  141. package/src/file-handle-types.ts +0 -20
  142. package/src/file-provider-resolver-types.ts +0 -7
  143. package/src/file-storage-provider-types.ts +0 -54
  144. package/src/handlers.ts +0 -1246
  145. package/src/hook-phase.ts +0 -2
  146. package/src/hooks.ts +0 -170
  147. package/src/http-route.ts +0 -78
  148. package/src/kms-adapter-types.ts +0 -128
  149. package/src/logger.ts +0 -7
  150. package/src/multi-stream-apply-context-types.ts +0 -52
  151. package/src/nav-icon.ts +0 -105
  152. package/src/nav.ts +0 -139
  153. package/src/observability/index.ts +0 -28
  154. package/src/observability/metric.ts +0 -56
  155. package/src/observability/provider.ts +0 -32
  156. package/src/observability/span.ts +0 -58
  157. package/src/ownership.ts +0 -83
  158. package/src/projection.ts +0 -170
  159. package/src/rate-limit-types.ts +0 -32
  160. package/src/relations.ts +0 -52
  161. package/src/screen.ts +0 -1593
  162. package/src/search-adapter.ts +0 -45
  163. package/src/secrets-types.ts +0 -182
  164. package/src/snapshot-types.ts +0 -36
  165. package/src/step.ts +0 -390
  166. package/src/tenancy-brand.ts +0 -9
  167. package/src/tenant-db-types.ts +0 -116
  168. package/src/tree-node.ts +0 -134
  169. package/src/tz-context.ts +0 -63
  170. package/src/websocket-route.ts +0 -68
  171. package/src/where-clause-types.ts +0 -31
  172. package/src/workspace.ts +0 -42
  173. package/src/write-error-info-types.ts +0 -20
  174. /package/{src/index.ts → dist/concurrency-mode.js} +0 -0
package/src/nav.ts DELETED
@@ -1,139 +0,0 @@
1
- import type { AccessRule } from "./handlers";
2
- import type { NavIconKey } from "./nav-icon";
3
- import type { TargetRef } from "./target-ref";
4
- import type { TreeAction } from "./tree-node";
5
-
6
- export type { IconKey, NavIconKey } from "./nav-icon";
7
-
8
- // Nav entry declaration. Every feature that wants to appear in the app's
9
- // navigation tree registers one or more entries via r.nav(). The engine
10
- // keeps the list flat — ui-core's resolveNavigation assembles the parent/
11
- // child tree at render time, so changes (toggles, access-gating) don't
12
- // require re-indexing a tree shape server-side.
13
- //
14
- // Cross-feature references are allowed: `screen` may point at any
15
- // registered screen QN, `parent` at any registered nav QN. The boot
16
- // validator checks both references exist + rejects parent cycles.
17
- export type NavDefinition = {
18
- // Feature author writes the feature-local short id ("catalog"); the
19
- // registry overwrites `id` with the qualified name ("shop:nav:catalog")
20
- // in its stored copy. Callers of `registry.getNav(qn)` /
21
- // `getTopLevelNavs()` / `getNavsByParent(...)` always see the qualified
22
- // id — no parallel reverse index needed. `feature.navs[shortId]` on the
23
- // unregistered FeatureDefinition keeps the short form.
24
- readonly id: string;
25
- // i18n translation key. Resolved at render time by the renderer's
26
- // useTranslation hook; engine keeps it opaque.
27
- readonly label: string;
28
- // Icon key from the closed NavIconKey vocabulary (see nav-icon.ts). Every
29
- // renderer's icon map is checked against the same union, so a typo'd key
30
- // is a compile error here rather than a missing icon at runtime.
31
- readonly icon?: NavIconKey;
32
- // Qualified name of a parent nav entry ("<feature>:nav:<id>"). Omit for
33
- // top-level entries. Boot-validator rejects cycles + dangling refs.
34
- readonly parent?: string;
35
- // Sort weight within the parent's children (lower = earlier). Ties are
36
- // broken by registration order — features registered later appear lower.
37
- readonly order?: number;
38
- // Qualified name of the screen this entry navigates to
39
- // ("<feature>:screen:<id>"). Omit for pure grouping entries (a parent-only
40
- // nav node that renders a sub-tree but has no target screen itself).
41
- readonly screen?: string;
42
- // Polymorphes Klick-Ziel (öffnet die EditorPanel-Maske via Target-
43
- // Resolver) — Alternative zu `screen`. Ein Knoten trägt screen XOR
44
- // target; der Renderer dispatcht das target statt einen Route-Link zu
45
- // rendern. Gespiegelt aus dem alten Visual-Tree (TreeNode.target).
46
- readonly target?: TargetRef;
47
- // Hover-Actions rechts in der Zeile (VS-Code-Pattern) — erst bei Hover
48
- // sichtbar. Reihenfolge wie deklariert.
49
- readonly actions?: readonly TreeAction[];
50
- // "+" affordance on the node. Click navigates to createAction.screen or
51
- // dispatches createAction.target; the provider knows what "create empty"
52
- // means for it (new page slug, etc.).
53
- readonly createAction?: TreeAction;
54
- // Children kommen zur Laufzeit aus einem registrierten nav-provider
55
- // (lazy beim Ausklappen, SSE-live via treeEntities), keyed auf diese
56
- // Nav-QN. Macht den Knoten expandable auch ohne statische children.
57
- readonly provider?: boolean;
58
- // Role / openToAll gate. The nav resolver hides entries the user can't
59
- // reach; leave unset to always show (engine stays un-opinionated about
60
- // who sees what — apps that need default-deny can set { roles: [] }).
61
- // If `screen` is set and `access` is left unset, the client-side nav
62
- // builder (buildNavRegistrySliceForApp) fills this in from the target
63
- // screen's own `access` — a nav entry never invites a role into a 403.
64
- // An explicit `access` here always wins over the screen's.
65
- readonly access?: AccessRule;
66
- // Workspace QNs this entry self-assigns to. Merged at boot with any
67
- // r.workspace({ nav: [...] }) explicit lists. Omit to leave workspace
68
- // membership decided solely by the workspace's nav list (or both empty
69
- // → entry belongs to no workspace).
70
- readonly workspaces?: readonly string[];
71
- };
72
-
73
- // A feature's content collection — a set of template-resources of one `kind`,
74
- // mounted in the nav next to the feature it belongs to rather than under a
75
- // central "Content" section. Declared via r.contentCollection(), which
76
- // registers the nav entry (always `provider: true`, the tree children arrive
77
- // at runtime) and records the `kind` so the client can build the matching tree
78
- // provider without the app repeating it.
79
- //
80
- // `parent` may point at another feature's nav QN; the boot validator rejects
81
- // dangling refs, so a collection mounted under a feature that isn't mounted
82
- // fails boot instead of silently disappearing from the sidebar.
83
- /** Client editor format for r.contentCollection() — not template body storage formats. */
84
- export type ContentEditorFormat = "plain" | "rich" | "markdown";
85
-
86
- export type ContentCollectionDefinition = {
87
- // Feature-local short id, kebab-case. Also becomes the nav entry's id, so
88
- // it must not collide with an r.nav()/r.screen() id in the same feature.
89
- // Handlers take this id, not a kind — a payload can therefore only ever
90
- // address a declared collection, with the rules that were declared for it.
91
- readonly id: string;
92
- // Which template-resource kind this collection lists ("mail-html",
93
- // "document-pdf", "text-block", ...). The engine keeps it opaque —
94
- // bundled-features owns the kind vocabulary. Two collections may share a
95
- // kind and still differ in access and ownership.
96
- readonly kind: string;
97
- // Who may read and write this collection's entries. Declared at mount time
98
- // by the app, because a bundled feature cannot know the host's role
99
- // vocabulary — same reasoning as the `access` option on tags/folders/ledger.
100
- // Omitted means the mounting app didn't decide; the feature's own default
101
- // applies.
102
- readonly access?: AccessRule;
103
- // "tenant": one set of entries shared by everyone in the tenant (reply
104
- // snippets an admin curates). "user": every user keeps their own (mail
105
- // signatures). Defaults to "tenant".
106
- readonly ownership?: "tenant" | "user";
107
- // Which editor the client renders for this collection's entries — not how
108
- // the content is stored. "rich" still stores HTML, because mail and PDF
109
- // rendering want HTML either way. "markdown" stores markdown text, not
110
- // HTML. Defaults to "plain" (textarea).
111
- readonly contentFormat?: ContentEditorFormat;
112
- // Fixed variable names the collection's editor offers as insertable chips,
113
- // mapped to an example value the Preview substitutes in for `{{name}}`
114
- // (e.g. `{ customerName: "Max Mustermann", orderId: "A-1042" }` for an
115
- // ai-prompt collection). Declared once per collection, not per entry — a
116
- // collection-set write always persists an entry's own `variableSchema` as
117
- // `{}` (collections never let a user redefine the variable set), so this
118
- // is the only place the client can learn which variables exist and what
119
- // their preview values are.
120
- readonly variableSchema?: Readonly<Record<string, string>>;
121
- readonly nav: {
122
- readonly label: string;
123
- readonly icon?: NavIconKey;
124
- readonly parent?: string;
125
- readonly order?: number;
126
- // Visibility of the nav node. Leave unset — it then follows the
127
- // collection's `access`, so the sidebar never offers a node whose
128
- // contents the handler will refuse. Set it only to hide the node from
129
- // someone who may still reach the data another way.
130
- readonly access?: AccessRule;
131
- readonly workspaces?: readonly string[];
132
- // "+" affordance on the node and hover actions on the row — same meaning
133
- // as on NavDefinition. Without a createAction a collection can only list
134
- // what already exists; the target is usually the owning feature's
135
- // r.treeActions create.
136
- readonly createAction?: TreeAction;
137
- readonly actions?: readonly TreeAction[];
138
- };
139
- };
@@ -1,28 +0,0 @@
1
- // Barrel for observability types. Split into span/metric/provider so each module stays focused.
2
-
3
- export type {
4
- Counter,
5
- Gauge,
6
- Histogram,
7
- Meter,
8
- MetricDefinition,
9
- MetricLabels,
10
- MetricsHandle,
11
- MetricType,
12
- } from "./metric";
13
- export type {
14
- ObservabilityOptions,
15
- ObservabilityProvider,
16
- SamplingConfig,
17
- SensitiveFilterConfig,
18
- } from "./provider";
19
- export type {
20
- SerializedTraceContext,
21
- Span,
22
- SpanAttributes,
23
- SpanAttributeValue,
24
- SpanKind,
25
- SpanStatus,
26
- StartSpanOptions,
27
- Tracer,
28
- } from "./span";
@@ -1,56 +0,0 @@
1
- // Metric + Meter contract. Feature code interacts through ctx.metrics
2
- // (MetricsHandle); the framework wires Counter/Histogram/Gauge behind that.
3
-
4
- export type MetricLabels = Record<string, string | number | boolean>;
5
-
6
- export type MetricType = "counter" | "histogram" | "gauge";
7
-
8
- export type MetricDefinition = {
9
- // Fully-qualified name (with kumiko_<feature>_ prefix already applied).
10
- readonly name: string;
11
- readonly type: MetricType;
12
- readonly description?: string;
13
- // Declared label keys. Inc/observe calls with unknown label keys throw.
14
- readonly labels?: readonly string[];
15
- // Buckets only for histogram. If omitted, provider-default is used.
16
- readonly buckets?: readonly number[];
17
- readonly unit?: string;
18
- // If true, the framework auto-injects tenant_id from the active ctx.
19
- // Default false — adding tenant_id multiplies cardinality by tenant count.
20
- readonly tenantLabel?: boolean;
21
- };
22
-
23
- export interface Counter {
24
- inc(value?: number, labels?: MetricLabels): void;
25
- }
26
-
27
- export interface Histogram {
28
- observe(value: number, labels?: MetricLabels): void;
29
- }
30
-
31
- export interface Gauge {
32
- set(value: number, labels?: MetricLabels): void;
33
- inc(value?: number, labels?: MetricLabels): void;
34
- dec(value?: number, labels?: MetricLabels): void;
35
- }
36
-
37
- export interface Meter {
38
- // Called once per metric during boot. Duplicate names throw.
39
- registerMetric(def: MetricDefinition): void;
40
- // Lookup by fully-qualified name. Unknown names throw — typed access only.
41
- counter(name: string): Counter;
42
- histogram(name: string): Histogram;
43
- gauge(name: string): Gauge;
44
- // List of registered definitions — used by ctx.metrics to validate labels.
45
- definitions(): ReadonlyMap<string, MetricDefinition>;
46
- }
47
-
48
- // Public handle for feature code — ctx.metrics.
49
- // Name resolution uses the fully-qualified name (kumiko_<feature>_<short>).
50
- // The registrar resolves the short name from the calling feature context
51
- // at boot time; at handler time the map is ready.
52
- export interface MetricsHandle {
53
- inc(name: string, labels?: MetricLabels, value?: number): void;
54
- observe(name: string, value: number, labels?: MetricLabels): void;
55
- set(name: string, value: number, labels?: MetricLabels): void;
56
- }
@@ -1,32 +0,0 @@
1
- // Observability provider contract — the "plug" that implementations (noop,
2
- // console, otlp, prometheus) fulfil. Configuration types that consumers
3
- // (buildServer, setupTestStack) hand in also live here.
4
-
5
- import type { Meter } from "./metric";
6
- import type { Tracer } from "./span";
7
-
8
- export type SamplingConfig = {
9
- // Base sampling rate 0..1. Default 1 in v1 (sample everything).
10
- readonly tracing?: number;
11
- readonly alwaysOnError?: boolean;
12
- readonly alwaysOnSlow?: { readonly thresholdMs: number };
13
- };
14
-
15
- export type SensitiveFilterConfig = {
16
- readonly redactedHeaders: readonly string[];
17
- readonly redactedQueryParams: readonly string[];
18
- readonly redactedAttributeKeyPatterns: readonly RegExp[];
19
- };
20
-
21
- export type ObservabilityOptions = {
22
- readonly sampling?: SamplingConfig;
23
- readonly sensitiveFilter?: Partial<SensitiveFilterConfig>;
24
- };
25
-
26
- export interface ObservabilityProvider {
27
- readonly name: string;
28
- readonly tracer: Tracer;
29
- readonly meter: Meter;
30
- // Graceful flush. Called from framework lifecycle shutdown.
31
- shutdown(): Promise<void>;
32
- }
@@ -1,58 +0,0 @@
1
- // Span + Tracer contract. Provider implementations (noop, recording → console/otlp)
2
- // all speak this — everything else (middleware, dispatcher, db, redis, jobs)
3
- // is provider-agnostic.
4
-
5
- export type SpanAttributeValue = string | number | boolean;
6
- export type SpanAttributes = Record<string, SpanAttributeValue>;
7
-
8
- export type SpanStatus = "unset" | "ok" | "error";
9
-
10
- export type SpanKind = "internal" | "server" | "client" | "producer" | "consumer";
11
-
12
- // Serialized form of a trace context — what we pass across process boundaries
13
- // (outbox row, BullMQ job payload). Matches W3C trace-context spec loosely,
14
- // but staying minimal — a full W3C parser is v2.
15
- export type SerializedTraceContext = {
16
- readonly traceId: string;
17
- readonly spanId: string;
18
- readonly baggage?: Readonly<Record<string, string>>;
19
- };
20
-
21
- export type StartSpanOptions = {
22
- // Either a live Span (normal in-process parent) or a serialized trace
23
- // context (cross-process — outbox row, job payload). Both carry traceId
24
- // and spanId, so the tracer reads them uniformly. Omitted → fall back to
25
- // the AsyncLocalStorage active span.
26
- readonly parent?: Span | SerializedTraceContext;
27
- readonly attributes?: SpanAttributes;
28
- readonly kind?: SpanKind;
29
- readonly startTime?: number;
30
- };
31
-
32
- export interface Span {
33
- readonly traceId: string;
34
- readonly spanId: string;
35
- readonly parentSpanId: string | undefined;
36
- readonly name: string;
37
- setAttribute(key: string, value: SpanAttributeValue): void;
38
- setAttributes(attrs: SpanAttributes): void;
39
- setStatus(status: SpanStatus, message?: string): void;
40
- recordException(error: Error): void;
41
- end(endTime?: number): void;
42
- // Whether end() has been called. Idempotency guard for auto-wrappers.
43
- readonly ended: boolean;
44
- }
45
-
46
- export interface Tracer {
47
- startSpan(name: string, options?: StartSpanOptions): Span;
48
- // Runs fn inside the span context (AsyncLocalStorage), ends the span
49
- // automatically — including on thrown errors, where the error is recorded
50
- // and status set to "error" before re-throwing.
51
- withSpan<T>(
52
- name: string,
53
- optionsOrFn: StartSpanOptions | ((span: Span) => Promise<T>),
54
- fn?: (span: Span) => Promise<T>,
55
- ): Promise<T>;
56
- // Current active span from AsyncLocalStorage, or undefined.
57
- getActiveSpan(): Span | undefined;
58
- }
package/src/ownership.ts DELETED
@@ -1,83 +0,0 @@
1
- // --- Ownership ---
2
- // Pure types for the declarative Claims → Access bridge. Runtime (from(),
3
- // matchesRule(), buildOwnershipClause()) stays in engine/ownership.ts, which
4
- // re-exports these for backwards compatibility.
5
-
6
- import type { SessionUser } from "./handlers";
7
-
8
- // Parameterised SQL fragment — produced by buildOwnershipClause + by the
9
- // WhereRule escape-hatch. Caller weaves `sqlText` into a larger statement,
10
- // renumbering placeholders if needed (shiftParams in engine/ownership.ts).
11
- export type SqlFragment = {
12
- readonly sqlText: string;
13
- readonly params: readonly unknown[];
14
- };
15
-
16
- // Reference spec supported by `from()`:
17
- // "user:id" → user.id
18
- // "user:tenantId" → user.tenantId (rarely needed — TenantDb scopes anyway)
19
- // "claim:<featureName>:<key>" → user.claims["<featureName>:<key>"]
20
- //
21
- // The string form is keyed so the framework can look up the referenced
22
- // Registry entry at boot (Claim-QN exists? Column type compatible?). A typed
23
- // object form would force features to import each other's handles — the
24
- // whole point of H.2's unified path is string-based references, no imports.
25
- export type OwnershipRef = string;
26
-
27
- // Resolved during `from()` — the parser eagerly splits the prefix so the
28
- // runtime evaluator avoids string-parsing on every row. `kind` drives the
29
- // evaluator branch; the rest is the resolved metadata.
30
- export type FromRuleKind = "user" | "claim";
31
-
32
- export type FromRule = {
33
- readonly kind: "from";
34
- readonly refKind: FromRuleKind;
35
- // For "user:id" → "id"; for "user:tenantId" → "tenantId".
36
- // For "claim:<featureName>:<key>" → "<featureName>:<key>" (the full QN,
37
- // which is exactly the key under which the JWT stores the value).
38
- readonly refPath: string;
39
- // Row-column to match against. For claim rules defaults to the claim's
40
- // shortName (second segment of the claim QN). For user-rules the column
41
- // is always explicit.
42
- readonly column: string;
43
- };
44
-
45
- // Context passed to a WhereRule escape-hatch. The author returns a SqlFragment
46
- // whose placeholders start at `paramStart` ($N, $N+1, ...); the framework
47
- // concatenates the fragment into the larger query.
48
- export type WhereRuleContext<TTable = unknown> = {
49
- readonly table: TTable;
50
- readonly tableName: string;
51
- readonly paramStart: number;
52
- };
53
-
54
- export type WhereRule<TTable = unknown> = {
55
- readonly kind: "where";
56
- readonly where: (user: SessionUser, ctx: WhereRuleContext<TTable>) => SqlFragment;
57
- };
58
-
59
- // "all" collapses to a primitive so map authors can write `Admin: "all"`
60
- // without importing a helper.
61
- export type OwnershipRule = "all" | FromRule | WhereRule;
62
-
63
- // Per-role map: every key is a role name, value is the rule that role
64
- // satisfies to pass the access check.
65
- export type OwnershipMap = Readonly<Record<string, OwnershipRule>>;
66
-
67
- // Result of buildOwnershipClause. The discriminant lets the caller handle
68
- // the three outcomes without inspecting SQL internals:
69
- //
70
- // "pass" → user is unrestricted. Run the query as-is.
71
- // "empty" → user has a role mapped but no rule accepts any row (missing
72
- // claim, empty array, role not in map). Skip the DB call entirely
73
- // — returning [] is equivalent and avoids a pointless roundtrip.
74
- // "sql" → apply the parameterised fragment as an AND on the query.
75
- // Caller is responsible for renumbering placeholders when
76
- // concatenating with other fragments (see `shiftParams`).
77
- //
78
- // "empty" vs. "pass" is the critical distinction for a safe default:
79
- // undefined/pass = allow, empty = deny-by-construction.
80
- export type OwnershipClause =
81
- | { readonly kind: "pass" }
82
- | { readonly kind: "empty" }
83
- | { readonly kind: "sql"; readonly sqlText: string; readonly params: readonly unknown[] };
package/src/projection.ts DELETED
@@ -1,170 +0,0 @@
1
- import type { RunIn } from "./config";
2
- import type { DbRunner } from "./db-connection";
3
- import type { StoredEvent } from "./event-store-types";
4
- import type { EntityDefinition } from "./fields";
5
- import type { MultiStreamApplyContext } from "./multi-stream-apply-context-types";
6
- import type { SchemaTable } from "./schema-table-types";
7
-
8
- // Drizzle pgTable shape — projections hand their table through to apply() so
9
- // user code writes upserts/updates directly instead of going through a
10
- // framework-managed state reducer. Using the native dialect's `SchemaTable`
11
- // (drizzle-compat surface) keeps typing honest: typed paths work inside
12
- // apply(), but the column union is erased so framework code doesn't need
13
- // to know the schema shape of every user table.
14
- export type ProjectionTable = SchemaTable;
15
-
16
- // Single-stream projection apply: runs inline in the write-TX of the event
17
- // it projects. Gets the event, the TX-scoped DbRunner, and the projection's
18
- // own `table` (already erased to ProjectionTable). Write through THAT table —
19
- // it is the only ES-blessed write into a managed projection outside the
20
- // executor, and it is reachable only here (an arbitrary handler has no such
21
- // arg), so the write-brand cannot be bypassed by closing over the branded
22
- // table constant. Inline projections must not spawn further events (no ctx)
23
- // because they run inside the command's transaction and the framework
24
- // guarantees a single commit boundary per command.
25
- //
26
- // Generic über payload-shape. Default = Record<string, unknown> behält
27
- // rückwärtskompatibles Verhalten; Konkrete Apply-Handler annotieren
28
- // `SingleStreamApplyFn<MyPayload>` für typed event.payload-Access. Der
29
- // `table`-Param ist additiv — 2-arg-Applies (event, tx) bleiben gültig.
30
- export type SingleStreamApplyFn<TPayload = Record<string, unknown>> = (
31
- event: StoredEvent<TPayload>,
32
- tx: DbRunner,
33
- table: ProjectionTable,
34
- ) => Promise<void>;
35
-
36
- // Multi-stream projection apply: runs asynchronously via the event-dispatcher
37
- // with its own cursor. Gets the event, tx, and a ctx surface for emitting
38
- // follow-up events (saga / process-manager pattern). ctx.appendEvent +
39
- // ctx.loadAggregate are the Marten-equivalent of IProjectionSession — write
40
- // cross-aggregate reactions here, not in single-stream projections.
41
- export type MultiStreamApplyFn<TPayload = Record<string, unknown>> = (
42
- event: StoredEvent<TPayload>,
43
- tx: DbRunner,
44
- ctx: MultiStreamApplyContext,
45
- ) => Promise<void>;
46
-
47
- export type ProjectionDefinition = {
48
- readonly name: string;
49
- // One or more entity names whose events feed this projection. Event-types
50
- // are matched in `apply` (e.g. "unit.created") — `source` is only used to
51
- // index projections so the executor doesn't scan all projections on every
52
- // write.
53
- readonly source: string | readonly string[];
54
- // Additional aggregate-types whose events the rebuild replay must include
55
- // beyond `source`. Fed by r.extendEntityProjection — an extension can react
56
- // to events on foreign streams (e.g. "field-definition") while `source`
57
- // keeps meaning "the owning entity" for consumers like soft-delete-cleanup.
58
- readonly extraSources?: readonly string[];
59
- // Drizzle-table the projection materializes into. User owns the schema —
60
- // framework just guarantees the TX and event delivery.
61
- readonly table: ProjectionTable;
62
- // Optional: the EntityDefinition the table was built from, for projections
63
- // without an r.entity registration — lets boot-time GDPR guards see
64
- // pii/tenantOwned fields that feature.entities (r.entity-only) would miss.
65
- readonly entity?: EntityDefinition;
66
- // Keyed by fully-qualified event type ("<aggregate>.<verb>", e.g. "unit.created").
67
- // Missing keys are silently skipped — a projection declares only the events it
68
- // cares about.
69
- readonly apply: Readonly<Record<string, SingleStreamApplyFn>>;
70
- // Auto-registered projection (one per r.entity) that exists ONLY to
71
- // make rebuildProjection work for entity-tables. Live writes go through
72
- // the EventStoreExecutor directly — firing the implicit apply inline
73
- // would double-write into the same table. The inline-projection-runner
74
- // skips entries with this flag; rebuildProjection treats them
75
- // identically to explicit projections.
76
- readonly isImplicit?: boolean;
77
- };
78
-
79
- // Extension merged into an entity's implicit projection at registry build.
80
- // Lets a bundled feature that writes into the HOST entity's table via events
81
- // (custom-fields pattern) hook those event types into the entity's rebuild
82
- // replay — without it, a rebuild resets everything the extension wrote.
83
- // Live delivery stays with the extension's own MSP: implicit projections are
84
- // skipped by the inline runner, so the apply here runs ONLY during rebuild.
85
- export type EntityProjectionExtension = {
86
- // Aggregate-types beyond the entity's own stream whose events the rebuild
87
- // must scan (e.g. "field-definition"). Omit when all extension events are
88
- // appended on the host entity's stream.
89
- readonly sources?: readonly string[];
90
- // Keyed by fully-qualified event type. Must not collide with the entity's
91
- // built-in lifecycle applies (<entity>.created/updated/...) or another
92
- // extension — collisions fail at boot.
93
- readonly apply: Readonly<Record<string, SingleStreamApplyFn>>;
94
- };
95
-
96
- // Per-lifecycle error policy for a MultiStreamProjection. Mirrors Marten's
97
- // Projections.Errors / Projections.RebuildErrors split — a projection can
98
- // be lenient during steady-state delivery but strict during rebuild (or
99
- // vice versa).
100
- export type MspErrorPolicy = {
101
- // When the apply handler throws: log the error, advance the cursor past
102
- // the offending event, and keep delivering. Default false — current
103
- // strict behaviour: retry up to maxAttempts, then mark the consumer
104
- // status="dead" and pause delivery. Use for best-effort sinks
105
- // (notifications, webhooks) where a single bad event should not stall
106
- // the whole consumer.
107
- readonly skipApplyErrors?: boolean;
108
- };
109
-
110
- export type MspErrorMode = {
111
- // Applied during steady-state dispatcher delivery.
112
- readonly continuous?: MspErrorPolicy;
113
- // Applied during rebuildProjection() / backfill passes. When omitted,
114
- // rebuild inherits continuous — explicit override common for "strict
115
- // during rebuild, lenient in production" patterns.
116
- readonly rebuild?: MspErrorPolicy;
117
- };
118
-
119
- // Marten-style MultiStreamProjection: aggregates events from many streams
120
- // into one cross-cutting read-model. Unlike ProjectionDefinition (single-
121
- // source, inline in the write-TX), an MSP is ASYNC — the event-dispatcher
122
- // picks events off the log via its own cursor. Handlers MUST be idempotent
123
- // because the dispatcher guarantees at-least-once delivery.
124
- //
125
- // Use for Sagas / process managers, customer-centric views that span
126
- // multiple aggregate types, cross-feature aggregations, audit logs. With
127
- // `table` omitted, the MSP becomes a pure side-effect consumer — sending
128
- // notifications, posting webhooks, updating an external system. Marten's
129
- // equivalent of a subscription / event listener, without a separate API.
130
- export type MultiStreamProjectionDefinition = {
131
- readonly name: string;
132
- // Optional: omit for side-effect-only handlers (notifications, external
133
- // system sync). When present, setupTestStack auto-pushes the table.
134
- readonly table?: ProjectionTable;
135
- // Keyed by fully-qualified event type. Unlike a single-stream projection,
136
- // there is no source-entity hint — the MSP declares the event types it
137
- // cares about directly. Extract the identity/grouping key inside the
138
- // apply handler from the event payload.
139
- readonly apply: Readonly<Record<string, MultiStreamApplyFn>>;
140
- // How the dispatcher handles apply-throws. Default strict (retry + dead).
141
- readonly errorMode?: MspErrorMode;
142
- // Which deploy-lane runs this MSP's dispatcher. Default "worker". MSPs
143
- // share a single consumer-row per MSP name with SKIP LOCKED, so "both"
144
- // is safe semantically (API + Worker race for each event; exactly one
145
- // wins). Use "api" for MSPs that need in-process state on the API
146
- // (rare); use "both" only when genuinely load-balancing is helpful.
147
- readonly runIn?: RunIn;
148
- // Delivery semantics across multi-instance deploys:
149
- // "shared" (default) — one cursor across all dispatcher instances,
150
- // SKIP LOCKED serialises; each event delivered exactly
151
- // once globally. The right choice for side-effects with
152
- // any downstream state: notifications, external APIs,
153
- // projection tables, audit rows.
154
- // "per-instance" — one cursor PER dispatcher instance, so every process
155
- // delivers every event. Required for push-to-local-
156
- // subscribers (SSE, in-memory caches): a split-deploy
157
- // where API instance B emits an event that API instance
158
- // A's clients also need to see. Handler MUST be
159
- // side-effect-free relative to the DB — it only reaches
160
- // in-process structures — otherwise each instance
161
- // writes duplicate rows. Misuse = duplicated side
162
- // effects, not a safety property.
163
- readonly delivery?: "shared" | "per-instance";
164
- // Where the consumer's cursor starts on its FIRST registration. Default
165
- // "beginning" replays the full log. "now" seeds the cursor at the current
166
- // MAX(events.id) so mounting the MSP into an existing app does not
167
- // retroactively fire side effects for historical events. Only affects the
168
- // first registration — an existing cursor row is never clobbered.
169
- readonly startFrom?: "beginning" | "now";
170
- };
@@ -1,32 +0,0 @@
1
- import type { Temporal } from "temporal-polyfill";
2
-
3
- export type RateLimitDecision = {
4
- readonly allowed: boolean;
5
- readonly limit: number;
6
- readonly remaining: number;
7
- readonly retryAfterSeconds: number;
8
- readonly windowSeconds: number;
9
- readonly resetAt: Temporal.Instant;
10
- };
11
-
12
- export type RateLimitConfig = {
13
- readonly limit: number;
14
- readonly windowSeconds: number;
15
- readonly cost?: number;
16
- };
17
-
18
- export type RateLimitResolver = {
19
- // Atomic check + deduct. Returns the decision and current bucket state
20
- // — caller decides whether to throw RateLimitError or proceed.
21
- check(bucket: string, config: RateLimitConfig): Promise<RateLimitDecision>;
22
-
23
- // Convenience: throws RateLimitError when blocked. Useful inside the
24
- // dispatcher / middleware code-paths where the failure shape is fixed.
25
- enforce(bucket: string, config: RateLimitConfig): Promise<RateLimitDecision>;
26
-
27
- // Read-only inspection: returns the same shape as check() but never
28
- // mutates the bucket — no token deduction, no refill-timestamp update.
29
- // Use for ops/status queries (e.g. "kumiko rl status user:42") that
30
- // must observe the bucket without disturbing it.
31
- peek(bucket: string, config: Omit<RateLimitConfig, "cost">): Promise<RateLimitDecision>;
32
- };
package/src/relations.ts DELETED
@@ -1,52 +0,0 @@
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";
5
-
6
- // --- Relations ---
7
-
8
- export type BelongsToRelation = {
9
- readonly type: "belongsTo";
10
- readonly target: string;
11
- readonly foreignKey: string;
12
- // onDelete is declared on the parent-side (hasMany / manyToMany) because
13
- // that's where the "what happens to my children?" decision lives. A
14
- // belongsTo node just points at a parent — the parent's onDelete drives
15
- // the cleanup.
16
- };
17
-
18
- export type HasManyRelation = {
19
- readonly type: "hasMany";
20
- readonly target: string;
21
- readonly foreignKey: string;
22
- readonly onDelete?: OnDeleteStrategy;
23
- // When true, a nested payload under this relation's key (e.g.
24
- // `{ tasks: [{ ... }] }` on a `project:create` write) is auto-expanded
25
- // into child writes: parent first, then one child-write per entry with
26
- // the foreign key set to the parent's new id — all in the same TX.
27
- // Opt-in (default false) so legacy hasMany relations that were declared
28
- // purely for cascade-delete or UI-nav semantics don't silently gain a
29
- // client-writable path. Children are never inferred from payload-shape
30
- // alone; only relations with this flag unlock nested-write.
31
- //
32
- // Scope v1: depth=1, create-only, hasMany-only. Update-nested,
33
- // delete-nested, and belongsTo/m2m auto-expansion are explicit future
34
- // work — when they arrive, they'll take the same flag so the opt-in
35
- // stays a single, consistent surface.
36
- readonly nestedWrite?: boolean;
37
- };
38
-
39
- export type ManyToManyRelation = {
40
- readonly type: "manyToMany";
41
- readonly target: string;
42
- readonly through: {
43
- readonly table: string;
44
- readonly sourceKey: string;
45
- readonly targetKey: string;
46
- };
47
- readonly onDelete?: OnDeleteStrategy;
48
- };
49
-
50
- export type RelationDefinition = BelongsToRelation | HasManyRelation | ManyToManyRelation;
51
-
52
- export type EntityRelations = Readonly<Record<string, RelationDefinition>>;