Release v7.17.0
Summary
These notes have been corrected. This version was published from the head of an open pull request rather than from main, because the Publish workflow cut a release on a merge into any base branch, not only into main. It therefore contains the whole of that branch's work, not only the DateOnly and TimeOnly types the original notes described.
Nothing here is withdrawn — the packages are what they are, and the list below is what they actually contain. The trigger has since been scoped to main so a release can only come from the branch it is released from.
Added
DateOnlyholds a date with no time and no time zone, withparse,toString,toDate,from,fromDateandequals. A calendar date put through a JavaScriptDatebecomes UTC midnight, which every browser-local getter west of UTC reads back as the day before — an answer that looks right and is wrong only for users in some time zones, which is how it survives development in othersTimeOnlyholds a time of day with no date and no time zone, withparse,toString,fromandequals. ADateneeds a date and a time of day has none, sonew Date('14:30:45')isInvalid Date— the value is destroyed outright rather than merely shiftedDateOnlyJsonConverterandTimeOnlyJsonConverter, registered so both deserialize from the ISO-8601 form the server sends and serialize back to itJsonSerializer.registerConverterregisters a JSON converter for a type, taking the place of any converter already registered for it, so an application can correct how a type crosses the wire without forking the serializertypeKeyOf,declaredTypeKey,conceptAsTypeKeyandvalueMapTypeKeyidentify a convertible type by the key it declares rather than by its class object. Comparing class objects is what breaks when two copies of this package end up in one realm, and a consuming package recognizing a concept that way has no way to be correct —typeKeyOf(type) === conceptAsTypeKeysurvives the boundary wheretype === ConceptAscannotITypes.DiscoveryModereports whether the type universe was built from generated providers, the reflection fallback, or providers supplied by the caller, so a silent fall back to reflection is visible rather than something to infer from behaviorTypeDiscoveryDiagnostics.FindMissingContributorslists project-referenced libraries that contributed nothing to the type universe, which is what a missing or misconfigured generator looks like from the outside- A
Cratis.Fundamentals.TypeDiscoveryevent source reports the assemblies behind a type universe, and warns when it reached nothing beyondCratis.Fundamentals— a universe that small is almost always a discovery failure rather than an application with no types @cratis/fundamentalswarns on load when it has been loaded more than once into the same JavaScript realm. Two copies each bring their own converter registry and their own class objects, so a converter registered on one is invisible to the other andinstanceofacross them is false, all without anything failing outright
Changed
- A concept in a collection or a value map serializes as its underlying value instead of as
{"value": ...}, matching how a concept serializes everywhere else; the wrapped form was an accident of the container, not a declared shape - Types this package converts are recognized across two copies of it loaded into the same JavaScript realm, so a
Guidor a concept crossing that boundary keeps its declared representation rather than silently serializing as a plain object
Fixed
- A
ValueMapwith primitive values lost every value on deserialization, returning the keys with nothing attached @cratis/fundamentals/jsonand@cratis/fundamentals/geospatialwere exported by the package but failed to resolve at runtime, because the barrel files the manifest pointed at were never emitted — TypeScript resolved them from source, so the break only appeared once installed. The build now fails if the manifest names a path it did not produce
Deprecated
JsonConverter.canConvert, whichJsonSerializerdoes not call, is scheduled for removal in the next major version — implementing it has no effect today, so relying on it to exclude a type does not work