@ontrails/hono 0.2.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/CHANGELOG.md +321 -0
- package/README.md +44 -0
- package/package.json +42 -0
- package/src/caught-error.ts +65 -0
- package/src/index.ts +6 -0
- package/src/surface.ts +242 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# @ontrails/hono
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`664e8bb`](https://github.com/outfitter-dev/trails/commit/664e8bb049e61f1d47cec1dd246606707af5d1a8): Point public installation examples at exact approved 0.2.0 versions and distinguish the prepared source release from pending npm publication.
|
|
8
|
+
- [`b3ddf91`](https://github.com/outfitter-dev/trails/commit/b3ddf918ada8211f44983512e2bbdfbc5b66d722): Prepare the first normal Trails release at `0.2.0` on `latest`, replacing the unpublished 1.0.0 source release. The target advances the original `0.1.0` source minor, which was never published under the current package names. Public packages remain in lockstep. Update consumer installation guidance and provide a temporary manifest bridge for old 1.0 beta sources. Published beta versions remain unchanged; minor 0.x releases may carry documented breaking changes.
|
|
9
|
+
|
|
10
|
+
The `1.0.0` section retained below records an unpublished preparation, not an npm release. Its accumulated changes are included in `0.2.0`; the section remains as source history alongside the published beta entries.
|
|
11
|
+
|
|
12
|
+
## 1.0.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
|
|
17
|
+
`implementation` across trail contracts, surface projections, tests, examples,
|
|
18
|
+
and public source-analysis helpers. Existing applications must rename authored
|
|
19
|
+
trail behavior fields and direct trail-object access before upgrading.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- [`f5c6777`](https://github.com/outfitter-dev/trails/commit/f5c6777c39ea959d2123f17bb683151fe265386c): Move adapter package workspaces from `connectors/*` to `adapters/*` as part of
|
|
24
|
+
the package-boundary taxonomy cutover. Package names and public APIs are
|
|
25
|
+
unchanged.
|
|
26
|
+
- [`e41c382`](https://github.com/outfitter-dev/trails/commit/e41c3829c2d692683b78c730e67fd5b17ac0ff4e): Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
|
|
27
|
+
- [`ed5926b`](https://github.com/outfitter-dev/trails/commit/ed5926bddebed7be19a902d69be58f2d5e8b4c51): Add missing TSDoc for public adapter and sink boundary types.
|
|
28
|
+
- [`6300f70`](https://github.com/outfitter-dev/trails/commit/6300f709bb6dffc0e6cc82479fe8d0204c52bbba): Refresh source comments and test labels for retired connector terminology as adapter guardrails become strict.
|
|
29
|
+
- [`20d7a5c`](https://github.com/outfitter-dev/trails/commit/20d7a5c8e675fd3ecd8c29441bbd8a99b5c64ed0): Enforce the shared safe error projection policy for public error bodies, diagnostics, serialized payloads, and CLI stderr.
|
|
30
|
+
- [`95bf132`](https://github.com/outfitter-dev/trails/commit/95bf132a15d6bd0f3a9e5fa597697393014f1e21): Wire HTTP permit resolution through the Hono adapter, including request headers for Bearer Authorization handling.
|
|
31
|
+
- [`729f957`](https://github.com/outfitter-dev/trails/commit/729f957a11dfa54474c20262dc2c37866f8b437e): Harden the Hono surface by capping JSON request bodies at 1 MiB by default and
|
|
32
|
+
redacting generic internal errors while preserving server-side diagnostics.
|
|
33
|
+
- [`49c2e7d`](https://github.com/outfitter-dev/trails/commit/49c2e7d5c7c063b9aa6abee1d2932bf3003133cc): Refresh published package README taxonomy to use adapter language instead of retired connector vocabulary.
|
|
34
|
+
- [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
|
|
35
|
+
to derive/derived for contract-owned fact production and render/rendered for
|
|
36
|
+
surface presentation. Public type, helper, rule, relation, and report names move
|
|
37
|
+
without compatibility aliases; ordinary repository/project nouns remain
|
|
38
|
+
explicit preserves or structured review inventory.
|
|
39
|
+
- [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
|
|
40
|
+
binding, add exact repository metadata for each public workspace package, and
|
|
41
|
+
correct the native Bun release descriptor to its pack-only runtime boundary.
|
|
42
|
+
- [`bc2d327`](https://github.com/outfitter-dev/trails/commit/bc2d3276cf0af2c7217365a28b436ebf3023c09b): Close HTTP package documentation around the shared `@ontrails/http/fetch` kernel, Bun-native `@ontrails/http/bun` subpath, and Hono adapter boundary before versioning.
|
|
43
|
+
- [`20cb72c`](https://github.com/outfitter-dev/trails/commit/20cb72cc91e48a4683f8832e18b0f55855943583): Refactor Hono route handling to delegate Web request parsing, response
|
|
44
|
+
projection, diagnostics, permits, and webhook handling through
|
|
45
|
+
`@ontrails/http/fetch`.
|
|
46
|
+
- [`8105f53`](https://github.com/outfitter-dev/trails/commit/8105f538ee3a0768a21482e6b7385122c2ed90dd): Declare the Hono package as an extracted HTTP adapter and dogfood the shared
|
|
47
|
+
adapter authoring check path against its owner conformance test.
|
|
48
|
+
- [`df9a7d0`](https://github.com/outfitter-dev/trails/commit/df9a7d00fe4d9ebec948b6ebed6dc4525fc8e0dc): Add project-aware public export-map governance for @ontrails workspace docs,
|
|
49
|
+
imports, root barrels, and bin-only package surfaces.
|
|
50
|
+
- [`61497c5`](https://github.com/outfitter-dev/trails/commit/61497c54deaaae2d067af88d0be6db0a5acb5faf): Add v1-minimum public API examples for shipped surface entrypoints.
|
|
51
|
+
|
|
52
|
+
## 1.0.0-beta.50
|
|
53
|
+
|
|
54
|
+
## 1.0.0-beta.49
|
|
55
|
+
|
|
56
|
+
## 1.0.0-beta.48
|
|
57
|
+
|
|
58
|
+
## 1.0.0-beta.47
|
|
59
|
+
|
|
60
|
+
## 1.0.0-beta.46
|
|
61
|
+
|
|
62
|
+
## 1.0.0-beta.45
|
|
63
|
+
|
|
64
|
+
## 1.0.0-beta.44
|
|
65
|
+
|
|
66
|
+
### Patch Changes
|
|
67
|
+
|
|
68
|
+
- [`b1fbe57`](https://github.com/outfitter-dev/trails/commit/b1fbe574e6f44d1fecb5e3a000270955c0a77b7b): Publish Bun-validated package tarballs through an npm trusted-publishing adapter
|
|
69
|
+
binding, add exact repository metadata for each public workspace package, and
|
|
70
|
+
correct the native Bun release descriptor to its pack-only runtime boundary.
|
|
71
|
+
|
|
72
|
+
## 1.0.0-beta.43
|
|
73
|
+
|
|
74
|
+
### Patch Changes
|
|
75
|
+
|
|
76
|
+
- [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
|
|
77
|
+
to derive/derived for contract-owned fact production and render/rendered for
|
|
78
|
+
surface presentation. Public type, helper, rule, relation, and report names move
|
|
79
|
+
without compatibility aliases; ordinary repository/project nouns remain
|
|
80
|
+
explicit preserves or structured review inventory.
|
|
81
|
+
|
|
82
|
+
## 1.0.0-beta.42
|
|
83
|
+
|
|
84
|
+
## 1.0.0-beta.41
|
|
85
|
+
|
|
86
|
+
## 1.0.0-beta.40
|
|
87
|
+
|
|
88
|
+
### Minor Changes
|
|
89
|
+
|
|
90
|
+
- [`5adb995`](https://github.com/outfitter-dev/trails/commit/5adb99551c2dda6190d46cce7f60bb08d63c99aa): Complete the v1 hard cutover from the authored `blaze` field to
|
|
91
|
+
`implementation` across trail contracts, surface projections, tests, examples,
|
|
92
|
+
and public source-analysis helpers. Existing applications must rename authored
|
|
93
|
+
trail behavior fields and direct trail-object access before upgrading.
|
|
94
|
+
|
|
95
|
+
## 1.0.0-beta.39
|
|
96
|
+
|
|
97
|
+
## 1.0.0-beta.38
|
|
98
|
+
|
|
99
|
+
## 1.0.0-beta.37
|
|
100
|
+
|
|
101
|
+
## 1.0.0-beta.36
|
|
102
|
+
|
|
103
|
+
## 1.0.0-beta.35
|
|
104
|
+
|
|
105
|
+
## 1.0.0-beta.34
|
|
106
|
+
|
|
107
|
+
## 1.0.0-beta.33
|
|
108
|
+
|
|
109
|
+
## 1.0.0-beta.32
|
|
110
|
+
|
|
111
|
+
### Patch Changes
|
|
112
|
+
|
|
113
|
+
- Updated dependencies [3e5c0fc]
|
|
114
|
+
- Updated dependencies [f3c4fef]
|
|
115
|
+
- Updated dependencies [cb0a9d8]
|
|
116
|
+
- Updated dependencies [21c6dda]
|
|
117
|
+
- Updated dependencies [fe72b84]
|
|
118
|
+
- @ontrails/core@1.0.0-beta.32
|
|
119
|
+
- @ontrails/http@1.0.0-beta.32
|
|
120
|
+
|
|
121
|
+
## 1.0.0-beta.31
|
|
122
|
+
|
|
123
|
+
### Patch Changes
|
|
124
|
+
|
|
125
|
+
- Updated dependencies [4cd5d4e]
|
|
126
|
+
- Updated dependencies [38907cc]
|
|
127
|
+
- @ontrails/core@1.0.0-beta.31
|
|
128
|
+
- @ontrails/http@1.0.0-beta.31
|
|
129
|
+
|
|
130
|
+
## 1.0.0-beta.30
|
|
131
|
+
|
|
132
|
+
### Patch Changes
|
|
133
|
+
|
|
134
|
+
- @ontrails/core@1.0.0-beta.30
|
|
135
|
+
- @ontrails/http@1.0.0-beta.30
|
|
136
|
+
|
|
137
|
+
## 1.0.0-beta.29
|
|
138
|
+
|
|
139
|
+
### Patch Changes
|
|
140
|
+
|
|
141
|
+
- @ontrails/core@1.0.0-beta.29
|
|
142
|
+
- @ontrails/http@1.0.0-beta.29
|
|
143
|
+
|
|
144
|
+
## 1.0.0-beta.28
|
|
145
|
+
|
|
146
|
+
### Patch Changes
|
|
147
|
+
|
|
148
|
+
- @ontrails/core@1.0.0-beta.28
|
|
149
|
+
- @ontrails/http@1.0.0-beta.28
|
|
150
|
+
|
|
151
|
+
## 1.0.0-beta.27
|
|
152
|
+
|
|
153
|
+
### Patch Changes
|
|
154
|
+
|
|
155
|
+
- @ontrails/core@1.0.0-beta.27
|
|
156
|
+
- @ontrails/http@1.0.0-beta.27
|
|
157
|
+
|
|
158
|
+
## 1.0.0-beta.26
|
|
159
|
+
|
|
160
|
+
### Patch Changes
|
|
161
|
+
|
|
162
|
+
- Updated dependencies [1307568]
|
|
163
|
+
- Updated dependencies [371d19e]
|
|
164
|
+
- @ontrails/core@1.0.0-beta.26
|
|
165
|
+
- @ontrails/http@1.0.0-beta.26
|
|
166
|
+
|
|
167
|
+
## 1.0.0-beta.25
|
|
168
|
+
|
|
169
|
+
### Patch Changes
|
|
170
|
+
|
|
171
|
+
- Updated dependencies [c36aca9]
|
|
172
|
+
- Updated dependencies [3befcf1]
|
|
173
|
+
- Updated dependencies [a4f9cf6]
|
|
174
|
+
- Updated dependencies [9bcf34e]
|
|
175
|
+
- @ontrails/core@1.0.0-beta.25
|
|
176
|
+
- @ontrails/http@1.0.0-beta.25
|
|
177
|
+
|
|
178
|
+
## 1.0.0-beta.24
|
|
179
|
+
|
|
180
|
+
### Patch Changes
|
|
181
|
+
|
|
182
|
+
- @ontrails/core@1.0.0-beta.24
|
|
183
|
+
- @ontrails/http@1.0.0-beta.24
|
|
184
|
+
|
|
185
|
+
## 1.0.0-beta.23
|
|
186
|
+
|
|
187
|
+
### Patch Changes
|
|
188
|
+
|
|
189
|
+
- Updated dependencies [9c5ecdc]
|
|
190
|
+
- @ontrails/http@1.0.0-beta.23
|
|
191
|
+
- @ontrails/core@1.0.0-beta.23
|
|
192
|
+
|
|
193
|
+
## 1.0.0-beta.22
|
|
194
|
+
|
|
195
|
+
### Patch Changes
|
|
196
|
+
|
|
197
|
+
- @ontrails/core@1.0.0-beta.22
|
|
198
|
+
- @ontrails/http@1.0.0-beta.22
|
|
199
|
+
|
|
200
|
+
## 1.0.0-beta.21
|
|
201
|
+
|
|
202
|
+
### Patch Changes
|
|
203
|
+
|
|
204
|
+
- Updated dependencies [99523f2]
|
|
205
|
+
- @ontrails/core@1.0.0-beta.21
|
|
206
|
+
- @ontrails/http@1.0.0-beta.21
|
|
207
|
+
|
|
208
|
+
## 1.0.0-beta.20
|
|
209
|
+
|
|
210
|
+
### Patch Changes
|
|
211
|
+
|
|
212
|
+
- Updated dependencies [851a2a3]
|
|
213
|
+
- @ontrails/core@1.0.0-beta.20
|
|
214
|
+
- @ontrails/http@1.0.0-beta.20
|
|
215
|
+
|
|
216
|
+
## 1.0.0-beta.19
|
|
217
|
+
|
|
218
|
+
### Patch Changes
|
|
219
|
+
|
|
220
|
+
- e41c382: Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
|
|
221
|
+
- ed5926b: Add missing TSDoc for public adapter and sink boundary types.
|
|
222
|
+
- 8105f53: Declare the Hono package as an extracted HTTP adapter and dogfood the shared
|
|
223
|
+
adapter authoring check path against its owner conformance test.
|
|
224
|
+
- Updated dependencies [e41c382]
|
|
225
|
+
- Updated dependencies [1eb5bdc]
|
|
226
|
+
- Updated dependencies [f8d80b9]
|
|
227
|
+
- Updated dependencies [94a8380]
|
|
228
|
+
- Updated dependencies [94a8380]
|
|
229
|
+
- Updated dependencies [846a597]
|
|
230
|
+
- Updated dependencies [223aaad]
|
|
231
|
+
- Updated dependencies [3125f4d]
|
|
232
|
+
- Updated dependencies [2494dc6]
|
|
233
|
+
- Updated dependencies [2d53717]
|
|
234
|
+
- Updated dependencies [16cb740]
|
|
235
|
+
- Updated dependencies [8894ecb]
|
|
236
|
+
- Updated dependencies [fdf7ec9]
|
|
237
|
+
- Updated dependencies [d76be13]
|
|
238
|
+
- Updated dependencies [84f56a5]
|
|
239
|
+
- Updated dependencies [431b04c]
|
|
240
|
+
- Updated dependencies [5d88104]
|
|
241
|
+
- Updated dependencies [f04a9ef]
|
|
242
|
+
- Updated dependencies [fc00aeb]
|
|
243
|
+
- Updated dependencies [ab1c77c]
|
|
244
|
+
- Updated dependencies [8ca5b85]
|
|
245
|
+
- @ontrails/core@1.0.0-beta.19
|
|
246
|
+
- @ontrails/http@1.0.0-beta.19
|
|
247
|
+
|
|
248
|
+
## 1.0.0-beta.18
|
|
249
|
+
|
|
250
|
+
### Patch Changes
|
|
251
|
+
|
|
252
|
+
- bc2d327: Close HTTP package documentation around the shared `@ontrails/http/fetch` kernel, Bun-native `@ontrails/http/bun` subpath, and Hono adapter boundary before versioning.
|
|
253
|
+
- 20cb72c: Refactor Hono route handling to delegate Web request parsing, response
|
|
254
|
+
projection, diagnostics, permits, and webhook handling through
|
|
255
|
+
`@ontrails/http/fetch`.
|
|
256
|
+
- Updated dependencies [c0b2948]
|
|
257
|
+
- Updated dependencies [fc3219c]
|
|
258
|
+
- Updated dependencies [bc2d327]
|
|
259
|
+
- @ontrails/http@1.0.0-beta.18
|
|
260
|
+
- @ontrails/core@1.0.0-beta.18
|
|
261
|
+
|
|
262
|
+
## 1.0.0-beta.17
|
|
263
|
+
|
|
264
|
+
### Patch Changes
|
|
265
|
+
|
|
266
|
+
- 61497c5: Add v1-minimum public API examples for shipped surface entrypoints.
|
|
267
|
+
- Updated dependencies [3dc8254]
|
|
268
|
+
- Updated dependencies [61497c5]
|
|
269
|
+
- @ontrails/core@1.0.0-beta.17
|
|
270
|
+
- @ontrails/http@1.0.0-beta.17
|
|
271
|
+
|
|
272
|
+
## 1.0.0-beta.16
|
|
273
|
+
|
|
274
|
+
### Patch Changes
|
|
275
|
+
|
|
276
|
+
- f5c6777: Move adapter package workspaces from `connectors/*` to `adapters/*` as part of
|
|
277
|
+
the package-boundary taxonomy cutover. Package names and public APIs are
|
|
278
|
+
unchanged.
|
|
279
|
+
- 6300f70: Refresh source comments and test labels for retired connector terminology as adapter guardrails become strict.
|
|
280
|
+
- 20d7a5c: Enforce the shared safe error projection policy for public error bodies, diagnostics, serialized payloads, and CLI stderr.
|
|
281
|
+
- 95bf132: Wire HTTP permit resolution through the Hono adapter, including request headers for Bearer Authorization handling.
|
|
282
|
+
- 729f957: Harden the Hono surface by capping JSON request bodies at 1 MiB by default and
|
|
283
|
+
redacting generic internal errors while preserving server-side diagnostics.
|
|
284
|
+
- 49c2e7d: Refresh published package README taxonomy to use adapter language instead of retired connector vocabulary.
|
|
285
|
+
- df9a7d0: Add project-aware public export-map governance for @ontrails workspace docs,
|
|
286
|
+
imports, root barrels, and bin-only package surfaces.
|
|
287
|
+
- Updated dependencies [73622ae]
|
|
288
|
+
- Updated dependencies [6300f70]
|
|
289
|
+
- Updated dependencies [d172013]
|
|
290
|
+
- Updated dependencies [c3fc5c3]
|
|
291
|
+
- Updated dependencies [20d7a5c]
|
|
292
|
+
- Updated dependencies [be5fb46]
|
|
293
|
+
- Updated dependencies [95bf132]
|
|
294
|
+
- Updated dependencies [e898cc4]
|
|
295
|
+
- Updated dependencies [2bf239e]
|
|
296
|
+
- Updated dependencies [3395234]
|
|
297
|
+
- Updated dependencies [bcdc484]
|
|
298
|
+
- Updated dependencies [49c2e7d]
|
|
299
|
+
- Updated dependencies [331e3a9]
|
|
300
|
+
- Updated dependencies [4399fdb]
|
|
301
|
+
- Updated dependencies [4b8d13b]
|
|
302
|
+
- Updated dependencies [112b9f2]
|
|
303
|
+
- Updated dependencies [893025e]
|
|
304
|
+
- Updated dependencies [eec5e9d]
|
|
305
|
+
- Updated dependencies [ebd4434]
|
|
306
|
+
- Updated dependencies [863d473]
|
|
307
|
+
- Updated dependencies [344f2f7]
|
|
308
|
+
- Updated dependencies [26f9ffd]
|
|
309
|
+
- Updated dependencies [10eae9a]
|
|
310
|
+
- Updated dependencies [22c6c06]
|
|
311
|
+
- Updated dependencies [df9a7d0]
|
|
312
|
+
- @ontrails/core@1.0.0-beta.16
|
|
313
|
+
- @ontrails/http@1.0.0-beta.16
|
|
314
|
+
|
|
315
|
+
## 1.0.0-beta.15
|
|
316
|
+
|
|
317
|
+
### Patch Changes
|
|
318
|
+
|
|
319
|
+
- Updated dependencies [4ad6b25]
|
|
320
|
+
- @ontrails/core@1.0.0-beta.15
|
|
321
|
+
- @ontrails/http@1.0.0-beta.15
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @ontrails/hono
|
|
2
|
+
|
|
3
|
+
Hono surface adapter for Trails. Use this package when you want to serve a topo over HTTP with Hono while keeping `@ontrails/http` focused on framework-agnostic route building and the shared Web Fetch kernel.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { surface } from '@ontrails/hono';
|
|
9
|
+
import { graph } from './app';
|
|
10
|
+
|
|
11
|
+
await surface(graph, { port: 3000 });
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
JSON request bodies are capped at 1 MiB by default. Override the cap with `maxJsonBodyBytes` when a surface intentionally accepts larger JSON payloads:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
await surface(graph, {
|
|
18
|
+
maxJsonBodyBytes: 2 * 1024 * 1024,
|
|
19
|
+
port: 3000,
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Pass `resolvePermit` to resolve HTTP `Authorization: Bearer ...` credentials into `ctx.permit` before protected trails execute. The adapter forwards request headers to the framework-agnostic HTTP route executor, so malformed Authorization headers return `401` and resolved permits with insufficient scopes return `403`.
|
|
24
|
+
|
|
25
|
+
Generic non-TrailsError failures return a redacted 500 response while a redacted diagnostic rendering is written to server diagnostics. `TrailsError` responses keep their taxonomy category and class name but redact sensitive message fragments before writing the public body.
|
|
26
|
+
|
|
27
|
+
For custom HTTP integrations or route inspection, keep using `deriveHttpRoutes()` from `@ontrails/http`. For a framework-neutral runtime handler, use `createRouteHandler()` or `createFetchHandler()` from `@ontrails/http/fetch`. For Bun-native serving without Hono, use `@ontrails/http/bun`.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
These commands target stable `0.2.0`. Run them after that version is published to npm.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun add --exact @ontrails/http@0.2.0 @ontrails/hono@0.2.0
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Migration
|
|
38
|
+
|
|
39
|
+
<!-- warden-ignore-next-line -->
|
|
40
|
+
This package replaces the old `@ontrails/http/hono` subpath.
|
|
41
|
+
|
|
42
|
+
<!-- warden-ignore-next-line -->
|
|
43
|
+
- Before: `import { trailhead } from '@ontrails/http/hono'`
|
|
44
|
+
- After: `import { surface } from '@ontrails/hono'`
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ontrails/hono",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/outfitter-dev/trails.git",
|
|
7
|
+
"directory": "adapters/hono"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"src/**/*.ts",
|
|
11
|
+
"!src/**/__tests__/**",
|
|
12
|
+
"!src/**/*.test.ts",
|
|
13
|
+
"!src/**/*.test-d.ts",
|
|
14
|
+
"README.md",
|
|
15
|
+
"CHANGELOG.md"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": "./src/index.ts",
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -b",
|
|
24
|
+
"test": "bun test",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"lint": "oxlint ./src",
|
|
27
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@ontrails/core": "^0.2.0",
|
|
31
|
+
"hono": "^4.7.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@ontrails/http": "^0.2.0",
|
|
35
|
+
"zod": "^4.3.5"
|
|
36
|
+
},
|
|
37
|
+
"trails": {
|
|
38
|
+
"adapter": {
|
|
39
|
+
"target": "http"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { InternalError, Result, trail } from '@ontrails/core';
|
|
2
|
+
import type { Trail } from '@ontrails/core';
|
|
3
|
+
import { createRouteHandler } from '@ontrails/http';
|
|
4
|
+
import type { HttpRouteDefinition } from '@ontrails/http';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
const caughtErrors = new Map<string, Error>();
|
|
8
|
+
const caughtErrorInput = z.object({ errorId: z.string() });
|
|
9
|
+
const caughtErrorTrail = trail('__ontrails.hono.error', {
|
|
10
|
+
implementation: () =>
|
|
11
|
+
Result.err(new InternalError('Hono error fallback executed directly')),
|
|
12
|
+
input: caughtErrorInput,
|
|
13
|
+
intent: 'read',
|
|
14
|
+
output: z.object({}),
|
|
15
|
+
}) as Trail<unknown, unknown, unknown>;
|
|
16
|
+
|
|
17
|
+
const caughtErrorRoute: HttpRouteDefinition = {
|
|
18
|
+
execute: async (input) => {
|
|
19
|
+
const parsed = caughtErrorInput.safeParse(input);
|
|
20
|
+
if (!parsed.success) {
|
|
21
|
+
return Result.err(
|
|
22
|
+
new InternalError('Hono error fallback missing error id')
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
const error =
|
|
26
|
+
caughtErrors.get(parsed.data.errorId) ??
|
|
27
|
+
new Error('Hono error fallback missing caught error');
|
|
28
|
+
return Result.err(error);
|
|
29
|
+
},
|
|
30
|
+
inputSource: 'query',
|
|
31
|
+
method: 'GET',
|
|
32
|
+
path: '/__ontrails/hono/error',
|
|
33
|
+
trail: caughtErrorTrail,
|
|
34
|
+
trailId: '__ontrails.hono.error',
|
|
35
|
+
};
|
|
36
|
+
const caughtErrorHandler = createRouteHandler(caughtErrorRoute);
|
|
37
|
+
|
|
38
|
+
const materializeCaughtErrorRequest = (
|
|
39
|
+
request: Request,
|
|
40
|
+
errorId: string
|
|
41
|
+
): Request => {
|
|
42
|
+
const url = new URL('/__ontrails/hono/error', request.url);
|
|
43
|
+
url.searchParams.set('errorId', errorId);
|
|
44
|
+
return new Request(url, {
|
|
45
|
+
headers: request.headers,
|
|
46
|
+
method: 'GET',
|
|
47
|
+
signal: request.signal,
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const handleCaughtHonoError = async (
|
|
52
|
+
error: unknown,
|
|
53
|
+
request: Request
|
|
54
|
+
): Promise<Response> => {
|
|
55
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
56
|
+
const errorId = crypto.randomUUID();
|
|
57
|
+
caughtErrors.set(errorId, err);
|
|
58
|
+
try {
|
|
59
|
+
return await caughtErrorHandler(
|
|
60
|
+
materializeCaughtErrorRequest(request, errorId)
|
|
61
|
+
);
|
|
62
|
+
} finally {
|
|
63
|
+
caughtErrors.delete(errorId);
|
|
64
|
+
}
|
|
65
|
+
};
|
package/src/index.ts
ADDED
package/src/surface.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hono adapter for Trails HTTP routes.
|
|
3
|
+
*
|
|
4
|
+
* Takes framework-agnostic HttpRouteDefinition[] and wires them into a
|
|
5
|
+
* Hono application, handling request parsing, response mapping, and errors.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* const graph = topo("myapp", entity);
|
|
9
|
+
* await surface(graph, { port: 3000 });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
BaseSurfaceOptions,
|
|
15
|
+
Layer,
|
|
16
|
+
ResourceOverrideMap,
|
|
17
|
+
Topo,
|
|
18
|
+
TrailContextInit,
|
|
19
|
+
} from '@ontrails/core';
|
|
20
|
+
import { Hono } from 'hono';
|
|
21
|
+
import type { Context as HonoContext } from 'hono';
|
|
22
|
+
import { createRouteHandler, deriveHttpRoutes } from '@ontrails/http';
|
|
23
|
+
import type {
|
|
24
|
+
HttpMethod,
|
|
25
|
+
HttpRouteDefinition,
|
|
26
|
+
ResolveHttpPermit,
|
|
27
|
+
} from '@ontrails/http';
|
|
28
|
+
import { handleCaughtHonoError } from './caught-error.js';
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Options
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Options for building a Trails HTTP app on Hono.
|
|
36
|
+
*/
|
|
37
|
+
export interface CreateAppOptions extends BaseSurfaceOptions {
|
|
38
|
+
readonly basePath?: string | undefined;
|
|
39
|
+
readonly createContext?:
|
|
40
|
+
| (() => TrailContextInit | Promise<TrailContextInit>)
|
|
41
|
+
| undefined;
|
|
42
|
+
readonly hostname?: string | undefined;
|
|
43
|
+
readonly layers?: readonly Layer[] | undefined;
|
|
44
|
+
/** Maximum JSON request body size in bytes. Defaults to 1 MiB. */
|
|
45
|
+
readonly maxJsonBodyBytes?: number | undefined;
|
|
46
|
+
readonly name?: string | undefined;
|
|
47
|
+
readonly port?: number | undefined;
|
|
48
|
+
readonly resources?: ResourceOverrideMap | undefined;
|
|
49
|
+
readonly resolvePermit?: ResolveHttpPermit | undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface RuntimeOptions {
|
|
53
|
+
readonly maxJsonBodyBytes?: number | undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Runtime handle returned by the Hono surface.
|
|
58
|
+
*/
|
|
59
|
+
export interface SurfaceHttpResult {
|
|
60
|
+
readonly close: () => Promise<void>;
|
|
61
|
+
readonly url: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Route registration
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
const materializeHonoRequest = async (c: HonoContext): Promise<Request> => {
|
|
69
|
+
if (!c.req.raw.bodyUsed) {
|
|
70
|
+
return c.req.raw;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const body = await c.req.text();
|
|
74
|
+
return new Request(c.req.raw.url, {
|
|
75
|
+
body,
|
|
76
|
+
headers: c.req.raw.headers,
|
|
77
|
+
method: c.req.raw.method,
|
|
78
|
+
signal: c.req.raw.signal,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/** Create a Hono handler from a route definition. */
|
|
83
|
+
const createHonoHandler = (
|
|
84
|
+
route: HttpRouteDefinition,
|
|
85
|
+
options: RuntimeOptions
|
|
86
|
+
): ((c: HonoContext) => Promise<Response>) => {
|
|
87
|
+
const handler = createRouteHandler(route, {
|
|
88
|
+
maxJsonBodyBytes: options.maxJsonBodyBytes,
|
|
89
|
+
});
|
|
90
|
+
return async (c) => handler(await materializeHonoRequest(c));
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/** Route registration keyed by HTTP method. */
|
|
94
|
+
const routeRegistrars: Record<
|
|
95
|
+
HttpMethod,
|
|
96
|
+
(
|
|
97
|
+
hono: Hono,
|
|
98
|
+
path: string,
|
|
99
|
+
handler: (c: HonoContext) => Promise<Response>
|
|
100
|
+
) => void
|
|
101
|
+
> = {
|
|
102
|
+
DELETE: (hono, path, handler) => {
|
|
103
|
+
hono.delete(path, handler);
|
|
104
|
+
},
|
|
105
|
+
GET: (hono, path, handler) => {
|
|
106
|
+
hono.get(path, handler);
|
|
107
|
+
},
|
|
108
|
+
PATCH: (hono, path, handler) => {
|
|
109
|
+
hono.patch(path, handler);
|
|
110
|
+
},
|
|
111
|
+
POST: (hono, path, handler) => {
|
|
112
|
+
hono.post(path, handler);
|
|
113
|
+
},
|
|
114
|
+
PUT: (hono, path, handler) => {
|
|
115
|
+
hono.put(path, handler);
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const registerRoutes = (
|
|
120
|
+
hono: Hono,
|
|
121
|
+
routes: HttpRouteDefinition[],
|
|
122
|
+
options: RuntimeOptions
|
|
123
|
+
): void => {
|
|
124
|
+
for (const route of routes) {
|
|
125
|
+
const handler = createHonoHandler(route, options);
|
|
126
|
+
routeRegistrars[route.method](hono, route.path, handler);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Global error handler
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
const handleCaughtError = async (
|
|
135
|
+
error: unknown,
|
|
136
|
+
c: HonoContext
|
|
137
|
+
): Promise<Response> => handleCaughtHonoError(error, c.req.raw);
|
|
138
|
+
|
|
139
|
+
const registerErrorHandler = (hono: Hono): void => {
|
|
140
|
+
// oxlint-disable-next-line prefer-await-to-callbacks -- Hono's onError API requires a callback
|
|
141
|
+
hono.onError((err, c) => handleCaughtError(err, c));
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// Validation
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// createApp
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Build HTTP routes from a topo and register them on a Hono app.
|
|
154
|
+
*
|
|
155
|
+
* @remarks This is a host materialization boundary. Derivation failures are
|
|
156
|
+
* thrown for HTTP bootstrap code after `deriveHttpRoutes` has already
|
|
157
|
+
* represented the framework error as a Result.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* import { createApp } from '@ontrails/hono';
|
|
162
|
+
*
|
|
163
|
+
* const app = createApp(graph, { basePath: '/api' });
|
|
164
|
+
* Bun.serve({ fetch: app.fetch, port: 3000 });
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export const createApp = (
|
|
168
|
+
graph: Topo,
|
|
169
|
+
options: CreateAppOptions = {}
|
|
170
|
+
): Hono => {
|
|
171
|
+
const hono = new Hono();
|
|
172
|
+
const runtimeOptions = {
|
|
173
|
+
maxJsonBodyBytes: options.maxJsonBodyBytes,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
registerErrorHandler(hono);
|
|
177
|
+
|
|
178
|
+
const routesResult = deriveHttpRoutes(graph, {
|
|
179
|
+
basePath: options.basePath,
|
|
180
|
+
configValues: options.configValues,
|
|
181
|
+
createContext: options.createContext,
|
|
182
|
+
exclude: options.exclude,
|
|
183
|
+
include: options.include,
|
|
184
|
+
intent: options.intent,
|
|
185
|
+
layers: options.layers,
|
|
186
|
+
resolvePermit: options.resolvePermit,
|
|
187
|
+
resources: options.resources,
|
|
188
|
+
validate: options.validate,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (routesResult.isErr()) {
|
|
192
|
+
throw routesResult.error;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
registerRoutes(hono, routesResult.value, runtimeOptions);
|
|
196
|
+
return hono;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const startServer = (
|
|
200
|
+
hono: Hono,
|
|
201
|
+
options: CreateAppOptions
|
|
202
|
+
): SurfaceHttpResult => {
|
|
203
|
+
const server = Bun.serve({
|
|
204
|
+
fetch: hono.fetch,
|
|
205
|
+
hostname: options.hostname ?? '0.0.0.0',
|
|
206
|
+
port: options.port ?? 3000,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
close: async () => {
|
|
211
|
+
await server.stop(true);
|
|
212
|
+
},
|
|
213
|
+
url: String(server.url),
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// surface
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Build a Hono app from a topo and start serving it with Bun.
|
|
223
|
+
*
|
|
224
|
+
* @remarks Always starts a Bun server. Use `createApp(graph)` for an
|
|
225
|
+
* unserved Hono app that you can wire into your own server.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* import { surface } from '@ontrails/hono';
|
|
230
|
+
*
|
|
231
|
+
* const server = await surface(graph, { port: 3000 });
|
|
232
|
+
* console.log(server.url);
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export const surface = async (
|
|
236
|
+
graph: Topo,
|
|
237
|
+
options: CreateAppOptions = {}
|
|
238
|
+
): Promise<SurfaceHttpResult> => {
|
|
239
|
+
// oxlint-disable-next-line require-await -- async ensures createApp() throws become rejected promises, not uncaught exceptions
|
|
240
|
+
const hono = createApp(graph, options);
|
|
241
|
+
return startServer(hono, options);
|
|
242
|
+
};
|