typespec1-7 Exercise 2: Renaming and Requiring in a Request ==================================================================== orders.tsp (the change as the team described it): import "@typespec/http"; import "@typespec/versioning"; using Http; using TypeSpec.Versioning; @versioned(Versions) @service(#{ title: "Order Service" }) namespace Orders; enum Versions { v1: "1.0", v2: "2.0" } model NewOrder { @renamedFrom(Versions.v2, "item") product: string; quantity: int32; @added(Versions.v2) currency: string; } @route("/orders") interface OrderOps { @post create(@body order: NewOrder): void; } Changelog 1.0 -> 2.0: error new-required-request-property POST /orders added the new required request property `currency` error new-required-request-property POST /orders added the new required request property `product` warning request-property-removed POST /orders removed the request property `item` `oasdiff breaking ... --fail-on ERR` exits 1 for it. WHAT THE DIFF SAYS A request that was valid in version 1 (item and quantity) is not valid in version 2: it lacks the required product and the required currency. The rename shows up as a removal of item (a warning, since a server that stops reading a field does not hurt the sender) and the new required product (an error). So the rename on its own is already breaking, because a rename of a request field IS a new required field. The versioning decorator records the history; it does not make the change compatible. THE REDESIGN orders_fixed.tsp: import "@typespec/http"; import "@typespec/versioning"; using Http; using TypeSpec.Versioning; @versioned(Versions) @service(#{ title: "Order Service Fixed" }) namespace OrdersFixed; enum Versions { v1: "1.0", v2: "2.0" } model NewOrder { item: string; quantity: int32; @added(Versions.v2) currency?: string = "GBP"; @added(Versions.v2) product?: string; } @route("/orders") interface OrderOps { @post create(@body order: NewOrder): void; } Changelog 1.0 -> 2.0: info new-optional-request-property POST /orders added the new optional request property `currency` info new-optional-request-property POST /orders added the new optional request property `product` `--fail-on ERR` now exits 0. WHAT CHANGED item stays, unchanged and required. product and currency are added as optional (currency with a default of "GBP"). Two info lines, no errors, no warnings. The cost: the contract now has two names for the same thing in version 2 (item and product), and nothing in it says how a server should treat a request that sends both. That rule has to go in the descriptions (chapter 5) and in the server. A later version can remove item when clients have moved; that removal will be flagged by the diff again, which is the point. Not checked: I did not write a server, so 'servers accept either' is the design, not something I tested. WHY THIS WORKS AS AN ANSWER --------------------------- It shows the whole loop: write the change, measure it, redesign, measure again. The measurement is what turns 'is this OK?' from an opinion into a number.