The file thatDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/metareflection/dafny-replay/llms.txt
Use this file to discover all available pages before exploring further.
dafny2js generates is a faithful, mechanical translation of your AppCore module into JavaScript. It is correct and complete, but it reflects Dafny’s type system rather than the idioms that JavaScript callers expect. app-extras.js is the sanctioned place to add that translation layer: it imports GeneratedApp, extends it with convenience methods, and re-exports the result as the App object your components use. Because it is a separate file, it survives regeneration of app.js intact.
When to use app-extras.js
Useapp-extras.js when you need to:
- Wrap
Result<T, E>return types into{ok, model}objects that are easier to branch on in JavaScript - Derive parameters automatically so callers pass fewer arguments
- Expose enum values as object properties instead of zero-argument constructor calls
- Flatten Dafny maps into JavaScript arrays for easier iteration
- Accept serialized JSON on the boundary with a server or edge function
The base pattern
Createsrc/dafny/app-extras.js in your app:
app-extras.js in your components instead of app.js:
Pattern 1: Wrap Result types
Dafny functions that can fail returnResult<T, E> values. The raw Dafny runtime represents these as objects with is_Ok / is_Err discriminants and dtor_value / dtor_error destructors. In JavaScript, it is more idiomatic to return {ok: true, model: ...} or {ok: false, error: ...}.
Pattern 2: Derive parameters automatically
SomeAppCore functions take a parameter that is always derivable from another argument. For example, if MakeExpense requires both a shares object and its shareKeys array, the caller should not have to supply both:
GeneratedApp.MakeExpense. The generated function handles converting paidBy from a JavaScript string to a Dafny seq<char>, converting amountCents to a BigNumber, and converting each share value. If you call AppCore.__default.MakeExpense directly, those conversions are bypassed.
Pattern 3: Object-style enum access
Dafny constructors with no arguments compile to zero-argument factory functions:App.Vibrant(). When you have many enum variants, the parentheses become noise and the pattern is unfamiliar to JavaScript developers. You can expose an object-style accessor:
Pattern 4: Return all map entries
Generated accessors typically look up a single entry in a Dafny map. If you need to expose the entire map as a JavaScript array, iterate the map’sKeys.Elements:
map objects expose their keys through map.Keys.Elements (an iterable) and values through map.get(key). Dafny strings (seq<char>) can be converted to JavaScript strings with Array.from(seq).join('') or .toVerbatimString(false).
Pattern 5: Accept JSON for server communication
When your app communicates with a server or edge function, it is convenient to pass and receive plain JSON rather than Dafny runtime objects. Use the generatedmodelFromJson and modelToJson converters inside a wrapper:
Why always delegate to GeneratedApp
The generatedapp.js inserts type conversions at every boundary:
- JavaScript strings →
_dafny.Seq.UnicodeFromString(s)(Dafnyseq<char>) - JavaScript numbers →
new BigNumber(n)(Dafnyint) - JavaScript arrays →
_dafny.Seq.of(...arr)(Dafnyseq<T>)
AppCore.__default.SomeFunction directly and pass a raw JavaScript string, Dafny will receive a string where it expects a sequence of characters, and the result will be silently wrong or throw at runtime.
Delegating to GeneratedApp functions keeps all those conversions in the generated code where they are tested and correct:
dafny2js tool
Understand what the generated app.js contains and how to regenerate it.
React integration
Wire the App object from app-extras.js into React state and JSX.