@nxgt/typespec 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/typespec",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -51,7 +51,7 @@
51
51
  "typescript": "^6.0.3"
52
52
  },
53
53
  "devDependencies": {
54
- "@nxgt/openapi-codegen": "^0.5.0",
54
+ "@nxgt/openapi-codegen": "^0.5.1",
55
55
  "@nxgt/openapi-hono": "^0.3.0",
56
56
  "@types/bun": "^1.4.0",
57
57
  "@typespec/compiler": "1.16.0",
@@ -1,112 +0,0 @@
1
- # Resources
2
-
3
- `Resource` gives a resource its five operations in one line: list, read,
4
- create, update and delete, with the replies each one can send.
5
-
6
- ## One resource
7
-
8
- ```tsp
9
- import "@typespec/http";
10
- import "@nxgt/typespec";
11
-
12
- using Http;
13
- using Nxgt;
14
-
15
- namespace Blog;
16
-
17
- model Author {
18
- @visibility(Lifecycle.Read) id: uuid;
19
- name: string;
20
- email: email;
21
- ...Timestamps;
22
- }
23
-
24
- model AuthorFilters {
25
- /** Authors of this name. */
26
- @query name?: string;
27
- }
28
-
29
- @route("/authors")
30
- interface Authors extends Resource<Author, AuthorFilters, SortField = "name" | "createdAt"> {}
31
- ```
32
-
33
- | Operation | Route | Body | Answers |
34
- | --- | --- | --- | --- |
35
- | `listAuthors` | `GET /authors` | | `Page<Author>` |
36
- | `readAuthors` | `GET /authors/{id}` | | `Author`, `NotFound` |
37
- | `createAuthors` | `POST /authors` | `Create<Author>` | 201 `Author`, `BadRequest`, `Conflict` |
38
- | `updateAuthors` | `PATCH /authors/{id}` | `MergePatchUpdate<Author>` | `Author`, `BadRequest`, `NotFound`, `Conflict` |
39
- | `deleteAuthors` | `DELETE /authors/{id}` | | 204, `NotFound` |
40
-
41
- The template carries `@operationIds`, so each operation is named after the
42
- interface that extends it. The generator's own 400 is on every operation
43
- that takes a parameter or a body, as always.
44
-
45
- ## The template's arguments
46
-
47
- `Resource<Item, Filters = {}, SortField = "id", Id = uuid>`. Name the ones
48
- after `Filters`, as above, to skip those you keep:
49
-
50
- - `Item`: the resource's model. `Create<Item>` and `MergePatchUpdate<Item>`
51
- leave its read-only properties out, such as `id` and the `Timestamps`.
52
- - `Filters`: a model of `@query` properties, spread into `list`. Each is
53
- typed and checked, as any query parameter.
54
- - `SortField`: the fields `list` may sort by, as a union of strings.
55
- - `Id`: the type of `{id}`. `Id = integer` for a table whose id is
56
- `@nxgt/drizzle`'s `id('identity')`.
57
-
58
- ## Filters and sort
59
-
60
- `list` takes the filters, the offset page's `page` and `pageSize`, and
61
- `SortParameters<SortField>`:
62
-
63
- | Query | Default | Checked |
64
- | --- | --- | --- |
65
- | `orderBy` | none: the server's order, the primary key with `@nxgt/drizzle` | one of the `SortField`s |
66
- | `direction` | `asc` | `asc` or `desc` |
67
-
68
- `?orderBy=email` on `Authors` is a 400: `email` is not a `SortField`. The
69
- handler passes them to `@nxgt/drizzle`:
70
-
71
- ```ts
72
- import { Hono } from 'hono';
73
- import { createRoutes } from './generated/hono';
74
-
75
- const app = new Hono();
76
- createRoutes(app).get('/authors', async (c) => {
77
- const { name, page, pageSize, orderBy, direction } = c.req.valid('query');
78
- const found = await authors.paginate({
79
- where: name === undefined ? {} : { name },
80
- page,
81
- pageSize,
82
- // paginate takes the sort as an object of directions by field
83
- ...(orderBy === undefined ? {} : { orderBy: { [orderBy]: direction } }),
84
- });
85
- return c.json(found, 200);
86
- });
87
- ```
88
-
89
- `paginateByCursor` takes them apart instead, `{ orderBy, direction }`, as
90
- the query has them.
91
-
92
- `SortParameters<Field>` works on its own too, in any list:
93
-
94
- ```tsp
95
- @get list(...PageParameters, ...SortParameters<"createdAt" | "title">): Page<Post>;
96
- ```
97
-
98
- ## Changing an operation
99
-
100
- An interface that extends `Resource` can declare one of its operations
101
- again, and its own replaces the template's. A list paged by cursor:
102
-
103
- ```tsp
104
- @route("/comments")
105
- interface Comments extends Resource<Comment> {
106
- @get list(...CursorPageParameters): CursorPage<Comment>;
107
- }
108
- ```
109
-
110
- Add `@useAuth(JanusAuth)` on the interface to protect all five, and name the
111
- guards' replies in the operations you declare again
112
- ([Authentication](auth.md)).
package/lib/resources.tsp DELETED
@@ -1,63 +0,0 @@
1
- import "@typespec/http";
2
-
3
- using Http;
4
-
5
- namespace Nxgt;
6
-
7
- /**
8
- * The sort of a list, as `@nxgt/drizzle` takes it: one field, and a
9
- * direction. `Field` is the union of the fields a client may sort by.
10
- * Spread it into an operation's parameters.
11
- */
12
- model SortParameters<Field extends string> {
13
- /** The field to sort by. */
14
- @query
15
- orderBy?: Field;
16
-
17
- /** `asc` or `desc`. */
18
- @query
19
- direction?: "asc" | "desc" = "asc";
20
- }
21
-
22
- /**
23
- * The five operations of a resource, at `/<route>` and `/<route>/{id}`:
24
- * `list` pages by offset, with the `Filters` the spec writes and a sort by
25
- * `SortField`; `read`, `create`, `update` (a merge patch) and `delete`.
26
- * Extend it with `@route`; `@operationIds` names the operations after the
27
- * interface that extends it: `listPosts`, `readPosts`…
28
- *
29
- * @template Item The resource's model.
30
- * @template Filters A model of `@query` properties, spread into `list`.
31
- * @template SortField The fields `list` may sort by; `"id"` by default.
32
- * @template Id The type of `{id}`; `uuid` by default.
33
- */
34
- @operationIds
35
- interface Resource<
36
- Item extends {},
37
- Filters extends {} = {},
38
- SortField extends string = "id",
39
- Id = uuid
40
- > {
41
- /** One page of the resources, filtered and sorted. */
42
- @get
43
- list(...Filters, ...PageParameters, ...SortParameters<SortField>): Page<Item>;
44
-
45
- /** One resource. */
46
- @get
47
- read(@path id: Id): Item | NotFound;
48
-
49
- /** Creates a resource. */
50
- @post
51
- create(@body item: Create<Item>): {
52
- @statusCode _: 201;
53
- @body item: Item;
54
- } | BadRequest | Conflict;
55
-
56
- /** Updates a resource with a merge patch. */
57
- @patch
58
- update(@path id: Id, @body item: MergePatchUpdate<Item>): Item | BadRequest | NotFound | Conflict;
59
-
60
- /** Deletes a resource. */
61
- @delete
62
- delete(@path id: Id): NoContentResponse | NotFound;
63
- }