@cosmicdrift/kumiko-types 0.333.0 → 0.335.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/dist/config.d.ts +8 -4
- package/dist/feature.d.ts +1 -0
- package/dist/fields.d.ts +30 -4
- package/dist/fields.js +8 -0
- package/dist/screen.d.ts +32 -2
- package/package.json +1 -1
- package/src/changes.json +7 -0
package/dist/config.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ZodType } from "zod";
|
|
|
2
2
|
import type { ConcurrencyMode } from "./concurrency-mode.js";
|
|
3
3
|
import type { ConfigScope } from "./config-scope.js";
|
|
4
4
|
import type { DbConnection } from "./db-connection.js";
|
|
5
|
-
import type { FieldDefinition } from "./fields.js";
|
|
5
|
+
import type { FieldDefinition, OptionsQueryPayload } from "./fields.js";
|
|
6
6
|
import type { EscapeHatchDeclaration, JobContext } from "./handlers.js";
|
|
7
7
|
import type { PostDeleteHookFn, PostSaveHookFn, PreDeleteHookFn, PreQueryHookFn, PreSaveHookFn } from "./hooks.js";
|
|
8
8
|
import type { TenantId } from "./identifiers.js";
|
|
@@ -46,12 +46,14 @@ export type ConfigKeyDefinition<T extends ConfigKeyType = ConfigKeyType> = {
|
|
|
46
46
|
readonly piiEncrypted?: boolean;
|
|
47
47
|
readonly options?: readonly string[];
|
|
48
48
|
/** Only on `type: "select"`: loads the options from this query (QN), contract
|
|
49
|
-
* `{ rows: { value, label }[] }`, labels shown verbatim. Mutually exclusive with
|
|
49
|
+
* `{ rows: { value, label, description?, group? }[] }`, labels shown verbatim. Mutually exclusive with
|
|
50
50
|
* `options` and `allowPerRequest`. The write side does not check the value against
|
|
51
51
|
* the query result; the consuming feature validates it where it uses it. */
|
|
52
52
|
readonly optionsQuery?: string;
|
|
53
|
-
/**
|
|
54
|
-
|
|
53
|
+
/** Payload sent with every `optionsQuery` call. Requires `optionsQuery`. `{ field }`
|
|
54
|
+
* names another config key (short name) of the owner feature, resolved on the
|
|
55
|
+
* generated settings screen. */
|
|
56
|
+
readonly optionsQueryPayload?: OptionsQueryPayload;
|
|
55
57
|
readonly bounds?: ConfigBounds;
|
|
56
58
|
readonly pattern?: {
|
|
57
59
|
readonly regex: string;
|
|
@@ -68,6 +70,8 @@ export type ConfigKeyDefinition<T extends ConfigKeyType = ConfigKeyType> = {
|
|
|
68
70
|
};
|
|
69
71
|
export type ConfigMask = {
|
|
70
72
|
readonly title: string;
|
|
73
|
+
/** i18n key for help text shown under the field label. */
|
|
74
|
+
readonly description?: string;
|
|
71
75
|
readonly icon?: NavIconKey;
|
|
72
76
|
readonly order?: number;
|
|
73
77
|
};
|
package/dist/feature.d.ts
CHANGED
|
@@ -473,6 +473,7 @@ export type Registry = {
|
|
|
473
473
|
isHandlerSystemScoped(qualifiedHandler: string): boolean;
|
|
474
474
|
isJobSystemScoped(qualifiedJobName: string): boolean;
|
|
475
475
|
getHandlerFeature(qualifiedHandler: string): string | undefined;
|
|
476
|
+
getJobFeature(qualifiedJobName: string): string | undefined;
|
|
476
477
|
hasRateLimitedHandler(): boolean;
|
|
477
478
|
getAllMetrics(): ReadonlyMap<string, FeatureMetricDef & {
|
|
478
479
|
readonly featureName: string;
|
package/dist/fields.d.ts
CHANGED
|
@@ -89,6 +89,20 @@ export type TextFieldDef = {
|
|
|
89
89
|
readonly filterable?: boolean;
|
|
90
90
|
readonly encrypted?: boolean;
|
|
91
91
|
readonly sensitive?: boolean;
|
|
92
|
+
/** Write-only secret (API key): the value is never returned to clients. Reads
|
|
93
|
+
* (list/detail/write responses) show `true` = set, `null` = empty. Writes:
|
|
94
|
+
* `""` or omitted = unchanged, `null` = clear, string = new value.
|
|
95
|
+
* Server-side: executor reads (detail/list in server handlers) and
|
|
96
|
+
* postSave/postQuery hooks see the plaintext; ctx.query, dispatcher.query,
|
|
97
|
+
* agent tools and `_refs` see true/null; ctx.db sees the ciphertext.
|
|
98
|
+
* Known limit: masking runs for entity-bound query handlers with array /
|
|
99
|
+
* {rows} / flat results; an unbound custom query handler that returns
|
|
100
|
+
* executor rows must call maskWriteOnlyFields itself (same scope limit as
|
|
101
|
+
* access.read). Requires `sensitive` (via `find: "secret"`); forbidden with
|
|
102
|
+
* default/searchable/sortable/filterable/lookupable and on inline form fields
|
|
103
|
+
* (actionForm/wizard). Allowed on configEdit text fields only over an
|
|
104
|
+
* encrypted-at-rest config key, where it is also set automatically. */
|
|
105
|
+
readonly writeOnly?: boolean;
|
|
92
106
|
/** A later run reads this field's value as an instruction — prompt, rule,
|
|
93
107
|
* template. Every create/update whose payload writes it requires agent.risk
|
|
94
108
|
* "high" on the directly-dispatched entry handler; a revert doesn't undo a
|
|
@@ -158,6 +172,16 @@ export type BooleanFieldDef = {
|
|
|
158
172
|
readonly access?: FieldAccess;
|
|
159
173
|
};
|
|
160
174
|
export type SelectOptionTone = "ok" | "warn" | "bad" | "neutral";
|
|
175
|
+
/** One `optionsQueryPayload` entry: a literal, or `{ field }` = the current value of
|
|
176
|
+
* a sibling field of the same form (config keys: another key of the owner feature). */
|
|
177
|
+
export type OptionsQueryPayloadValue = string | number | boolean | {
|
|
178
|
+
readonly field: string;
|
|
179
|
+
};
|
|
180
|
+
export type OptionsQueryPayload = Readonly<Record<string, OptionsQueryPayloadValue>>;
|
|
181
|
+
export declare function isOptionsQueryFieldRef(value: OptionsQueryPayloadValue): value is {
|
|
182
|
+
readonly field: string;
|
|
183
|
+
};
|
|
184
|
+
export declare function optionsQueryFieldRefs(payload: OptionsQueryPayload | undefined): string[];
|
|
161
185
|
export type SelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
|
|
162
186
|
readonly type: "select";
|
|
163
187
|
readonly description?: string;
|
|
@@ -180,13 +204,15 @@ export type SelectFieldDef<TOptions extends readonly string[] = readonly string[
|
|
|
180
204
|
readonly optionTones?: {
|
|
181
205
|
readonly [K in TOptions[number]]?: SelectOptionTone;
|
|
182
206
|
};
|
|
183
|
-
/** Loads the options from this query (QN). Contract:
|
|
184
|
-
*
|
|
207
|
+
/** Loads the options from this query (QN). Contract:
|
|
208
|
+
* `{ rows: { value, label, description?, group? }[] }`, labels are shown verbatim
|
|
209
|
+
* (not translated); description is a muted second line, group a heading. `options` must be empty when set.
|
|
185
210
|
* Only valid on configEdit/actionForm screen fields and config keys, not on entity
|
|
186
211
|
* fields: the stored value would not be checked against the query result. */
|
|
187
212
|
readonly optionsQuery?: string;
|
|
188
|
-
/**
|
|
189
|
-
|
|
213
|
+
/** Payload sent with every `optionsQuery` call. `{ field }` entries re-load the
|
|
214
|
+
* options when that sibling field changes. */
|
|
215
|
+
readonly optionsQueryPayload?: OptionsQueryPayload;
|
|
190
216
|
} & ResolvedPiiFlags;
|
|
191
217
|
export type MultiSelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
|
|
192
218
|
readonly type: "multiSelect";
|
package/dist/fields.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// --- Field Types ---
|
|
2
|
+
export function isOptionsQueryFieldRef(value) {
|
|
3
|
+
return typeof value === "object" && value !== null;
|
|
4
|
+
}
|
|
5
|
+
export function optionsQueryFieldRefs(payload) {
|
|
6
|
+
return Object.values(payload ?? {})
|
|
7
|
+
.filter(isOptionsQueryFieldRef)
|
|
8
|
+
.map((ref) => ref.field);
|
|
9
|
+
}
|
|
2
10
|
/** Qualified config key a `{ kind: "tenant" }` MoneyCurrencySource resolves
|
|
3
11
|
* against — the tenant-settings bundle's per-tenant currency. Lives here
|
|
4
12
|
* (client-safe) rather than framework/engine so renderer code can read it
|
package/dist/screen.d.ts
CHANGED
|
@@ -115,12 +115,14 @@ export type ListColumnSpec = string | {
|
|
|
115
115
|
readonly hideOnNarrow?: boolean;
|
|
116
116
|
/** Dashboard list panels only. "bar": field holds a 0..1 fraction, drawn
|
|
117
117
|
* as bar + percent. "badge": field holds a label, drawn as a pill whose
|
|
118
|
-
* tone comes from `badgeToneField`.
|
|
118
|
+
* tone comes from `badgeToneField`. "datetime": field holds an ISO string or
|
|
119
|
+
* epoch ms, shown in the user's locale and time zone. Other list renderers
|
|
120
|
+
* ignore it. */
|
|
119
121
|
readonly display?: ListColumnDisplay;
|
|
120
122
|
/** Row field naming the badge tone; only with `display: "badge"`. */
|
|
121
123
|
readonly badgeToneField?: string;
|
|
122
124
|
};
|
|
123
|
-
export type ListColumnDisplay = "bar" | "badge";
|
|
125
|
+
export type ListColumnDisplay = "bar" | "badge" | "datetime";
|
|
124
126
|
export type ListBadgeTone = "positive" | "warn" | "negative" | "neutral";
|
|
125
127
|
export type ListPaginationMode = "pages" | "infinite" | false;
|
|
126
128
|
export type ListSortDir = "asc" | "desc";
|
|
@@ -194,6 +196,14 @@ export type RowActionWriteHandler = {
|
|
|
194
196
|
readonly icon?: IconKey;
|
|
195
197
|
/** Inline render form in the row-action column — see `RowActionDisplay`. */
|
|
196
198
|
readonly display?: RowActionDisplay;
|
|
199
|
+
/** Where to go after the write succeeded instead of staying on the shown
|
|
200
|
+
* record. Same forms as entityEdit `redirect`. Honored on record actions
|
|
201
|
+
* (projectionDetail header/section actions, entityEdit header/section
|
|
202
|
+
* actions); a valid `returnTo` wins under the same rule as
|
|
203
|
+
* entityEdit.redirect. Not used by list row actions. Without it, an action
|
|
204
|
+
* deleting the shown record (`<feature>:write:<entity>:delete` with that
|
|
205
|
+
* record's id) leaves to `returnTo`/the list; any other action refetches. */
|
|
206
|
+
readonly redirect?: string | ActionFormRedirect;
|
|
197
207
|
};
|
|
198
208
|
export type RowActionNavigateBase = {
|
|
199
209
|
readonly kind: "navigate";
|
|
@@ -735,6 +745,11 @@ export type DashboardScreenPanel = {
|
|
|
735
745
|
readonly screen: string;
|
|
736
746
|
readonly label?: string;
|
|
737
747
|
readonly visibleWhen?: DashboardPanelVisibility;
|
|
748
|
+
/** Render the embedded form without its own card frame and padding, aligned to
|
|
749
|
+
* the dashboard's page grid like a standalone settings screen. Default false
|
|
750
|
+
* (framed card); set for panels whose body is a settings-list form, where a
|
|
751
|
+
* card inside the page would double the inset. */
|
|
752
|
+
readonly chromeless?: boolean;
|
|
738
753
|
};
|
|
739
754
|
export type DashboardPanelDefinition = DashboardStatPanel | DashboardStatGroupPanel | DashboardChartPanel | DashboardListPanel | DashboardFeedPanel | DashboardProgressListPanel | DashboardCustomPanel | DashboardScreenPanel;
|
|
740
755
|
export type DashboardFilterDefinition = {
|
|
@@ -781,6 +796,10 @@ export type DashboardScreenDefinition = {
|
|
|
781
796
|
readonly timeRange?: DashboardTimeRangeDefinition;
|
|
782
797
|
/** Marks the screen as spanning more than the caller's own scope. */
|
|
783
798
|
readonly scope?: DashboardScopeDefinition;
|
|
799
|
+
/** Show the "Updated at" timestamp in the toolbar. Default true; turn off for
|
|
800
|
+
* dashboards that host forms rather than live metrics, where a load time
|
|
801
|
+
* next to the form reads as stale data. */
|
|
802
|
+
readonly showUpdatedAt?: boolean;
|
|
784
803
|
readonly slots?: ScreenSlots;
|
|
785
804
|
readonly access?: AccessRule;
|
|
786
805
|
};
|
|
@@ -1062,6 +1081,12 @@ export type EditLayout = {
|
|
|
1062
1081
|
* boot-validator rejects it on entityEdit, see the check for the reason);
|
|
1063
1082
|
* requires >= 2 sections, each with a title and an `id`. */
|
|
1064
1083
|
readonly mode?: "single" | "wizard" | "tabs";
|
|
1084
|
+
/** "settings-list" lays each section out as a band with a title column on
|
|
1085
|
+
* the left and one hairline-separated row per field (label + help left,
|
|
1086
|
+
* control right) — the familiar settings pattern, for screens that are a
|
|
1087
|
+
* list of independent preferences rather than one record form. Default
|
|
1088
|
+
* "form" keeps the grid of cells. */
|
|
1089
|
+
readonly variant?: "form" | "settings-list";
|
|
1065
1090
|
/** Persists in-progress wizard state as a resumable draft instead of
|
|
1066
1091
|
* discarding it on navigation away. */
|
|
1067
1092
|
readonly draft?: boolean;
|
|
@@ -1424,6 +1449,11 @@ export type ConfigEditScreenDefinition = {
|
|
|
1424
1449
|
* ohne es unter der `__config-edit__`-Konvention zu duplizieren.
|
|
1425
1450
|
* Fehlt ein Eintrag, gilt die Konvention. */
|
|
1426
1451
|
readonly fieldLabels?: Readonly<Record<string, string>>;
|
|
1452
|
+
/** Per-field help text i18n key (Field-Name → Key), from `mask.description`. */
|
|
1453
|
+
readonly fieldDescriptions?: Readonly<Record<string, string>>;
|
|
1454
|
+
/** Field names whose config key declares `required: true` — drives the
|
|
1455
|
+
* "Not set. Required." origin line, not form validation. */
|
|
1456
|
+
readonly requiredFields?: readonly string[];
|
|
1427
1457
|
/** i18n-key für den Submit-Button. Default: "kumiko.actions.save". */
|
|
1428
1458
|
readonly submitLabel?: string;
|
|
1429
1459
|
readonly slots?: ScreenSlots;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.335.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>",
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.335.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "RowActionWriteHandler gets an optional redirect for record actions",
|
|
6
|
+
"detail": "`redirect` takes the same forms as entityEdit `redirect` and is honored on projectionDetail and entityEdit header and section actions, not on list row actions.",
|
|
7
|
+
"migration": "No code change needed."
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"version": "0.328.1",
|
|
4
11
|
"type": "improvement",
|