@cosmicdrift/kumiko-framework 0.307.0 → 0.308.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 +4 -4
- package/src/__tests__/anonymous-access.integration.test.ts +1 -1
- package/src/__tests__/error-contract.integration.test.ts +1 -1
- package/src/__tests__/field-access.integration.test.ts +1 -1
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.expected.ts +1 -1
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.input.ts +1 -1
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.expected.ts +1 -1
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.input.ts +1 -1
- package/src/__tests__/full-stack.integration.test.ts +1 -1
- package/src/__tests__/transition-guard.integration.test.ts +1 -1
- package/src/api/__tests__/api.test.ts +1 -1
- package/src/api/__tests__/batch.integration.test.ts +1 -1
- package/src/api/__tests__/body-limit.test.ts +1 -1
- package/src/api/__tests__/dispatcher-live.integration.test.ts +1 -1
- package/src/api/__tests__/extra-routes.integration.test.ts +1 -1
- package/src/api/__tests__/http-route-rate-limit.integration.test.ts +1 -1
- package/src/api/__tests__/nested-write-ownership.integration.test.ts +1 -1
- package/src/api/__tests__/nested-write.integration.test.ts +1 -1
- package/src/api/__tests__/pii-leak-guard.integration.test.ts +1 -1
- package/src/api/__tests__/redis-sse-broker.integration.test.ts +73 -6
- package/src/api/__tests__/request-locale.integration.test.ts +1 -1
- package/src/api/__tests__/server-boot-guards.test.ts +1 -1
- package/src/api/__tests__/server-error-logging.test.ts +1 -1
- package/src/api/__tests__/sse-broker.test.ts +107 -13
- package/src/api/__tests__/stream-escape-hatch.integration.test.ts +1 -1
- package/src/api/auth-routes.ts +1 -1
- package/src/api/redis-sse-broker.ts +51 -11
- package/src/api/server.ts +11 -0
- package/src/api/sse-broker.ts +61 -22
- package/src/changes.json +37 -0
- package/src/compliance/override-schema.ts +1 -1
- package/src/crypto/__tests__/event-pii.test.ts +1 -1
- package/src/crypto/kms-adapter.ts +1 -1
- package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
- package/src/db/queries/event-consumer.ts +98 -6
- package/src/derivatives/__tests__/derivatives-context.integration.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-action-wiring.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-nav-area.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-projection-list.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-query-output-schema.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-query-refs.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-ref-entity.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +1 -1
- package/src/engine/__tests__/boot-validator.test.ts +35 -1
- package/src/engine/__tests__/build-app-schema.test.ts +1 -1
- package/src/engine/__tests__/build-config-feature-schema-secrets.test.ts +1 -1
- package/src/engine/__tests__/define-feature-entity-mapping.test.ts +1 -1
- package/src/engine/__tests__/engine.test.ts +1 -1
- package/src/engine/__tests__/event-helpers.test.ts +1 -1
- package/src/engine/__tests__/event-migration-declarative.test.ts +1 -1
- package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
- package/src/engine/__tests__/extends-registrar.test.ts +1 -1
- package/src/engine/__tests__/hook-phases.test.ts +1 -1
- package/src/engine/__tests__/lifecycle-hooks.test.ts +1 -1
- package/src/engine/__tests__/pipeline-engine.test.ts +1 -1
- package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +1 -1
- package/src/engine/__tests__/post-query-hook.test.ts +1 -1
- package/src/engine/__tests__/projection-detail-actions.test.ts +1 -1
- package/src/engine/__tests__/projection-detail-singleton.test.ts +1 -1
- package/src/engine/__tests__/projection-detail-tabs.test.ts +1 -1
- package/src/engine/__tests__/read-steps-tenant-filter.integration.test.ts +1 -1
- package/src/engine/__tests__/registry.test.ts +1 -1
- package/src/engine/__tests__/screen.test.ts +1 -1
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +1 -1
- package/src/engine/boot-validator/__tests__/access-declarations.test.ts +1 -1
- package/src/engine/boot-validator/__tests__/action-icon.test.ts +81 -0
- package/src/engine/boot-validator/__tests__/anonymous-rate-limit-required.test.ts +1 -1
- package/src/engine/boot-validator/__tests__/no-all-role-in-handler-access.test.ts +1 -1
- package/src/engine/boot-validator/__tests__/parent-ref.test.ts +1 -1
- package/src/engine/boot-validator/__tests__/rate-limit-disabled-reason.test.ts +1 -1
- package/src/engine/boot-validator/screens.ts +83 -0
- package/src/engine/define-handler.ts +2 -1
- package/src/engine/entity-handlers.ts +2 -1
- package/src/engine/feature-ast/__tests__/pattern-change-schema.test.ts +1 -1
- package/src/engine/feature-ast/pattern-change-schema.ts +1 -1
- package/src/engine/feature-builder-state.ts +2 -1
- package/src/engine/feature-config-events-jobs.ts +2 -1
- package/src/engine/feature-entity-handlers.ts +2 -1
- package/src/engine/schema-builder.ts +1 -1
- package/src/entrypoint/__tests__/entrypoint-attach-dispatcher.integration.test.ts +1 -1
- package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +1 -1
- package/src/entrypoint/__tests__/split-deploy.integration.test.ts +1 -1
- package/src/env/__tests__/compose-env-schema.test.ts +1 -1
- package/src/env/__tests__/dry-run.test.ts +1 -1
- package/src/env/__tests__/parse-env-dry-run.test.ts +1 -1
- package/src/env/_zod-introspect.ts +1 -1
- package/src/env/dry-run.ts +1 -1
- package/src/env/index.ts +1 -1
- package/src/errors/__tests__/classes.test.ts +1 -1
- package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
- package/src/event-store/__tests__/backfill-pii.integration.test.ts +1 -1
- package/src/event-store/__tests__/event-attribution.integration.test.ts +1 -1
- package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-backoff.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-event-trigger.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-multi-trigger.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-public-intake-origin.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-retention.integration.test.ts +1 -1
- package/src/jobs/__tests__/job-write-as.integration.test.ts +1 -1
- package/src/jobs/__tests__/jobs.integration.test.ts +1 -1
- package/src/observability/__tests__/metrics-wiring.test.ts +1 -1
- package/src/observability/__tests__/observability.integration.test.ts +1 -1
- package/src/observability/metrics-wiring.ts +1 -1
- package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
- package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +1 -1
- package/src/pipeline/__tests__/ctx-systemdb.integration.test.ts +1 -1
- package/src/pipeline/__tests__/dispatcher.test.ts +1 -1
- package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +1 -1
- package/src/pipeline/__tests__/escape-hatch-audit.integration.test.ts +1 -1
- package/src/pipeline/__tests__/escape-hatch.integration.test.ts +1 -1
- package/src/pipeline/__tests__/event-dedup.integration.test.ts +1 -1
- package/src/pipeline/__tests__/event-define-event-strict.integration.test.ts +1 -1
- package/src/pipeline/__tests__/event-dispatcher-batch-delivery.test.ts +178 -0
- package/src/pipeline/__tests__/event-dispatcher-batch-handler.integration.test.ts +143 -0
- package/src/pipeline/__tests__/event-dispatcher-idle.integration.test.ts +94 -0
- package/src/pipeline/__tests__/event-dispatcher-start-from.integration.test.ts +103 -3
- package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
- package/src/pipeline/__tests__/idempotency-transient-failure.integration.test.ts +1 -1
- package/src/pipeline/__tests__/job-trigger-consumer.integration.test.ts +1 -1
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +1 -1
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +1 -1
- package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
- package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +116 -1
- package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +1 -1
- package/src/pipeline/__tests__/pending-gap-ranges.test.ts +94 -0
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +1 -1
- package/src/pipeline/__tests__/public-intake-runtime-gate.integration.test.ts +1 -1
- package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
- package/src/pipeline/__tests__/rate-limit-default.integration.test.ts +1 -1
- package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +1 -1
- package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +1 -1
- package/src/pipeline/__tests__/system-identity-switch.integration.test.ts +1 -1
- package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
- package/src/pipeline/__tests__/unsafe-raw-escape-hatch.integration.test.ts +1 -1
- package/src/pipeline/dispatch-stream.ts +6 -1
- package/src/pipeline/event-dispatcher-delivery.ts +132 -37
- package/src/pipeline/event-dispatcher.ts +96 -9
- package/src/pipeline/index.ts +1 -0
- package/src/pipeline/msp-rebuild.ts +39 -1
- package/src/pipeline/pending-gap-ranges.ts +48 -0
- package/src/pipeline/system-hooks.ts +223 -68
- package/src/pipeline/write-origin.ts +1 -1
- package/src/rate-limit/__tests__/dispatcher-l3.integration.test.ts +1 -1
- package/src/search/__tests__/derive-search-adapter-config.test.ts +65 -0
- package/src/search/__tests__/meilisearch-adapter.integration.test.ts +91 -0
- package/src/search/__tests__/search-consumer-batch.integration.test.ts +306 -0
- package/src/search/derive-search-adapter-config.ts +27 -0
- package/src/search/index.ts +1 -0
- package/src/search/meilisearch-adapter.ts +96 -14
- package/src/secrets/__tests__/contains-secret.test.ts +1 -1
- package/src/stack/__tests__/request-helper.integration.test.ts +1 -1
- package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +1 -1
- package/src/stack/__tests__/setup-test-stack-metrics.integration.test.ts +1 -1
- package/src/testing/__tests__/e2e-generator.test.ts +1 -1
- package/src/testing/e2e-generator.ts +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { withBootValidatorFixture } from "../../testing/boot-validator-fixture";
|
|
4
4
|
import { validateBoot as validateBootRaw } from "../boot-validator";
|
|
5
5
|
import { defineFeature } from "../define-feature";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { withBootValidatorFixture } from "../../testing/boot-validator-fixture";
|
|
4
4
|
import { validateBoot as validateBootRaw } from "../boot-validator";
|
|
5
5
|
import { defineFeature } from "../define-feature";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { withBootValidatorFixture } from "../../testing/boot-validator-fixture";
|
|
4
4
|
import { validateBoot as validateBootRaw } from "../boot-validator";
|
|
5
5
|
import { defineFeature } from "../define-feature";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// escape-hatch-audit.integration.test.ts.
|
|
9
9
|
|
|
10
10
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
11
|
-
import
|
|
11
|
+
import * as z from "zod";
|
|
12
12
|
import { table, text, uuid } from "../../db/dialect";
|
|
13
13
|
import { insertOne } from "../../db/query";
|
|
14
14
|
import { defineFeature, defineWriteHandler } from "../../engine";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { createTenantConfig } from "../config-helpers";
|
|
4
4
|
import { defineFeature } from "../define-feature";
|
|
5
5
|
import { createEntity, createTextField } from "../factories";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { withBootValidatorFixture } from "../../testing/boot-validator-fixture";
|
|
4
4
|
import { validateBoot as validateBootRaw } from "../boot-validator";
|
|
5
5
|
import { createTenantConfig } from "../config-helpers";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { describe, expect, it } from "bun:test";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import
|
|
8
|
+
import * as z from "zod";
|
|
9
9
|
import { table as pgTable, text, uuid } from "../../db/dialect";
|
|
10
10
|
import { defineFeature } from "../define-feature";
|
|
11
11
|
import { defineWriteHandler } from "../define-handler";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { defineFeature } from "../../define-feature";
|
|
4
4
|
import { createEntity, createTextField } from "../../factories";
|
|
5
5
|
import { from } from "../../ownership";
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// validateActionHasIcon is the single icon-resolvability check shared by
|
|
2
|
+
// every projectionDetail/entityEdit action rendered in a Card title row:
|
|
3
|
+
// screen-level `actions`, section-level `actions`, and relatedList
|
|
4
|
+
// `emptyState.action` (see screens.ts call sites). Tested directly here
|
|
5
|
+
// rather than only via a full feature boot, since all three call sites
|
|
6
|
+
// share this one function.
|
|
7
|
+
|
|
8
|
+
import { describe, expect, test } from "bun:test";
|
|
9
|
+
import { validateActionHasIcon } from "../screens";
|
|
10
|
+
|
|
11
|
+
describe("validateActionHasIcon", () => {
|
|
12
|
+
test("rejects a screen-level action with no declared icon and an id that resolves none", () => {
|
|
13
|
+
expect(() =>
|
|
14
|
+
validateActionHasIcon("orders", "order-detail", "projectionDetail", "action", {
|
|
15
|
+
id: "custom-thing",
|
|
16
|
+
}),
|
|
17
|
+
).toThrow(/no resolvable icon/);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("rejects a section action, naming the section in the error", () => {
|
|
21
|
+
expect(() =>
|
|
22
|
+
validateActionHasIcon(
|
|
23
|
+
"orders",
|
|
24
|
+
"order-detail",
|
|
25
|
+
"projectionDetail",
|
|
26
|
+
'section "Payments" action',
|
|
27
|
+
{ id: "custom-thing" },
|
|
28
|
+
),
|
|
29
|
+
).toThrow(/section "Payments" action "custom-thing" has no resolvable icon/);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("rejects a relatedList emptyState action, naming it as such in the error", () => {
|
|
33
|
+
expect(() =>
|
|
34
|
+
validateActionHasIcon(
|
|
35
|
+
"orders",
|
|
36
|
+
"order-detail",
|
|
37
|
+
"projectionDetail",
|
|
38
|
+
'section "Payments" emptyState action',
|
|
39
|
+
{ id: "custom-thing" },
|
|
40
|
+
),
|
|
41
|
+
).toThrow(/emptyState action "custom-thing" has no resolvable icon/);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("passes when the action declares an explicit icon", () => {
|
|
45
|
+
expect(() =>
|
|
46
|
+
validateActionHasIcon("orders", "order-detail", "entityEdit", "action", {
|
|
47
|
+
id: "custom-thing",
|
|
48
|
+
icon: "lock",
|
|
49
|
+
}),
|
|
50
|
+
).not.toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("passes when the id resolves a default icon via a kebab segment (no explicit icon needed)", () => {
|
|
54
|
+
// "deletion" -> "trash" in the shared ACTION_ICON_BY_ID map.
|
|
55
|
+
expect(() =>
|
|
56
|
+
validateActionHasIcon("user-data-rights", "privacy-center", "projectionDetail", "action", {
|
|
57
|
+
id: "request-deletion",
|
|
58
|
+
}),
|
|
59
|
+
).not.toThrow();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// action.icon is typed IconKey (a closed union) — but that compile-time
|
|
63
|
+
// guarantee only covers call sites inside this repo's `tsc --build`
|
|
64
|
+
// project graph. Samples and external consumers aren't in it, so an
|
|
65
|
+
// unregistered literal (a typo, or a value copied from a different icon
|
|
66
|
+
// set) can reach here as plain runtime data. The renderer's actionIconFor
|
|
67
|
+
// (renderer-web/src/primitives/index.tsx) already falls back to "no icon"
|
|
68
|
+
// for such a value instead of crashing — this must throw here instead of
|
|
69
|
+
// silently accepting it, or the renderer/validator resolvers diverge.
|
|
70
|
+
test("rejects a declared icon that is not a registered NAV_ICON key, even though it resolves to a value", () => {
|
|
71
|
+
expect(() =>
|
|
72
|
+
validateActionHasIcon("orders", "order-detail", "projectionDetail", "action", {
|
|
73
|
+
id: "refresh-order",
|
|
74
|
+
// @ts-expect-error — exercising a value outside the closed IconKey
|
|
75
|
+
// union, exactly like an untypechecked caller (a sample, or a JS
|
|
76
|
+
// consumer) would produce at runtime.
|
|
77
|
+
icon: "refresh-cw",
|
|
78
|
+
}),
|
|
79
|
+
).toThrow(/no resolvable icon/);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// handler on a parentRef entity must fail boot rather than leak silently.
|
|
6
6
|
|
|
7
7
|
import { describe, expect, test } from "bun:test";
|
|
8
|
-
import
|
|
8
|
+
import * as z from "zod";
|
|
9
9
|
import { defineFeature } from "../../define-feature";
|
|
10
10
|
import { defineEntityDetailHandler, defineEntityListHandler } from "../../entity-handlers";
|
|
11
11
|
import { createEntity, createTextField } from "../../factories";
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
// into validateColumnRendererForm, splitting them would create a
|
|
5
5
|
// same-folder require cycle.
|
|
6
6
|
|
|
7
|
+
import { resolveActionIcon } from "@cosmicdrift/kumiko-types/action-icon";
|
|
7
8
|
import { NO_WIDGET_FIELD_TYPES } from "@cosmicdrift/kumiko-types/fields";
|
|
9
|
+
import type { IconKey } from "@cosmicdrift/kumiko-types/nav-icon";
|
|
10
|
+
import { NAV_ICON_KEYS } from "@cosmicdrift/kumiko-types/nav-icon";
|
|
8
11
|
import { rowMetaFieldNames } from "../../db/table-builder";
|
|
9
12
|
import { LIST_ROW_META_COLUMNS } from "../../ui-types/list-row-meta";
|
|
10
13
|
import { parseRefTarget } from "../parse-ref-target";
|
|
@@ -319,6 +322,41 @@ function validateWizardLayout(
|
|
|
319
322
|
// are NOT validated here — the r.uiComponent registry that would resolve
|
|
320
323
|
// them ships in M4/M5. Until then those are kept opaque on purpose.
|
|
321
324
|
|
|
325
|
+
// every action rendered in a Card title row (screen-level
|
|
326
|
+
// `actions`, section-level `actions`, `emptyState.action`) must draw an
|
|
327
|
+
// icon — declared or id-derived (resolveActionIcon, same resolver the
|
|
328
|
+
// renderer uses). Uncovered here: entityList/projectionList rowActions —
|
|
329
|
+
// those render inside a DataTable row, not a Card title row, so they keep
|
|
330
|
+
// today's "icon optional" behavior.
|
|
331
|
+
//
|
|
332
|
+
// Registration check (not just "resolved is not undefined"): action.icon is
|
|
333
|
+
// typed IconKey, a closed union — but that only protects call sites this
|
|
334
|
+
// repo's own `tsc --build` actually covers (samples and external consumers
|
|
335
|
+
// aren't in that project graph). The renderer's actionIconFor
|
|
336
|
+
// (renderer-web/src/primitives/index.tsx) already falls back to "no icon"
|
|
337
|
+
// for an unregistered key instead of crashing — this check makes the same
|
|
338
|
+
// gap fail loudly at boot instead of silently at render.
|
|
339
|
+
function isRegisteredIcon(icon: IconKey): boolean {
|
|
340
|
+
return (NAV_ICON_KEYS as readonly string[]).includes(icon);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function validateActionHasIcon(
|
|
344
|
+
featureName: string,
|
|
345
|
+
screenId: string,
|
|
346
|
+
screenType: "projectionDetail" | "entityEdit",
|
|
347
|
+
context: string,
|
|
348
|
+
action: { readonly id: string; readonly icon?: IconKey },
|
|
349
|
+
): void {
|
|
350
|
+
const resolved = resolveActionIcon(action.id, action.icon);
|
|
351
|
+
if (resolved === undefined || !isRegisteredIcon(resolved)) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`[Feature ${featureName}] Screen "${screenId}" (${screenType}) ${context} "${action.id}" has no ` +
|
|
354
|
+
`resolvable icon — set icon to a key registered in NAV_ICONS, or use an id that resolves one of ` +
|
|
355
|
+
`its kebab segments via the default icon map (resolveActionIcon).`,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
322
360
|
// Tier 2.7e-3: deklarative Feld-Referenzen einer Action gegen die Entity-
|
|
323
361
|
// Felder pinnen — ein Tippfehler in pick/map-Quellfeldern oder
|
|
324
362
|
// visible.field erzeugte sonst still `undefined` im Payload bzw. dauerhaft
|
|
@@ -1137,6 +1175,17 @@ export function validateScreens(
|
|
|
1137
1175
|
}
|
|
1138
1176
|
if (screen.layout.mode === "tabs") {
|
|
1139
1177
|
validateTabSections(feature.name, screenId, "projectionDetail", screen.layout.sections);
|
|
1178
|
+
for (const section of screen.layout.sections) {
|
|
1179
|
+
const isFieldsSection = section.kind === undefined || section.kind === "fields";
|
|
1180
|
+
if (isFieldsSection && section.groups !== undefined && section.actions !== undefined) {
|
|
1181
|
+
throw new Error(
|
|
1182
|
+
`[Feature ${feature.name}] Screen "${screenId}" (projectionDetail) section "${section.id}" ` +
|
|
1183
|
+
`declares both groups and actions in tabs mode — actions has no single group's Card to sit ` +
|
|
1184
|
+
`in, and an extra title-less Card around the group cards would nest a Card inside a Card. ` +
|
|
1185
|
+
`Move the actions onto one group's title, or drop groups for a flat fields grid.`,
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1140
1189
|
}
|
|
1141
1190
|
if (screen.metrics !== undefined) {
|
|
1142
1191
|
for (const metric of screen.metrics) {
|
|
@@ -1166,6 +1215,27 @@ export function validateScreens(
|
|
|
1166
1215
|
}
|
|
1167
1216
|
}
|
|
1168
1217
|
for (const section of screen.layout.sections) {
|
|
1218
|
+
const sectionLabel = section.title ?? section.id ?? "(untitled)";
|
|
1219
|
+
if (section.actions !== undefined) {
|
|
1220
|
+
for (const action of section.actions) {
|
|
1221
|
+
validateActionHasIcon(
|
|
1222
|
+
feature.name,
|
|
1223
|
+
screenId,
|
|
1224
|
+
"projectionDetail",
|
|
1225
|
+
`section "${sectionLabel}" action`,
|
|
1226
|
+
action,
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
if (section.kind === "relatedList" && section.emptyState?.action !== undefined) {
|
|
1231
|
+
validateActionHasIcon(
|
|
1232
|
+
feature.name,
|
|
1233
|
+
screenId,
|
|
1234
|
+
"projectionDetail",
|
|
1235
|
+
`section "${sectionLabel}" emptyState action`,
|
|
1236
|
+
section.emptyState.action,
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1169
1239
|
if (isExtensionEditSection(section)) {
|
|
1170
1240
|
// projectionDetail is read-only (no composed form submit) — an
|
|
1171
1241
|
// extension that persists through the host's Save button has
|
|
@@ -1402,6 +1472,7 @@ export function validateScreens(
|
|
|
1402
1472
|
// a detail screen has no row to click.
|
|
1403
1473
|
if (screen.actions !== undefined) {
|
|
1404
1474
|
for (const action of screen.actions) {
|
|
1475
|
+
validateActionHasIcon(feature.name, screenId, "projectionDetail", "action", action);
|
|
1405
1476
|
if (action.kind === "navigate" && action.rowClick === true) {
|
|
1406
1477
|
throw new Error(
|
|
1407
1478
|
`[Feature ${feature.name}] Screen "${qualifyEntityName(feature.name, "screen", screenId)}" ` +
|
|
@@ -1902,6 +1973,18 @@ export function validateScreens(
|
|
|
1902
1973
|
);
|
|
1903
1974
|
}
|
|
1904
1975
|
for (const section of screen.layout.sections) {
|
|
1976
|
+
if (section.actions !== undefined) {
|
|
1977
|
+
const sectionLabel = section.title ?? section.id ?? "(untitled)";
|
|
1978
|
+
for (const action of section.actions) {
|
|
1979
|
+
validateActionHasIcon(
|
|
1980
|
+
feature.name,
|
|
1981
|
+
screenId,
|
|
1982
|
+
"entityEdit",
|
|
1983
|
+
`section "${sectionLabel}" action`,
|
|
1984
|
+
action,
|
|
1985
|
+
);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1905
1988
|
if (isExtensionEditSection(section)) {
|
|
1906
1989
|
if (section.component?.react === undefined && section.component?.native === undefined) {
|
|
1907
1990
|
throw new Error(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CursorResult } from "@cosmicdrift/kumiko-types/cursor-types";
|
|
2
2
|
import { ENTITY_CONVENTION_QUERY_BRAND } from "@cosmicdrift/kumiko-types/handlers";
|
|
3
|
-
import type
|
|
3
|
+
import type * as z from "zod";
|
|
4
|
+
import type { ZodType } from "zod";
|
|
4
5
|
import type { ContainsSecret } from "../secrets/types";
|
|
5
6
|
import { runPipeline } from "./run-pipeline";
|
|
6
7
|
import type { HandlerContext, KumikoEventTypeMap, WriteEvent, WriteResult } from "./types";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ENTITY_CONVENTION_QUERY_BRAND } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
-
import {
|
|
2
|
+
import type { ZodType } from "zod";
|
|
3
|
+
import * as z from "zod";
|
|
3
4
|
import type { DbRow } from "../db/connection";
|
|
4
5
|
import {
|
|
5
6
|
collectReferenceFields,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { describe, expect, test } from "bun:test";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
8
|
import { Project, type SourceFile } from "ts-morph";
|
|
9
|
-
import type
|
|
9
|
+
import type * as z from "zod";
|
|
10
10
|
import { parseFeatureFile, parseSourceFile } from "../parse";
|
|
11
11
|
import { applyChanges, type PatternId } from "../patch";
|
|
12
12
|
import {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// additionally checked for field-type membership via the shared
|
|
23
23
|
// `findUnknownEntityFieldTypes` helper (kept in sync with `extractEntity`).
|
|
24
24
|
|
|
25
|
-
import
|
|
25
|
+
import * as z from "zod";
|
|
26
26
|
import { type LifecycleHookType, LifecycleHookTypes } from "../constants";
|
|
27
27
|
import type {
|
|
28
28
|
ConfigKeyDefinition,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizeEventPiiSubject } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
-
import
|
|
2
|
+
import type * as z from "zod";
|
|
3
|
+
import { ZodObject, type ZodType } from "zod";
|
|
3
4
|
import type { FeatureBuilderState } from "./feature-builder-state";
|
|
4
5
|
import { resolveName } from "./handler-helpers";
|
|
5
6
|
import { splitNamedDefinition, unwrapArrayForm } from "./object-form";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ENTITY_CONVENTION_QUERY_BRAND } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
-
import type
|
|
2
|
+
import type * as z from "zod";
|
|
3
|
+
import type { ZodType } from "zod";
|
|
3
4
|
import { toTableName } from "../db/table-builder";
|
|
4
5
|
import {
|
|
5
6
|
isEntityConventionQueryHandler,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// throws the #2043 stub).
|
|
11
11
|
|
|
12
12
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
13
|
-
import
|
|
13
|
+
import * as z from "zod";
|
|
14
14
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
15
15
|
import { asRawClient } from "../../db/query";
|
|
16
16
|
import { createRegistry, defineFeature } from "../../engine";
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// regressing to the Welle-2.5 state.
|
|
14
14
|
|
|
15
15
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
16
|
-
import
|
|
16
|
+
import * as z from "zod";
|
|
17
17
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
18
18
|
import { createRegistry, defineFeature } from "../../engine";
|
|
19
19
|
import { createArchivedStreamsTable } from "../../event-store";
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// fires with systemConsumers explicitly disabled).
|
|
14
14
|
|
|
15
15
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
16
|
-
import
|
|
16
|
+
import * as z from "zod";
|
|
17
17
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
18
18
|
import { asRawClient } from "../../db/query";
|
|
19
19
|
import { createRegistry, defineFeature } from "../../engine";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import { defineFeature } from "../../engine/define-feature";
|
|
4
4
|
import { prometheusMetricsEnvSchema } from "../../observability/metrics-wiring";
|
|
5
5
|
import { renderDryRun } from "../dry-run";
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// All helpers accept the *runtime* Zod instance — TypeScript wrapper
|
|
7
7
|
// (`z.ZodType`) and core (`$ZodType`) are the same object at runtime.
|
|
8
8
|
|
|
9
|
-
import type
|
|
9
|
+
import type * as z from "zod";
|
|
10
10
|
|
|
11
11
|
export type ZodDef = {
|
|
12
12
|
readonly innerType?: z.ZodType;
|
package/src/env/dry-run.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// The same schema introspection (`classifyField`, `readKumikoMeta`) used
|
|
9
9
|
// by parseEnv drives the output here — single source of truth.
|
|
10
10
|
|
|
11
|
-
import type
|
|
11
|
+
import type * as z from "zod";
|
|
12
12
|
import { zodShape } from "./_zod-introspect";
|
|
13
13
|
import {
|
|
14
14
|
type ComposedEnvSchema,
|
package/src/env/index.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// Without meta, defaults: `camelCase(envVarName)` for the Pulumi key,
|
|
15
15
|
// `<set-me>` placeholder for the value, no `--secret` flag.
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import * as z from "zod";
|
|
18
18
|
import type { FeatureDefinition } from "../engine/types/feature";
|
|
19
19
|
import { zodDef, zodDescription, zodMeta, zodShape, zodShapeField } from "./_zod-introspect";
|
|
20
20
|
|
|
@@ -17,7 +17,7 @@ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:tes
|
|
|
17
17
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
18
18
|
import { tmpdir } from "node:os";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
-
import
|
|
20
|
+
import * as z from "zod";
|
|
21
21
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
22
22
|
import { asRawClient, insertOne, selectMany } from "../../db/query";
|
|
23
23
|
import { buildEntityTable } from "../../db/table-builder";
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
|
|
17
17
|
import { UNATTRIBUTED_ORIGIN, type WriteOrigin } from "@cosmicdrift/kumiko-types/event-store-types";
|
|
18
|
-
import
|
|
18
|
+
import * as z from "zod";
|
|
19
19
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
20
20
|
import { selectMany } from "../../db/query";
|
|
21
21
|
import { buildEntityTable } from "../../db/table-builder";
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// can never silently hand half-migrated data to consumers.
|
|
10
10
|
|
|
11
11
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
12
|
-
import
|
|
12
|
+
import * as z from "zod";
|
|
13
13
|
import { integer as pgInteger, table as pgTable, text as pgText } from "../../db/dialect";
|
|
14
14
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
15
15
|
import { asRawClient, insertOne, selectMany } from "../../db/query";
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// so a >= assertion is flake-free without inflating waitFor's budget.
|
|
11
11
|
|
|
12
12
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
13
|
-
import
|
|
13
|
+
import * as z from "zod";
|
|
14
14
|
import { defineFeature } from "../../engine";
|
|
15
15
|
import { setupTestStack, type TestStack, TestUsers } from "../../stack";
|
|
16
16
|
import { waitFor } from "../../testing";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
2
|
import type { Hono } from "hono";
|
|
3
|
-
import
|
|
3
|
+
import * as z from "zod";
|
|
4
4
|
import { buildServer, type JwtHelper } from "../../api";
|
|
5
5
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
6
6
|
import { createRegistry, defineFeature, type SessionUser } from "../../engine";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
10
10
|
import type { Hono } from "hono";
|
|
11
|
-
import
|
|
11
|
+
import * as z from "zod";
|
|
12
12
|
import { buildServer, type JwtHelper } from "../../api";
|
|
13
13
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
14
14
|
import { createRegistry, defineFeature, type SessionUser } from "../../engine";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
4
4
|
import { Queue } from "bullmq";
|
|
5
|
-
import
|
|
5
|
+
import * as z from "zod";
|
|
6
6
|
import type { SchemaTable } from "../../db";
|
|
7
7
|
import { createEventStoreExecutor } from "../../db/event-store-executor";
|
|
8
8
|
import { asRawClient, selectMany } from "../../db/query";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
9
9
|
import { Queue } from "bullmq";
|
|
10
|
-
import
|
|
10
|
+
import * as z from "zod";
|
|
11
11
|
import { createRegistry, defineFeature } from "../../engine";
|
|
12
12
|
import type { AppContext, TenantId } from "../../engine/types";
|
|
13
13
|
import { createTestRedis, type TestRedis } from "../../stack";
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// to the actor rather than to SYSTEM.
|
|
10
10
|
|
|
11
11
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
12
|
-
import
|
|
12
|
+
import * as z from "zod";
|
|
13
13
|
import { ROLES } from "../../auth/roles";
|
|
14
14
|
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
15
15
|
import { asRawClient } from "../../db/query";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
2
|
import { Queue } from "bullmq";
|
|
3
|
-
import
|
|
3
|
+
import * as z from "zod";
|
|
4
4
|
import { requestContext } from "../../api/request-context";
|
|
5
5
|
import { tenantDbRunner } from "../../db/tenant-db-runner";
|
|
6
6
|
import { createRegistry, defineFeature } from "../../engine";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
import type { TableColumns } from "../../db/dialect";
|
|
4
4
|
import { buildEntityTable } from "../../db/table-builder";
|
|
5
5
|
import { createRegistry, defineFeature } from "../../engine";
|