typespec1-10 Exercise 1: A Mock Member Service ==================================================== members.tsp (TypeSpec 1.17.0): import "@typespec/http"; using Http; @service(#{ title: "Member Service" }) namespace Members; @example(#{ id: "m_1", code: "AB1234", name: "Ada Lovelace", age: 36 }) model Member { @visibility(Lifecycle.Read) id: string; @pattern("^[A-Z]{2}[0-9]{4}$") code: string; @minLength(2) @maxLength(40) name: string; @minValue(16) @maxValue(120) age: int32; } @error model NotFound { @statusCode _: 404; message: string; } @route("/members") interface Members { @get list(): Member[]; @route("{id}") @get read(@path id: string): Member | NotFound; @post create(@body member: Create): Member; } Compiled to OpenAPI (3.0.0, the default) and served with: prism mock members.yaml -p 4011 (Prism 5.16.0) curl results (headers other than the status line and content type left out): $ curl -s -i http://127.0.0.1:4011/members HTTP/1.1 200 OK Content-type: application/json [{"id":"m_1","code":"AB1234","name":"Ada Lovelace","age":36}] $ curl -s -i -X POST http://127.0.0.1:4011/members -H Content-Type: application/json -d {"code":"AB1234","name":"Ada Lovelace","age":36} HTTP/1.1 200 OK Content-type: application/json {"id":"m_1","code":"AB1234","name":"Ada Lovelace","age":36} $ curl -s -i -X POST http://127.0.0.1:4011/members -H Content-Type: application/json -d {"code":"ab1234","name":"A","age":15} HTTP/1.1 422 Unprocessable Entity content-type: application/problem+json {"type":"https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY","title":"Invalid request","status":422,"detail":"Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.","validation":[{"location":["body","code"],"severity":"Error","code":"pattern","message":"Request body property code must match pattern \"^[A-Z]{2}[0-9]{4}$\""},{"location":["body","name"],"severity":"Error","code":"minLength","message":"Request body property name must NOT have fewer than 2 characters"},{"location":["body","age"],"severity":"Error","code":"minimum","message":"Request body property age must be >= 16"}]} $ curl -s -i http://127.0.0.1:4011/members/x -H Prefer: code=404 HTTP/1.1 404 Not Found Content-type: application/json {"message":"string"} WHICH DECORATORS PRISM ENFORCED code @pattern -> 'must match pattern ^[A-Z]{2}[0-9]{4}$' (sent 'ab1234') name @minLength(2) -> 'must NOT have fewer than 2 characters' (sent 'A') age @minValue(16) -> 'must be >= 16' (sent 15) Not tried: @maxLength, @maxValue, a missing required property (the chapter's Book Service test covered 'required'). OTHER THINGS TO NOTICE The GET answers with the @example from the model, not with data. The valid create answered 200, not 201: this contract's create does not declare a 201 (I wrote 'Member' as the return type, and a POST's default is 200). A mock follows the contract, so the contract's omission shows. There is no 400 in this contract, so Prism produced its own 422 'application/problem+json' with a list of violations. The Book Service, which declares a 400, got a 400 instead. Prefer: code=404 returned the declared NotFound shape, with the placeholder value "string". WHY THIS WORKS AS AN ANSWER --------------------------- Each decorator was tested by sending one value that breaks it. Reading the 422 shows which decorators reached the mock; the ones I did not test I have listed as not tried.