# `AshTypescript.Codegen.SchemaCore`
[🔗](https://github.com/ash-project/ash_typescript/blob/v0.18.1/lib/ash_typescript/codegen/schema_core.ex#L5)

Shared logic for schema generation across all validation library targets.

All resource introspection, topological sorting, field resolution, and structural
code generation lives here. Output syntax is delegated to a module implementing
`AshTypescript.Codegen.SchemaFormatter`.

Consumers (e.g. `ZodSchemaGenerator`) pass `__MODULE__` as the first `formatter`
argument to each public function.

# `action_has_schema?`

Whether an RPC action gets an input schema at all.

An action with no inputs produces no schema, so anything that advertises or
re-exports a schema name must ask this first — otherwise it points consumers
at an export that does not exist.

# `action_schema_name`

Returns the exported schema constant name for an RPC action's input.

Single source of truth for the name — used by `generate_action_schema/4` (the
export itself), the namespace re-export collection, and both manifests, so
they cannot drift from the configured `*_schema_suffix`.

# `build_js_flags`

Builds a JS regex flag string from Elixir Regex opts.

# `compose_input_field`

Composes a single input-field schema entry: resolves the field's type
through the formatter, then wraps nullable/optional.

This is the one place that knows how "input argument -> schema field"
works — shared by RPC action input schemas (above) and typed-controller
route argument schemas (`RouteRenderer`), so the two surfaces cannot drift.

# `effective_min_length`

Computes the effective minimum length for a string schema.

Shared by the Zod and Valibot formatters so the rule cannot drift: an
explicit `:min_length` replaces the implicit non-empty minimum — but when
the string is non-empty (`allow_empty?: false`), the minimum is floored at
1, since the server nulls `""` regardless of a declared `min_length: 0`.
Returns `nil` when no minimum applies.

# `generate_action_schema`

Generates a schema definition for an RPC action's input.
Returns an empty string when the action has no input.

# `generate_schema_for_resource`

Generates a schema for a single resource.

# `generate_schemas_for_resources`

Generates schemas for a list of resources (embedded resources, struct args).
Returns an empty string when generation is disabled or the list is empty.

Builds an augmented resource lookup that includes any orphan resources not
already present in the cached spec — letting callers pass arbitrary embedded
resources (e.g., test fixtures) without pre-registering them.

# `get_type`

Maps a type-bearing spec input to a schema string.

Accepted shapes (all `%Ash.Info.Manifest.*{}`):
- `%Ash.Info.Manifest.Type{}` — the canonical spec form
- `%Ash.Info.Manifest.Argument{}` / `%Ash.Info.Manifest.Field{}` — anything with a
  `:type` field carrying a `%Ash.Info.Manifest.Type{}`
- Aggregate kind atoms (e.g. `:count`, `:sum`) — looked up in
  `formatter.aggregate_types()`

Callers must feed spec data. Raw Ash types (atom modules, `{:array, _}`
tuples, `%{type: SomeType, constraints: [...]}` shapes) are no longer
accepted; resolve via `Ash.Info.Manifest.Generator.TypeResolver.resolve/2` first.

Non-empty enforcement for string types is constraint-driven: whenever the
string's folded constraints carry `allow_empty?: false` (the Ash default),
the schema gets an effective min-length 1 (unless an explicit `:min_length`
is set) — matching server-side validation regardless of the field's
nilability. Strings with `allow_empty?: true` stay unconstrained. This
applies uniformly, including nested string fields inside typed containers.

# `maybe_wrap_nullable_optional`

Wraps a schema string with `wrap_nullable` (innermost) and/or `wrap_optional`
(outermost) based on the two booleans, using the given formatter.

# `regex_safe_for_js?`

Returns true when a regex source string is safe to emit as a JS literal.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
