sygnal 7.0.0 → 7.2.0-preview.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.
Files changed (343) hide show
  1. package/CHANGELOG.md +632 -0
  2. package/dist/agent-ui.cjs.js +592 -0
  3. package/dist/agent-ui.cjs.js.map +1 -0
  4. package/dist/agent-ui.esm.js +582 -0
  5. package/dist/agent-ui.esm.js.map +1 -0
  6. package/dist/api.cjs.js +63 -0
  7. package/dist/api.cjs.js.map +1 -0
  8. package/dist/api.esm.js +2 -0
  9. package/dist/api.esm.js.map +1 -0
  10. package/dist/astro/index.cjs.js +968 -4
  11. package/dist/astro/index.cjs.js.map +1 -1
  12. package/dist/astro/index.mjs +968 -4
  13. package/dist/astro/index.mjs.map +1 -1
  14. package/dist/astro/server.cjs.js +73 -45
  15. package/dist/astro/server.cjs.js.map +1 -1
  16. package/dist/astro/server.mjs +73 -45
  17. package/dist/astro/server.mjs.map +1 -1
  18. package/dist/canvas.cjs.js +2919 -0
  19. package/dist/canvas.cjs.js.map +1 -0
  20. package/dist/canvas.esm.js +2866 -0
  21. package/dist/canvas.esm.js.map +1 -0
  22. package/dist/devtools.cjs.js +38 -6
  23. package/dist/devtools.cjs.js.map +1 -1
  24. package/dist/devtools.esm.js +38 -6
  25. package/dist/devtools.esm.js.map +1 -1
  26. package/dist/diagnostics.cjs.js +224 -20
  27. package/dist/diagnostics.cjs.js.map +1 -1
  28. package/dist/diagnostics.esm.js +224 -20
  29. package/dist/diagnostics.esm.js.map +1 -1
  30. package/dist/guide/accessibility.md +1 -1
  31. package/dist/guide/ai-compose.md +150 -0
  32. package/dist/guide/behaviors.md +2 -1
  33. package/dist/guide/collaborative-state.md +265 -0
  34. package/dist/guide/element-commands.md +36 -2
  35. package/dist/guide/forms-reference.md +5 -5
  36. package/dist/guide/forms.md +3 -2
  37. package/dist/guide/http.md +28 -1
  38. package/dist/guide/islands.md +240 -0
  39. package/dist/guide/recipes/code-editor.md +1 -1
  40. package/dist/guide/renderers/agent-ui.md +138 -0
  41. package/dist/guide/renderers/custom-targets.md +126 -0
  42. package/dist/guide/renderers/overview.md +120 -0
  43. package/dist/guide/renderers/react-native.md +128 -0
  44. package/dist/guide/renderers/terminal.md +306 -0
  45. package/dist/guide/renderers/three.md +332 -0
  46. package/dist/guide/renderers/write-once.md +137 -0
  47. package/dist/guide/resources.md +2 -0
  48. package/dist/guide/sandboxed-components.md +223 -0
  49. package/dist/guide/timers.md +32 -5
  50. package/dist/guide/typed-apis.md +442 -0
  51. package/dist/guide/ui/accordion.md +11 -0
  52. package/dist/guide/ui/combobox.md +112 -8
  53. package/dist/guide/ui/dialog.md +96 -20
  54. package/dist/guide/ui/menu.md +57 -5
  55. package/dist/guide/ui/overview.md +8 -4
  56. package/dist/guide/ui/popover.md +69 -9
  57. package/dist/guide/ui/select.md +54 -4
  58. package/dist/guide/ui/tabs.md +1 -1
  59. package/dist/guide/ui/tooltip.md +7 -5
  60. package/dist/guide/virtual-collections.md +3 -0
  61. package/dist/guide/widgets.md +90 -1
  62. package/dist/host.cjs.js +2181 -0
  63. package/dist/host.cjs.js.map +1 -0
  64. package/dist/host.esm.js +2146 -0
  65. package/dist/host.esm.js.map +1 -0
  66. package/dist/index.cjs.js +3948 -586
  67. package/dist/index.cjs.js.map +1 -1
  68. package/dist/index.d.ts +584 -44
  69. package/dist/index.esm.js +3918 -586
  70. package/dist/index.esm.js.map +1 -1
  71. package/dist/primitives.cjs.js +143 -0
  72. package/dist/primitives.cjs.js.map +1 -0
  73. package/dist/primitives.esm.js +133 -0
  74. package/dist/primitives.esm.js.map +1 -0
  75. package/dist/react-native.cjs.js +248 -0
  76. package/dist/react-native.cjs.js.map +1 -0
  77. package/dist/react-native.esm.js +244 -0
  78. package/dist/react-native.esm.js.map +1 -0
  79. package/dist/replay.cjs.js +39 -0
  80. package/dist/replay.cjs.js.map +1 -0
  81. package/dist/replay.esm.js +2 -0
  82. package/dist/replay.esm.js.map +1 -0
  83. package/dist/sandbox-build.cjs.js +140 -0
  84. package/dist/sandbox-build.cjs.js.map +1 -0
  85. package/dist/sandbox-build.esm.js +137 -0
  86. package/dist/sandbox-build.esm.js.map +1 -0
  87. package/dist/sandbox-kernel.esm.js +212 -0
  88. package/dist/sandbox-kernel.esm.js.map +1 -0
  89. package/dist/sandbox-worker.cjs.js +857 -0
  90. package/dist/sandbox-worker.cjs.js.map +1 -0
  91. package/dist/sandbox-worker.esm.js +854 -0
  92. package/dist/sandbox-worker.esm.js.map +1 -0
  93. package/dist/sandbox.cjs.js +1425 -0
  94. package/dist/sandbox.cjs.js.map +1 -0
  95. package/dist/sandbox.esm.js +1406 -0
  96. package/dist/sandbox.esm.js.map +1 -0
  97. package/dist/sygnal.min.js +1 -1
  98. package/dist/sygnal.min.js.map +1 -1
  99. package/dist/terminal.cjs.js +1314 -0
  100. package/dist/terminal.cjs.js.map +1 -0
  101. package/dist/terminal.esm.js +1304 -0
  102. package/dist/terminal.esm.js.map +1 -0
  103. package/dist/three.cjs.js +1111 -0
  104. package/dist/three.cjs.js.map +1 -0
  105. package/dist/three.esm.js +1079 -0
  106. package/dist/three.esm.js.map +1 -0
  107. package/dist/ui-combobox.cjs.js +256 -18
  108. package/dist/ui-combobox.cjs.js.map +1 -1
  109. package/dist/ui-combobox.esm.js +256 -18
  110. package/dist/ui-combobox.esm.js.map +1 -1
  111. package/dist/ui-menu.cjs.js +150 -16
  112. package/dist/ui-menu.cjs.js.map +1 -1
  113. package/dist/ui-menu.esm.js +151 -17
  114. package/dist/ui-menu.esm.js.map +1 -1
  115. package/dist/ui-select.cjs.js +95 -9
  116. package/dist/ui-select.cjs.js.map +1 -1
  117. package/dist/ui-select.esm.js +95 -9
  118. package/dist/ui-select.esm.js.map +1 -1
  119. package/dist/ui.cjs.js +679 -173
  120. package/dist/ui.cjs.js.map +1 -1
  121. package/dist/ui.esm.js +679 -175
  122. package/dist/ui.esm.js.map +1 -1
  123. package/dist/vike/config/package.json +1 -1
  124. package/dist/vite/plugin.cjs.js +968 -4
  125. package/dist/vite/plugin.cjs.js.map +1 -1
  126. package/dist/vite/plugin.mjs +968 -4
  127. package/dist/vite/plugin.mjs.map +1 -1
  128. package/dist/worker-page.cjs.js +669 -0
  129. package/dist/worker-page.cjs.js.map +1 -0
  130. package/dist/worker-page.esm.js +665 -0
  131. package/dist/worker-page.esm.js.map +1 -0
  132. package/dist/worker.cjs.js +377 -0
  133. package/dist/worker.cjs.js.map +1 -0
  134. package/dist/worker.esm.js +374 -0
  135. package/dist/worker.esm.js.map +1 -0
  136. package/dist/yjs-testing.cjs.js +98 -0
  137. package/dist/yjs-testing.cjs.js.map +1 -0
  138. package/dist/yjs-testing.esm.js +77 -0
  139. package/dist/yjs-testing.esm.js.map +1 -0
  140. package/dist/yjs.cjs.js +923 -0
  141. package/dist/yjs.cjs.js.map +1 -0
  142. package/dist/yjs.esm.js +900 -0
  143. package/dist/yjs.esm.js.map +1 -0
  144. package/dist/zag.cjs.js +11 -1
  145. package/dist/zag.cjs.js.map +1 -1
  146. package/dist/zag.esm.js +11 -1
  147. package/dist/zag.esm.js.map +1 -1
  148. package/llms/ai.md +65 -0
  149. package/llms/collaboration.md +5 -0
  150. package/llms/graphics.md +10 -0
  151. package/llms/renderers.md +7 -0
  152. package/llms/replay.md +5 -0
  153. package/llms/sandbox.md +5 -0
  154. package/llms/typed-apis.md +5 -0
  155. package/llms/ui.md +10 -0
  156. package/llms-full.txt +444 -0
  157. package/llms.txt +37 -35
  158. package/package.json +139 -3
  159. package/src/agent-ui/mcp.ts +152 -0
  160. package/src/agent-ui/snapshot.ts +212 -0
  161. package/src/agent-ui.d.ts +106 -0
  162. package/src/agent-ui.ts +249 -0
  163. package/src/ai.d.ts +95 -2
  164. package/src/api.d.ts +303 -0
  165. package/src/api.ts +9 -0
  166. package/src/canvas/Canvas.ts +585 -0
  167. package/src/canvas/backend.ts +627 -0
  168. package/src/canvas/geometry.ts +187 -0
  169. package/src/canvas/gesture.ts +23 -0
  170. package/src/canvas/image.ts +197 -0
  171. package/src/canvas/kit.ts +130 -0
  172. package/src/canvas/paint.ts +260 -0
  173. package/src/canvas/pointer.ts +25 -0
  174. package/src/canvas/snap.ts +68 -0
  175. package/src/canvas/svg.ts +99 -0
  176. package/src/canvas.d.ts +373 -0
  177. package/src/canvas.ts +46 -0
  178. package/src/core/actions.ts +14 -3
  179. package/src/core/cell.ts +12 -4
  180. package/src/core/debug.ts +8 -3
  181. package/src/core/hooks.ts +16 -2
  182. package/src/core/hosts/collection.ts +1 -1
  183. package/src/core/hosts/switchable.ts +26 -8
  184. package/src/core/instance.ts +98 -45
  185. package/src/core/markers/portal.ts +4 -0
  186. package/src/core/registry.ts +4 -0
  187. package/src/core/runtime.ts +34 -25
  188. package/src/core/statics.ts +5 -5
  189. package/src/cycle/dom/EventDelegator.ts +37 -33
  190. package/src/cycle/dom/MainDOMSource.ts +16 -14
  191. package/src/cycle/dom/enrichEventStream.ts +13 -9
  192. package/src/cycle/dom/fromEvent.ts +6 -10
  193. package/src/cycle/dom/index.ts +11 -7
  194. package/src/cycle/dom/isolate.ts +13 -6
  195. package/src/cycle/dom/makeDOMDriver.ts +6 -2
  196. package/src/cycle/dom/utils.ts +9 -2
  197. package/src/cycle/run/adapt.ts +4 -12
  198. package/src/devtools.d.ts +9 -0
  199. package/src/devtools.ts +2 -1
  200. package/src/extra/ai/compose/catalog.ts +2 -1
  201. package/src/extra/ai/compose/decisions.ts +1 -2
  202. package/src/extra/ai/compose/generated.ts +234 -0
  203. package/src/extra/ai/compose/index.ts +6 -2
  204. package/src/extra/ai/compose/layout.ts +3 -1
  205. package/src/extra/ai/compose/llm.ts +7 -3
  206. package/src/extra/ai/compose/types.ts +2 -2
  207. package/src/extra/ai/transports/shared.ts +3 -1
  208. package/src/extra/api/contract.ts +485 -0
  209. package/src/extra/api/index.ts +26 -0
  210. package/src/extra/behaviors.ts +3 -3
  211. package/src/extra/controlled.ts +44 -0
  212. package/src/extra/copyAsTest.ts +22 -0
  213. package/src/extra/devtools.ts +5 -3
  214. package/src/extra/devtoolsActions.ts +8 -0
  215. package/src/extra/devtoolsNext.ts +1 -1
  216. package/src/extra/diagnostics/checks/actionLog.ts +8 -3
  217. package/src/extra/diagnostics/checks/behaviors.ts +25 -0
  218. package/src/extra/diagnostics/checks/elementCommands.ts +17 -5
  219. package/src/extra/diagnostics/checks/index.ts +1 -1
  220. package/src/extra/diagnostics/checks/next.ts +78 -4
  221. package/src/extra/diagnostics/checks/props.ts +6 -1
  222. package/src/extra/diagnostics/checks/replies.ts +11 -7
  223. package/src/extra/diagnostics/checks/timers.ts +8 -2
  224. package/src/extra/diagnostics/checks/virtual.ts +11 -0
  225. package/src/extra/diagnostics/codes.ts +51 -1
  226. package/src/extra/elementCommands.ts +20 -4
  227. package/src/extra/fetchDriver.ts +4 -1
  228. package/src/extra/fetchEventSource.ts +6 -2
  229. package/src/extra/field.ts +29 -0
  230. package/src/extra/form.ts +42 -16
  231. package/src/extra/frame.ts +54 -0
  232. package/src/extra/keymap.ts +41 -0
  233. package/src/extra/pager.ts +2 -0
  234. package/src/extra/persist.ts +2 -1
  235. package/src/extra/pointer.ts +262 -0
  236. package/src/extra/processForm.ts +34 -1
  237. package/src/extra/replay/address.ts +49 -0
  238. package/src/extra/replay/entropy.ts +99 -0
  239. package/src/extra/replay/format.ts +263 -0
  240. package/src/extra/replay/index.ts +8 -0
  241. package/src/extra/replay/inert.ts +22 -0
  242. package/src/extra/replay/recorder.ts +247 -0
  243. package/src/extra/replay/replayer.ts +234 -0
  244. package/src/extra/replay/report.ts +126 -0
  245. package/src/extra/replay/schema.ts +52 -0
  246. package/src/extra/replay/version.ts +3 -0
  247. package/src/extra/router.ts +7 -3
  248. package/src/extra/selection.ts +2 -0
  249. package/src/extra/socketDriver.ts +51 -6
  250. package/src/extra/ssr.ts +128 -42
  251. package/src/extra/testing.ts +295 -39
  252. package/src/extra/timers.ts +96 -7
  253. package/src/extra/undo.ts +2 -0
  254. package/src/extra/virtual.ts +25 -2
  255. package/src/extra/widget.ts +106 -17
  256. package/src/host/actions.ts +383 -0
  257. package/src/host/delegation.ts +101 -0
  258. package/src/host/dom.ts +553 -0
  259. package/src/host/driver.ts +185 -0
  260. package/src/host/selector.ts +119 -0
  261. package/src/host/style.ts +51 -0
  262. package/src/host.d.ts +298 -0
  263. package/src/host.ts +46 -0
  264. package/src/index.d.ts +302 -38
  265. package/src/index.ts +15 -3
  266. package/src/pragma/blocks.ts +211 -0
  267. package/src/pragma/index.ts +44 -10
  268. package/src/primitives.d.ts +54 -0
  269. package/src/primitives.ts +136 -0
  270. package/src/react-native.d.ts +57 -0
  271. package/src/react-native.ts +285 -0
  272. package/src/react-peers.d.ts +21 -3
  273. package/src/replay.d.ts +185 -0
  274. package/src/replay.ts +6 -0
  275. package/src/sandbox/build.ts +119 -0
  276. package/src/sandbox/create.ts +187 -0
  277. package/src/sandbox/engine.ts +267 -0
  278. package/src/sandbox/generated.ts +195 -0
  279. package/src/sandbox/kernel.ts +180 -0
  280. package/src/sandbox/mirror.ts +269 -0
  281. package/src/sandbox/protocol.ts +128 -0
  282. package/src/sandbox/quickjs.ts +74 -0
  283. package/src/sandbox/ssr.ts +41 -0
  284. package/src/sandbox/widget.ts +60 -0
  285. package/src/sandbox/worker-entry.ts +59 -0
  286. package/src/sandbox/worker.ts +137 -0
  287. package/src/sandbox-build.d.ts +12 -0
  288. package/src/sandbox-build.ts +6 -0
  289. package/src/sandbox.d.ts +299 -0
  290. package/src/sandbox.ts +25 -0
  291. package/src/shared.ts +12 -0
  292. package/src/terminal/paint.ts +712 -0
  293. package/src/terminal.d.ts +167 -0
  294. package/src/terminal.ts +530 -0
  295. package/src/three/assets.ts +170 -0
  296. package/src/three/host.ts +36 -0
  297. package/src/three/scene.ts +217 -0
  298. package/src/three/target.ts +252 -0
  299. package/src/three.d.ts +221 -0
  300. package/src/three.ts +30 -0
  301. package/src/ui/accordion.ts +21 -7
  302. package/src/ui/dialog.ts +192 -90
  303. package/src/ui/disclosure.ts +2 -0
  304. package/src/ui/dom.ts +30 -0
  305. package/src/ui/layers.ts +132 -0
  306. package/src/ui/popover.ts +120 -21
  307. package/src/ui/shared.ts +98 -12
  308. package/src/ui/stack.ts +18 -0
  309. package/src/ui/tabs.ts +2 -0
  310. package/src/ui/toaster.ts +16 -15
  311. package/src/ui/tooltip.ts +24 -8
  312. package/src/ui/tooltips.ts +26 -14
  313. package/src/ui/zag/combobox.ts +180 -13
  314. package/src/ui/zag/menu.ts +97 -17
  315. package/src/ui/zag/select.ts +15 -4
  316. package/src/ui/zag/shared.ts +60 -8
  317. package/src/ui-combobox.d.ts +16 -1
  318. package/src/ui-menu.d.ts +22 -7
  319. package/src/ui-zag-types.d.ts +13 -5
  320. package/src/ui.d.ts +62 -7
  321. package/src/ui.ts +2 -2
  322. package/src/vite/api.ts +186 -0
  323. package/src/vite/compile.ts +280 -0
  324. package/src/vite/plugin.d.ts +34 -0
  325. package/src/vite/plugin.ts +78 -4
  326. package/src/vite/sandbox.ts +16 -0
  327. package/src/worker/page.ts +396 -0
  328. package/src/worker/protocol.ts +48 -0
  329. package/src/worker/target.ts +282 -0
  330. package/src/worker-page.d.ts +42 -0
  331. package/src/worker-page.ts +12 -0
  332. package/src/worker.d.ts +65 -0
  333. package/src/worker.ts +16 -0
  334. package/src/yjs/driver.ts +253 -0
  335. package/src/yjs/mapping.ts +389 -0
  336. package/src/yjs/shared.ts +138 -0
  337. package/src/yjs/testing.ts +91 -0
  338. package/src/yjs-testing.d.ts +34 -0
  339. package/src/yjs-testing.ts +7 -0
  340. package/src/yjs.d.ts +109 -0
  341. package/src/yjs.ts +18 -0
  342. package/src/zag.d.ts +2 -0
  343. package/src/zag.ts +8 -1
package/src/api.d.ts ADDED
@@ -0,0 +1,303 @@
1
+ // Types for 'sygnal/api' (dev preview). The implementation lives in src/extra/api/.
2
+ // Structural only: no oRPC, openapi-typescript or Hono types are imported, so an app needs only
3
+ // the library it uses.
4
+ import type { ResourceRequest, SseConnection, FetchFailure, StandardSchemaLike } from 'sygnal'
5
+
6
+ // ── JSON on the wire ───────────────────────────────────────────────────
7
+
8
+ /**
9
+ * What a value becomes after JSON: a `Date` is an ISO string, functions and symbols are gone,
10
+ * `undefined` properties are optional. Replies are typed with it (the server's `Date` arrives as
11
+ * a string).
12
+ */
13
+ export type Jsonify<T> =
14
+ T extends Date ? string :
15
+ T extends string | number | boolean | null ? T :
16
+ T extends bigint | symbol | ((...args: any[]) => any) ? never :
17
+ T extends readonly (infer U)[] ? Jsonify<U>[] :
18
+ T extends object ? { [K in keyof T as T[K] extends ((...args: any[]) => any) | symbol ? never : K]: Jsonify<T[K]> } :
19
+ T
20
+
21
+ type SchemaIn<S> = S extends StandardSchemaLike<infer I, any> ? I : unknown
22
+ type SchemaOut<S> = S extends StandardSchemaLike<any, infer O> ? O : unknown
23
+ /** optional input (undefined allowed, or an object of optional fields): the argument may be left out */
24
+ type Args<IN, OPTS> = undefined extends IN ? [input?: IN, options?: OPTS] : {} extends IN ? [input?: IN, options?: OPTS] : [input: IN, options?: OPTS]
25
+
26
+ // ── endpoints and their requests ───────────────────────────────────────
27
+
28
+ /** A request built by an endpoint: a FetchRequest that remembers the reply and error types (phantom) */
29
+ export type ApiRequest<OUT = unknown, ERR = unknown> = Exclude<ResourceRequest, string> & {
30
+ /** the endpoint id (an app key: not sent) */
31
+ endpoint: string
32
+ readonly '~output'?: OUT
33
+ readonly '~error'?: ERR
34
+ }
35
+ /** A stream connection built by an endpoint, for the `connections` static */
36
+ export type ApiStream<OUT = unknown> = SseConnection & { endpoint: string; readonly '~output'?: OUT }
37
+
38
+ /** The fields a call may add to its request: reply actions, `latest`, `key`, cache and retry options, ... */
39
+ export type CallOptions = Omit<Exclude<ResourceRequest, string>, 'url' | 'method' | 'json' | 'body' | 'query' | 'multipart' | 'invalidates'> & {
40
+ /** After a 2xx reply, refetch the resources of these GET endpoints (or tags) */
41
+ invalidates?: ({ readonly id: string; readonly kind: 'query' | 'mutation' } | string)[]
42
+ [key: string]: any
43
+ }
44
+ /** The actions and options of a stream connection (`message: 'ARRIVED'`, `open`, `close`, `resume`, ...) */
45
+ export type StreamOptions = Omit<SseConnection, 'sse'>
46
+
47
+ type EndpointInfo<K> = {
48
+ /** `quotes.list` (oRPC: the router keys), `GET /quotes/{id}` (OpenAPI, Hono), `SSE /feed` */
49
+ readonly id: string
50
+ readonly kind: K
51
+ readonly method: string
52
+ /** The path as the contract declares it (`/quotes/{id}`, `/quotes/:id`) */
53
+ readonly path: string
54
+ /** Whether a request (in its `t.requests` form) was built by this endpoint */
55
+ match(request: unknown): boolean
56
+ }
57
+
58
+ /**
59
+ * One endpoint of a client: builds the request (or stream connection) for an input. `OUT` is the
60
+ * reply as JSON delivers it; `RAW` the server's value before JSON (a `Date` where OUT has a string)
61
+ */
62
+ export type Endpoint<IN, OUT, ERR = unknown, K extends 'query' | 'mutation' | 'stream' = 'query' | 'mutation' | 'stream', RAW = OUT> =
63
+ (K extends 'stream'
64
+ ? (...args: Args<IN, StreamOptions>) => ApiStream<OUT>
65
+ : (...args: Args<IN, CallOptions>) => ApiRequest<OUT, ERR>) & EndpointInfo<K> & { readonly '~raw'?: RAW }
66
+ /** The server's value of an endpoint's reply, before JSON (what fixture() takes) */
67
+ export type RawOutput<E> = E extends { readonly '~raw'?: infer R } ? R : Output<E>
68
+
69
+ /**
70
+ * The data of the endpoint's `ok` reply action (or of each stream event), as JSON delivers it:
71
+ * `type Actions = { LOADED: Output<typeof api.quotes.get> }`
72
+ */
73
+ export type Output<E> =
74
+ E extends (...args: any[]) => { readonly '~output'?: infer O } ? O :
75
+ E extends { readonly '~output'?: infer O } ? O : never
76
+ /** The input an endpoint takes */
77
+ export type Input<E> = E extends (...args: infer A) => any ? A[0] : never
78
+ /** The body of the endpoint's error replies (oRPC: its declared errors, by `code`) */
79
+ export type ErrorBody<E> =
80
+ E extends (...args: any[]) => { readonly '~error'?: infer X } ? X :
81
+ E extends { readonly '~error'?: infer X } ? X : unknown
82
+ /**
83
+ * The data of the endpoint's `error` reply action: a FetchFailure whose `body` is typed:
84
+ * `type Actions = { FAILED: ApiFailure<typeof api.quotes.add> }`
85
+ */
86
+ export type ApiFailure<E> = Omit<FetchFailure, 'body'> & { body?: ErrorBody<E> }
87
+
88
+ /** Client options shared by every adapter */
89
+ export type ClientOptions = {
90
+ /** Prefix of every path (oRPC: the handler's `prefix`, e.g. '/api') */
91
+ prefix?: string
92
+ /** Headers on every request and stream (e.g. `{ 'x-api-contract': contractHash(contract) }`) */
93
+ headers?: Record<string, string>
94
+ /** oRPC: validate replies against the output schemas on the client too (`validate` on each request; default false) */
95
+ validate?: boolean
96
+ }
97
+
98
+ // ── oRPC ───────────────────────────────────────────────────────────────
99
+
100
+ /** oRPC's error body (OpenAPIHandler): a declared error, by code, or an undeclared one */
101
+ export type OrpcErrorBody<EM> =
102
+ | { [C in keyof EM & string]: { defined: true; code: C; status: number; message: string; data: Jsonify<EM[C] extends { data?: infer D } ? SchemaOut<D> : undefined> } }[keyof EM & string]
103
+ | { defined: false; code: string; status: number; message: string; data?: { issues?: { message: string; path?: (string | number)[] }[] } & Record<string, unknown> }
104
+
105
+ type OrpcProcedure = { '~orpc': { route: unknown; errorMap: unknown; inputSchema?: unknown; outputSchema?: unknown } }
106
+ type OrpcEndpoint<P> = P extends { '~orpc': { inputSchema?: infer I; outputSchema?: infer O; errorMap: infer EM } }
107
+ ? SchemaOut<O> extends AsyncIterable<infer Y>
108
+ ? Endpoint<unknown extends SchemaIn<I> ? undefined : SchemaIn<I>, Jsonify<Y>, OrpcErrorBody<EM>, 'stream', Y>
109
+ : Endpoint<unknown extends SchemaIn<I> ? undefined : SchemaIn<I>, Jsonify<SchemaOut<O>>, OrpcErrorBody<EM>, 'query' | 'mutation', SchemaOut<O>>
110
+ : never
111
+ /** The client of an oRPC contract router: the same tree, each procedure an Endpoint */
112
+ export type OrpcClient<R> = R extends OrpcProcedure ? OrpcEndpoint<R> : { [K in keyof R]: OrpcClient<R[K]> }
113
+
114
+ /**
115
+ * A client for an oRPC contract router served by oRPC's **OpenAPIHandler** (plain JSON):
116
+ * `const api = orpcClient(contract, { prefix: '/api' })`; `api.quotes.list({ tag })` is a GET
117
+ * request (a resource), `api.quotes.add(input, { ok: 'ADDED', error: 'FAILED' })` a POST, and an
118
+ * event iterator procedure (`.route({ method: 'GET' })`) an SSE connection. GET input goes in the
119
+ * query string in bracket notation, so its non-string fields need coercing schemas (`z.coerce.number()`).
120
+ */
121
+ export function orpcClient<R>(contract: R, options?: ClientOptions): OrpcClient<R>
122
+
123
+ // ── openapi-typescript ─────────────────────────────────────────────────
124
+
125
+ type Method = 'get' | 'post' | 'put' | 'patch' | 'delete'
126
+ type Op<P, Path extends keyof P, M extends Method> = P[Path] extends { [K in M]: infer O } ? O : never
127
+ type PathsWith<P, M extends Method> = { [K in keyof P]: P[K] extends { [X in M]: infer O } ? ([O] extends [never | undefined] ? never : K) : never }[keyof P] & string
128
+ type JsonOf<C> = C extends { content: { 'application/json': infer J } } ? J : C extends { content: { [k: string]: infer J } } ? J : undefined
129
+ type Ok = 200 | 201 | 202 | 203 | 204 | 206 | '200' | '201' | '202' | '203' | '204' | '206' | '2XX'
130
+ type OpOutput<O> = O extends { responses: infer R } ? { [S in keyof R]: S extends Ok ? JsonOf<R[S]> : never }[keyof R] : unknown
131
+ type OpError<O> = O extends { responses: infer R } ? { [S in keyof R]: S extends Ok ? never : JsonOf<R[S]> }[keyof R] : unknown
132
+ type Defined<T> = [T] extends [never] ? false : [T] extends [undefined] ? false : true
133
+ type OpParams<O> = O extends { parameters: infer PS }
134
+ ? { [K in keyof PS as K extends 'path' | 'query' | 'header' ? (Defined<PS[K]> extends true ? K : never) : never]: PS[K] }
135
+ : {}
136
+ type OpInput<O> =
137
+ (keyof OpParams<O> extends never ? {} : {} extends OpParams<O> ? { params?: OpParams<O> } : { params: OpParams<O> }) &
138
+ (O extends { requestBody: infer B } ? { body: JsonOf<B> } : O extends { requestBody?: infer B } ? (Defined<B> extends true ? { body?: JsonOf<B> } : {}) : {})
139
+ type MaybeInput<I> = {} extends I ? I | undefined : I
140
+
141
+ /** A client for openapi-typescript's `paths` (types only): `openApiClient<paths>().get('/quotes/{id}')` is an endpoint */
142
+ export type OpenApiClient<P> = {
143
+ [M in Method]: <Path extends PathsWith<P, M>>(path: Path) =>
144
+ Endpoint<MaybeInput<OpInput<Op<P, Path, M>>>, Jsonify<OpOutput<Op<P, Path, M>>>, OpError<Op<P, Path, M>>, M extends 'get' ? 'query' : 'mutation'>
145
+ } & {
146
+ /** A GET path that answers with server-sent events; `T` is the type of one event's data */
147
+ sse<T = unknown, Path extends PathsWith<P, 'get'> = PathsWith<P, 'get'>>(path: Path): Endpoint<MaybeInput<OpInput<Op<P, Path, 'get'>>>, T, unknown, 'stream'>
148
+ }
149
+ /**
150
+ * A client for an OpenAPI API through openapi-typescript's generated `paths` (any back end:
151
+ * Go, Python, oRPC's OpenAPIGenerator, ...). Input is openapi-fetch's `{ params: { path, query },
152
+ * body }`; query arrays repeat the key, objects use `key[field]`.
153
+ */
154
+ export function openApiClient<P = Record<string, any>>(options?: ClientOptions): OpenApiClient<P>
155
+
156
+ // ── Hono ───────────────────────────────────────────────────────────────
157
+
158
+ type HonoOk = 200 | 201 | 202 | 203 | 204 | 206
159
+ type HonoEp<S, Path extends keyof S, M extends Method> = S[Path] extends { [K in `$${M}`]: infer E } ? E : never
160
+ type HonoPaths<S, M extends Method> = { [K in keyof S]: S[K] extends { [X in `$${M}`]: any } ? K : never }[keyof S] & string
161
+ type HonoOutput<E> = E extends { output: infer O; status: infer St } ? (St extends HonoOk ? O : never) : never
162
+ type HonoError<E> = E extends { output: infer O; status: infer St } ? (St extends HonoOk ? never : O) : never
163
+ type HonoInput<E> = E extends { input: infer I } ? I : {}
164
+
165
+ /** A client for a Hono app's routes (types only): `honoClient<ExtractSchema<typeof app>>().get('/quotes/:id')` */
166
+ export type HonoClient<S> = {
167
+ [M in Method]: <Path extends HonoPaths<S, M>>(path: Path) =>
168
+ Endpoint<MaybeInput<HonoInput<HonoEp<S, Path, M>>>, Jsonify<HonoOutput<HonoEp<S, Path, M>>>, HonoError<HonoEp<S, Path, M>>, M extends 'get' ? 'query' : 'mutation'>
169
+ } & {
170
+ /** A GET route that streams server-sent events (`streamSSE`); `T` is the type of one event's data */
171
+ sse<T = unknown, Path extends HonoPaths<S, 'get'> = HonoPaths<S, 'get'>>(path: Path): Endpoint<MaybeInput<HonoInput<HonoEp<S, Path, 'get'>>>, T, unknown, 'stream'>
172
+ }
173
+ /**
174
+ * A client for Hono routes. Pass the app's schema with Hono's own `ExtractSchema<typeof app>`
175
+ * (from 'hono/types'). Input is hc's `{ param, query, json }`.
176
+ */
177
+ export function honoClient<S = Record<string, any>>(options?: ClientOptions): HonoClient<S>
178
+
179
+ // ── contract hash and version skew ─────────────────────────────────────
180
+
181
+ /**
182
+ * A stable hash of a contract: for an oRPC router its ids, routes, input/output JSON Schemas
183
+ * (Standard JSON Schema) and error codes; for anything else (an OpenAPI document) its stable
184
+ * JSON. Send it as a header (`headers` option) and check it on the server with contractSkew.
185
+ */
186
+ export function contractHash(contract: unknown): string
187
+ /**
188
+ * On the server, before the API handler: a request whose `header` carries another hash is
189
+ * answered 409 CONTRACT_SKEW (oRPC's error shape, `data: { client, server }`); otherwise
190
+ * undefined. Requests without the header pass unless `require: true`.
191
+ */
192
+ export function contractSkew(request: Request, options: { hash: string; header: string; require?: boolean }): Response | undefined
193
+ /** Whether an `error` reply is a CONTRACT_SKEW answer (the app is older than the server's API) */
194
+ export function isContractSkew(failure: unknown): boolean
195
+ /**
196
+ * A `fetch` for makeFetchDriver / makeSocketDriver that notices CONTRACT_SKEW answers: reports
197
+ * SYG690 once and calls `onSkew` for each (e.g. to offer a reload).
198
+ */
199
+ export function contractFetch(options?: {
200
+ fetch?: (input: any, init?: any) => Promise<Response>
201
+ onSkew?: (info: { server: string | null; url: string }) => void
202
+ }): (input: any, init?: any) => Promise<Response>
203
+
204
+ // ── test fixtures ──────────────────────────────────────────────────────
205
+
206
+ /**
207
+ * A reply body for `t.respond` (or one event for `t.push`): the server's value (a `Date` stays a
208
+ * `Date`), typed by the endpoint and, for an oRPC contract, checked against its output schema (a
209
+ * fixture that drifted from the contract throws). Returned as JSON delivers it.
210
+ */
211
+ export function fixture<E extends Endpoint<any, any, any, any, any>>(endpoint: E, data: RawOutput<E>): Output<E>
212
+ /**
213
+ * An error reply in oRPC's shape, its data checked against the declared error's schema:
214
+ * `const e = errorFixture(api.quotes.add, 'DUPLICATE', { id: 1 }); await t.fail('HTTP', e.status, { body: e.body })`
215
+ */
216
+ export function errorFixture<E extends Endpoint<any, any, any, any, any>, C extends DefinedCode<E>>(
217
+ endpoint: E, code: C, data?: Extract<ErrorBody<E>, { code: C }> extends { data: infer D } ? D : unknown, message?: string,
218
+ ): { status: number; body: [Extract<ErrorBody<E>, { code: C }>] extends [never] ? { defined: true; code: C; status: number; message: string; data: unknown } : Extract<ErrorBody<E>, { code: C }> }
219
+ /** The codes of an endpoint's declared errors (oRPC), else any string */
220
+ type DefinedCode<E> = [Extract<ErrorBody<E>, { defined: true }>] extends [never] ? string : Extract<ErrorBody<E>, { defined: true }>['code']
221
+
222
+ // ── function-first: *.server.ts modules ────────────────────────────────
223
+
224
+ /**
225
+ * The `context` a server function gets: whatever the server passes to oRPC's
226
+ * `handler.handle(request, { context })`. Augment it for your app:
227
+ * `declare module 'sygnal/api' { interface ServerContext { user?: User } }`
228
+ */
229
+ export interface ServerContext { [key: string]: unknown }
230
+
231
+ type ErrorMapOf = Record<string, { status?: number; message?: string; data?: StandardSchemaLike<any, any> }>
232
+ /** What a server function gets after its input: oRPC's handler options */
233
+ export type ServerFunctionOptions<EM = {}> = {
234
+ context: ServerContext
235
+ signal?: AbortSignal
236
+ lastEventId?: string
237
+ /** oRPC's declared-error constructors: `throw errors.DUPLICATE({ data: { id } })` */
238
+ errors: { [C in keyof EM & string]: (options?: { message?: string; data?: EM[C] extends { data?: infer D } ? SchemaIn<D> : undefined; cause?: unknown }) => Error }
239
+ }
240
+ type FnOptions<EM> = {
241
+ /** Validate the reply too (oRPC's `.output()`; each event of a stream) */
242
+ output?: StandardSchemaLike<any, any>
243
+ /** Declared errors, by code (oRPC's `.errors()`): typed on the client as `ErrorBody` */
244
+ errors?: EM
245
+ }
246
+
247
+ /**
248
+ * A query in a `*.server.ts` module: a POST that is a resource (tagged `api:<id>`, refetched by
249
+ * `invalidates`). Its input is always validated: pass a Standard Schema, or leave it out to take
250
+ * no input. `export const list = query(z.object({ tag: z.string() }), async ({ tag }) => db.list(tag))`
251
+ * gives the client (through sygnal/vite's stub) `list({ tag }, { ok: 'LISTED' })`.
252
+ */
253
+ export function query<S extends StandardSchemaLike<any, any>, R, EM extends ErrorMapOf = {}>(
254
+ input: S, fn: (input: SchemaOut<S>, options: ServerFunctionOptions<EM>) => R, options?: FnOptions<EM>,
255
+ ): Endpoint<SchemaIn<S>, Jsonify<Awaited<R>>, OrpcErrorBody<EM>, 'query', Awaited<R>>
256
+ export function query<R, EM extends ErrorMapOf = {}>(
257
+ fn: (input: undefined, options: ServerFunctionOptions<EM>) => R, options?: FnOptions<EM>,
258
+ ): Endpoint<undefined, Jsonify<Awaited<R>>, OrpcErrorBody<EM>, 'query', Awaited<R>>
259
+ /** A mutation in a `*.server.ts` module: a POST with reply actions (`ok`, `error`, `invalidates`) */
260
+ export function mutation<S extends StandardSchemaLike<any, any>, R, EM extends ErrorMapOf = {}>(
261
+ input: S, fn: (input: SchemaOut<S>, options: ServerFunctionOptions<EM>) => R, options?: FnOptions<EM>,
262
+ ): Endpoint<SchemaIn<S>, Jsonify<Awaited<R>>, OrpcErrorBody<EM>, 'mutation', Awaited<R>>
263
+ export function mutation<R, EM extends ErrorMapOf = {}>(
264
+ fn: (input: undefined, options: ServerFunctionOptions<EM>) => R, options?: FnOptions<EM>,
265
+ ): Endpoint<undefined, Jsonify<Awaited<R>>, OrpcErrorBody<EM>, 'mutation', Awaited<R>>
266
+ /**
267
+ * A stream in a `*.server.ts` module: an async generator, one server-sent event per `yield`, for
268
+ * `connections`. It is a GET, so its input comes from the query string (strings: coerce numbers).
269
+ */
270
+ export function stream<S extends StandardSchemaLike<any, any>, Y, EM extends ErrorMapOf = {}>(
271
+ input: S, fn: (input: SchemaOut<S>, options: ServerFunctionOptions<EM>) => AsyncIterable<Y>, options?: FnOptions<EM>,
272
+ ): Endpoint<SchemaIn<S>, Jsonify<Y>, OrpcErrorBody<EM>, 'stream', Y>
273
+ export function stream<Y, EM extends ErrorMapOf = {}>(
274
+ fn: (input: undefined, options: ServerFunctionOptions<EM>) => AsyncIterable<Y>, options?: FnOptions<EM>,
275
+ ): Endpoint<undefined, Jsonify<Y>, OrpcErrorBody<EM>, 'stream', Y>
276
+
277
+ /**
278
+ * On the server: the oRPC router of the app's `*.server.ts` modules (keys: their paths; the part
279
+ * after `dir/` names them, so `/src/quotes.server.ts` is `quotes`). Mount `router` with oRPC's
280
+ * OpenAPIHandler at the plugin's `api.prefix`, behind `skew(request)`:
281
+ * ```ts
282
+ * const fns = serverFunctions(import.meta.glob('/src/**\/*.server.ts', { eager: true }), { os })
283
+ * ```
284
+ */
285
+ export function serverFunctions(modules: Record<string, unknown>, options: {
286
+ /** oRPC's `os` (from '@orpc/server'): Sygnal has no server of its own */
287
+ os: unknown
288
+ /** The folder the module paths are named from (default 'src', as the plugin's `api.dir`) */
289
+ dir?: string
290
+ /** The header the client stubs send `<file>:<hash>` in (default 'x-api-functions') */
291
+ header?: string
292
+ }): {
293
+ /** oRPC's router: `new OpenAPIHandler(router)` */
294
+ router: any
295
+ /** The contract the stubs are built from (plain data and the schemas) */
296
+ contract: unknown
297
+ /** Each file's contract hash */
298
+ hashes: Record<string, string>
299
+ /** 409 CONTRACT_SKEW for a request from a client built against another version of its file */
300
+ skew(request: Request): Response | undefined
301
+ }
302
+ /** Generated code only (sygnal/vite): a client stub, or a server function given its id */
303
+ export function __serverFunction(id: string, value: unknown, client?: ClientOptions): any
package/src/api.ts ADDED
@@ -0,0 +1,9 @@
1
+ // 'sygnal/api' (dev preview): typed clients for an API contract (oRPC, OpenAPI paths, Hono). The
2
+ // code lives in the main package (src/extra/api/), and this entry re-exports it from the external
3
+ // 'sygnal' (rollup maps './index' to it), as 'sygnal/ai' does: one copy of the diagnostics per app.
4
+ // Keep this list in sync with src/index.ts and src/api.d.ts.
5
+ export {orpcClient, openApiClient, honoClient} from './index'
6
+ export {contractHash, contractSkew, isContractSkew, contractFetch} from './index'
7
+ export {fixture, errorFixture} from './index'
8
+ // function-first: *.server.ts modules (sygnal/vite's api.functions); __serverFunction is for generated code
9
+ export {serverQuery as query, serverMutation as mutation, serverStream as stream, serverFunctions, __serverFunction} from './index'