@cosmicdrift/kumiko-framework 0.232.0 → 0.234.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-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.234.0",
|
|
4
4
|
"description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
"./package.json": "./package.json"
|
|
199
199
|
},
|
|
200
200
|
"dependencies": {
|
|
201
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
201
|
+
"@cosmicdrift/kumiko-types": "0.234.0",
|
|
202
202
|
"bullmq": "^5.76.7",
|
|
203
203
|
"bun-types": "^1.3.13",
|
|
204
204
|
"hono": "^4.13.1",
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
"zod": "^4.4.3"
|
|
215
215
|
},
|
|
216
216
|
"devDependencies": {
|
|
217
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
217
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.234.0",
|
|
218
218
|
"bun-types": "^1.3.13",
|
|
219
219
|
"pino-pretty": "^13.1.3"
|
|
220
220
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// createNumberField({ unit }) passthrough — pins that NumberFieldDef.unit
|
|
2
|
+
// survives the factory's Partial<Omit<...>> spread, static string and
|
|
3
|
+
// sibling-field-reference form alike.
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from "bun:test";
|
|
6
|
+
import { createNumberField } from "../factories";
|
|
7
|
+
|
|
8
|
+
describe("createNumberField — unit passthrough", () => {
|
|
9
|
+
test("static unit string is preserved", () => {
|
|
10
|
+
const f = createNumberField({ unit: "km" });
|
|
11
|
+
expect(f.unit).toBe("km");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("sibling-field unit reference is preserved", () => {
|
|
15
|
+
const f = createNumberField({ unit: { field: "mileageUnit" } });
|
|
16
|
+
expect(f.unit).toEqual({ field: "mileageUnit" });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("omitted unit stays undefined", () => {
|
|
20
|
+
const f = createNumberField();
|
|
21
|
+
expect(f.unit).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -94,7 +94,7 @@ function validateNoWidgetRequiredField(
|
|
|
94
94
|
function validateRowActionNavigateParams(
|
|
95
95
|
featureName: string,
|
|
96
96
|
screenId: string,
|
|
97
|
-
screenType: "entityList" | "projectionList" | "projectionDetail",
|
|
97
|
+
screenType: "entityList" | "projectionList" | "projectionDetail" | "entityEdit",
|
|
98
98
|
screenEntity: string | undefined,
|
|
99
99
|
action: RowAction,
|
|
100
100
|
target: { readonly featureName: string; readonly screen: ScreenDefinition } | undefined,
|
|
@@ -396,7 +396,7 @@ type RowActionNavigateRuntime = RowActionNavigateBase & {
|
|
|
396
396
|
function resolveRowActionNavigateTarget(
|
|
397
397
|
featureName: string,
|
|
398
398
|
screenId: string,
|
|
399
|
-
screenType: "entityList" | "projectionList" | "projectionDetail",
|
|
399
|
+
screenType: "entityList" | "projectionList" | "projectionDetail" | "entityEdit",
|
|
400
400
|
actionLabel: "rowAction" | "action",
|
|
401
401
|
action: RowActionNavigateRuntime,
|
|
402
402
|
allScreenQns: ReadonlySet<string>,
|
|
@@ -1307,6 +1307,50 @@ export function validateScreens(
|
|
|
1307
1307
|
}
|
|
1308
1308
|
}
|
|
1309
1309
|
validateWizardLayout(feature.name, screenId, "entityEdit", screen.layout, featureMap);
|
|
1310
|
+
// Header actions reuse RowAction — same shape and same checks as
|
|
1311
|
+
// projectionDetail's `actions` above (the loaded record stands in
|
|
1312
|
+
// for the row). `rowClick` is rejected outright — entityEdit has no
|
|
1313
|
+
// row to click either.
|
|
1314
|
+
if (screen.actions !== undefined) {
|
|
1315
|
+
for (const action of screen.actions) {
|
|
1316
|
+
if (action.kind === "navigate" && action.rowClick === true) {
|
|
1317
|
+
throw new Error(
|
|
1318
|
+
`[Feature ${feature.name}] Screen "${qualifyEntityName(feature.name, "screen", screenId)}" ` +
|
|
1319
|
+
`(entityEdit) action "${action.id}" sets rowClick: true — there is no row to click ` +
|
|
1320
|
+
`on an edit screen. Remove rowClick.`,
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
if (action.kind === "navigate") {
|
|
1324
|
+
const target = resolveRowActionNavigateTarget(
|
|
1325
|
+
feature.name,
|
|
1326
|
+
screenId,
|
|
1327
|
+
"entityEdit",
|
|
1328
|
+
"action",
|
|
1329
|
+
action,
|
|
1330
|
+
allScreenQns,
|
|
1331
|
+
navTargetShortIds,
|
|
1332
|
+
screensByShortId,
|
|
1333
|
+
detailForScreens,
|
|
1334
|
+
);
|
|
1335
|
+
validateRowActionNavigateParams(
|
|
1336
|
+
feature.name,
|
|
1337
|
+
screenId,
|
|
1338
|
+
"entityEdit",
|
|
1339
|
+
screen.entity,
|
|
1340
|
+
action,
|
|
1341
|
+
target,
|
|
1342
|
+
);
|
|
1343
|
+
} else {
|
|
1344
|
+
if (!allWriteHandlerQns.has(action.handler)) {
|
|
1345
|
+
throw new Error(
|
|
1346
|
+
`[Feature ${feature.name}] Screen "${screenId}" (entityEdit) action "${action.id}" ` +
|
|
1347
|
+
`handler "${action.handler}" is not a registered write-handler. Check the QN spelling ` +
|
|
1348
|
+
`(expected "<feature>:write:<short>") and that the handler is declared via r.writeHandler(...).`,
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1310
1354
|
if (screen.redirect !== undefined) {
|
|
1311
1355
|
// Same rule as actionForm's redirect: short screen-ID (same-feature)
|
|
1312
1356
|
// or a fully-qualified cross-feature QN (#1946).
|
package/src/ui-types/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type {
|
|
|
52
52
|
TextFieldDef,
|
|
53
53
|
} from "../engine/types/fields";
|
|
54
54
|
export type { AccessRule } from "../engine/types/handlers";
|
|
55
|
-
export type { NavDefinition, NavIconKey } from "../engine/types/nav";
|
|
55
|
+
export type { IconKey, NavDefinition, NavIconKey } from "../engine/types/nav";
|
|
56
56
|
export type {
|
|
57
57
|
ActionFormScreenDefinition,
|
|
58
58
|
ConfigEditScreenDefinition,
|