Skip to content

DynamicValueSchema is narrower than resolveActionParam's actual contract #296

Description

@charbelrami

Summary

DynamicValueSchema rejects shapes that resolveActionParam resolves correctly at runtime. This causes false positives for tools that schema-validate emitted specs against ActionBindingSchema.

Repro

import {
  ActionBindingSchema,
  DynamicValueSchema,
  resolveActionParam,
} from "@json-render/core"; // 0.19.0

const ctx = {
  stateModel: { form: { text: "hi" } },
  repeatBasePath: "/todos/2",
  repeatIndex: 2,
};

// Runtime accepts each shape:
resolveActionParam({ $index: true }, ctx);                       // → 2
resolveActionParam(["a", "b"], ctx);                             // → ["a", "b"]
resolveActionParam({ id: { $state: "/form/text" } }, ctx);       // → { id: "hi" }

// Schema rejects each:
DynamicValueSchema.safeParse({ $index: true }).success;          // false
DynamicValueSchema.safeParse(["a", "b"]).success;                // false
DynamicValueSchema.safeParse({ id: { $state: "/x" } }).success;  // false

// Same rejection cascades into ActionBindingSchema:
ActionBindingSchema.safeParse({
  action: "setState",
  params: { value: ["a", "b"] },
}).success; // false

Why this matters

resolveActionParam is documented to:

  • Resolve { $item: "field" } to an absolute state path.
  • Resolve { $index: true } to a numeric index.
  • Delegate everything else to resolvePropValue, which recurses into objects/arrays and handles the full PropExpression grammar.

But DynamicValueSchema is union(string, number, boolean, null, { $state: string }) — anything else fails validation even though the runtime resolves it correctly.

Concrete impact: external tooling that validates an emitted Spec against ActionBindingSchema gets false positives on legitimate emissions like params: { value: ["a", "b"] } (literal array) or params: { value: { id: { \$state: "/x" } } } (object with state refs).

Context

Surfaced while building a parity test suite for a DSL → json-render compiler against @json-render/core@0.19.0. Happy to PR if alignment on the approach is reached.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions