From f79d19c91890861d1fae7367074eb3db8969091f Mon Sep 17 00:00:00 2001 From: Connor Sullivan Date: Sat, 9 Sep 2023 22:54:31 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20Experiment=20with=20templates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Experiments with using templates. Applies them only to Films and documents my thoughts. --- src/films.tsp | 23 ++++++---------------- src/main.tsp | 1 + src/operation-templates.tsp | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 src/operation-templates.tsp diff --git a/src/films.tsp b/src/films.tsp index 449e1c7..77f5ab1 100644 --- a/src/films.tsp +++ b/src/films.tsp @@ -2,26 +2,15 @@ using TypeSpec.Http; namespace SWAPI; +// Dev note: See `operation-template.tsp` + @route("/films") namespace films { - /** - * Get all the film resources. - * - * @param search Case-insensitive partial match on the `title` field. - */ @OpenAPI.operationId("ListFilms") - op list(@query search: string): Film[]; - - @route("/{filmId}") - namespace film { - /** - * Get a specific film resource. - * - * @param filmId Numeric ID of the film to get. - */ - @OpenAPI.operationId("GetFilm") - op read(@path filmId: int32): Film; - } + op list is List; + + @OpenAPI.operationId("GetFilm") + op read is Get; } /** A Film resource is a single film. */ diff --git a/src/main.tsp b/src/main.tsp index 819c96d..8de730f 100644 --- a/src/main.tsp +++ b/src/main.tsp @@ -2,6 +2,7 @@ import "@typespec/http"; import "@typespec/openapi"; import "./films.tsp"; +import "./operation-templates.tsp"; import "./people.tsp"; import "./planets.tsp"; import "./root.tsp"; diff --git a/src/operation-templates.tsp b/src/operation-templates.tsp new file mode 100644 index 0000000..23455a8 --- /dev/null +++ b/src/operation-templates.tsp @@ -0,0 +1,39 @@ +using TypeSpec.Http; + +// Dev note: Only `films.tsp` uses these templates due to shortcomings I find +// with the template approach. +// +// - I want `filmId` as the `Get` path parameter, not a generic `id`. I have +// found the specificity helps, especially with code generation. +// - The doc comments can only differ with `{name}`, which prevents deeper +// clarification. For example, the `search` parameter should clarify on which +// fields it searches. +// - The `@OpenAPI.operationId` decorator is not compatible with this reuse +// pattern. The resource route is also needed at the call site. +// _Note: This is why I did not wrap these operations in an interface._ +// +// Thus, almost half of the config is still needed/desired at the call site. +// +// Standardization presents a great benefit for this approach, but I’ve found +// independent evolution on top of a copied base proves similarly effective. +// +// I will leave these templates here for reference in the repository. + +/** The list operation template. */ +@get +@doc("Get all the {name} resources.", TResource) +op List( + @doc("Case-insensitive partial match on selected fields.") + @query + search: string, +): TResource[]; + +/** The get (read) operation template. */ +@route("/{id}") +@get +@doc("Get a specific {name} resource.", TResource) +op Get( + @doc("Numeric ID of the {name} to get.", TResource) + @path + id: int32, +): TResource;