I recently carved out some time to revisit some dormant projects. The primary driver was a tic-tac-toe app inspired by Scott Wlaschin‘s Enterprise Tic-Tac-Toe series of posts and presentation and a desire to learn and test out Datastar. An upcoming post will dive deeper into that topic. In this post, I want to share a high-level overview of what’s new with FSharp.Data.JsonSchema and Frank. Subsequent posts will dive into further details.
FSharp.Data.JsonSchema 3.0.1
FSharp.Data.JsonSchema is now three packages:
- FSharp.Data.JsonSchema.Core: Core JSON Schema representation types that relies on only
FSharp.SystemTextJson. This library can be uses to parse a JSON Schema into F# types and F# types into a JSON Schema. However, it no longer has a specific target. - FSharp.Data.JsonSchema.NJsonSchema: This is equivalent to the previous version with a dependency on
NJsonSchemaas the target. This should be backward compatible with previous versions of the library. - FSharp.Data.JsonSchema.OpenApi: The new target depends on the
Microsoft.OpenApilibrary introduced with thenet9.0framework target. This target is intended for use with generating Open API documents from ASP.NET Core applications.
In addition, several long overdue bug fixes and enhancements should now be resolved:
- Recursive Types (#15): Recursive F# types no longer cause infinite loops. Self-referential DUs, records with optional self-references, and recursion through collections all generate proper
$ref: "#"schemas, and a follow-up fix in3.0.1resolved anNJsonSchemaserialization failure whereRef("#")in nullable contexts tried to look up the root reference in the definitions dictionary instead of referencing the root schema directly - Choice types (#22):
Choice<'A,'B>throughChoice<'A,…,'G>now generate cleananyOfschemas instead of the verbose internal-tag encoding - Anonymous records: Inline object schemas, no
$ref - DU encoding styles:
InternalTag,AdjacentTag,ExternalTag, andUntaggedvia a newunionEncodingparameter onGenerator.Create - Format annotations: Proper
date-time,guid,uri,duration,date,time, andbyteformats forDateTime,Guid,Uri,TimeSpan,DateOnly,TimeOnly, andbyte[]
Frank 7.2.0
Frank has had a long and winding history as my favorite hobby project for trying out different approaches to encoding web applications. The computation expression approach starting in (IIRC) v5.0 has stuck. The goal is still to produce an HTTP resource-style set of builders that provides a consistent means of defining HTTP resources and the ASP.NET Core WebHost in which to run them while allowing for a lot of flexibility and extensibility. As such, I’ve added some additional libraries I’ve found useful to test out the extensibility and support the new tic-tac-toe hobby project mentioned above.
Packages
- Frank: Added
Metadatafield toResourceSpec, alistof(EndpointBuilder -> unit)convention functions applied duringRouteEndpointBuilder.Build(). This generic extensibility point lets companion libraries (Auth,OpenApi, etc.) attach typed endpoint metadata without requiring changes to the coreFranklibrary. This is a binary-breaking change but source-compatible with the empty default. Also addedplugBeforeRouting,plugBeforeRoutingWhen, andplugBeforeRoutingWhenNotfor middleware ordering control aroundUseRouting(). - Frank.Analyzers: F# Analyzer (
FSharp.Analyzers.SDK) that detects duplicate HTTP handler registrations within a resource block at compile time, enforcing the constraint of a single HTTP method per resource. It works in IDEs (Ionide, VS, Rider) and CLI (dotnet fsharp-analyzers) for CI/CD. - Frank.Auth: Adds
WebHostBuilderregistration and resource-level authorization viaResourceBuilderextensions, includingrequireAuth,requireClaim,requireRole,requirePolicyusing AND semantics for resources anduseAuthentication,useAuthorization,authorizationPolicyforWebHostBuilder. - Frank.OpenApi: Adds long-planned, declarative OpenAPI 3.0+ document generation, including a handler computation expression for pairing handlers with metadata (name, summary, tags, produces, accepts). F# type schemas (records, DUs, options, collections) via
FSharp.Data.JsonSchema.OpenApi.useOpenApionWebHostBuilderwires services and middleware. Includes Scalar UI to provide a web-based client for viewing and testing endpoints. Targetsnet9.0/net10.0. - Frank.Datastar: Native SSE implementation similar to the
StarFederation.Datastar.FSharplibrary. Zero-copy buffer writing viaIBufferWriter, zero external NuGet dependencies, full Datastar SDK ADR compliance. Added stream-based overloads (streamPatchElements, etc.) acceptingTextWriter -> Taskfor zero-allocation HTML rendering. No breaking API changes. Targetsnet8.0/net9.0/net10.0.
New Samples
- Frank.Datastar.Basic: RESTful hypermedia patterns (click-to-edit, search, bulk ops) using
Frank.Datastarwith F# string templates. - Frank.Datastar.Hox: Same patterns as
Basicusing theHoxview engine. Demonstrates stream-based SSE overloads viaRender.toStream. - Frank.Datastar.Oxpecker: Same patterns as
BasicusingOxpecker.ViewEngine. - Frank.OpenApi.Sample: Product catalog API demonstrating the handler CE with OpenAPI metadata, mixed plain/enriched handlers,
useOpenApi, and Scalar UI.
Looking Ahead
I’ll spend some time in upcoming posts exploring each of these. In the meantime, I’d love feedback on any of the updates and changes. I hope I haven’t broken anyone with changes to FSharp.Data.JsonSchema, and there is a transition package with version 3.0.0 to make it easier to switch without changing package names. I don’t have any additional plans at the moment for either of these, but please open issues if you have ideas or bug reports.
You must be logged in to post a comment.