@lovrozagar/honey 0.1.0 → 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.
Files changed (263) hide show
  1. package/README.md +1596 -6
  2. package/dist/accepts.d.ts +6 -0
  3. package/dist/accepts.d.ts.map +1 -0
  4. package/dist/body-limit.d.ts +22 -0
  5. package/dist/body-limit.d.ts.map +1 -0
  6. package/dist/build/index.d.ts +42 -0
  7. package/dist/build/index.d.ts.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/client/error.d.ts +14 -0
  11. package/dist/client/error.d.ts.map +1 -0
  12. package/dist/client/http.d.ts +88 -0
  13. package/dist/client/http.d.ts.map +1 -0
  14. package/dist/client/index.d.ts +22 -0
  15. package/dist/client/index.d.ts.map +1 -0
  16. package/dist/client/sdk.d.ts +34 -0
  17. package/dist/client/sdk.d.ts.map +1 -0
  18. package/dist/client/sse.d.ts +10 -0
  19. package/dist/client/sse.d.ts.map +1 -0
  20. package/dist/client/types.d.ts +124 -0
  21. package/dist/client/types.d.ts.map +1 -0
  22. package/dist/client/ws.d.ts +15 -0
  23. package/dist/client/ws.d.ts.map +1 -0
  24. package/dist/client-mcp/server.d.ts +10 -0
  25. package/dist/client-mcp/server.d.ts.map +1 -0
  26. package/dist/client-mcp/types.d.ts +16 -0
  27. package/dist/client-mcp/types.d.ts.map +1 -0
  28. package/dist/cloudflare/realtime.d.ts +30 -0
  29. package/dist/cloudflare/realtime.d.ts.map +1 -0
  30. package/dist/codegen-go-cli.d.ts +22 -0
  31. package/dist/codegen-go-cli.d.ts.map +1 -0
  32. package/dist/codegen-go.d.ts +29 -0
  33. package/dist/codegen-go.d.ts.map +1 -0
  34. package/dist/codegen-hash.d.ts +3 -0
  35. package/dist/codegen-hash.d.ts.map +1 -0
  36. package/dist/codegen-ir.d.ts +123 -0
  37. package/dist/codegen-ir.d.ts.map +1 -0
  38. package/dist/codegen-loaders.d.ts +12 -0
  39. package/dist/codegen-loaders.d.ts.map +1 -0
  40. package/dist/codegen-mcp.d.ts +13 -0
  41. package/dist/codegen-mcp.d.ts.map +1 -0
  42. package/dist/codegen-python.d.ts +21 -0
  43. package/dist/codegen-python.d.ts.map +1 -0
  44. package/dist/codegen-rust.d.ts +18 -0
  45. package/dist/codegen-rust.d.ts.map +1 -0
  46. package/dist/codegen-sanitize.d.ts +3 -0
  47. package/dist/codegen-sanitize.d.ts.map +1 -0
  48. package/dist/codegen-schema-naming.d.ts +22 -0
  49. package/dist/codegen-schema-naming.d.ts.map +1 -0
  50. package/dist/codegen.d.ts +178 -0
  51. package/dist/codegen.d.ts.map +1 -0
  52. package/dist/context.d.ts +56 -0
  53. package/dist/context.d.ts.map +1 -0
  54. package/dist/cookie-sign.d.ts +3 -0
  55. package/dist/cookie-sign.d.ts.map +1 -0
  56. package/dist/cookie.d.ts +12 -0
  57. package/dist/cookie.d.ts.map +1 -0
  58. package/dist/cors.d.ts +13 -0
  59. package/dist/cors.d.ts.map +1 -0
  60. package/dist/crypto.d.ts +2 -0
  61. package/dist/crypto.d.ts.map +1 -0
  62. package/dist/csrf.d.ts +9 -0
  63. package/dist/csrf.d.ts.map +1 -0
  64. package/dist/curl-logger.d.ts +33 -0
  65. package/dist/curl-logger.d.ts.map +1 -0
  66. package/dist/detect-runtime.d.ts +16 -0
  67. package/dist/detect-runtime.d.ts.map +1 -0
  68. package/dist/error.d.ts +21 -0
  69. package/dist/error.d.ts.map +1 -0
  70. package/dist/errors.d.ts +40 -0
  71. package/dist/errors.d.ts.map +1 -0
  72. package/dist/etag.d.ts +9 -0
  73. package/dist/etag.d.ts.map +1 -0
  74. package/dist/feature-load.d.ts +3 -0
  75. package/dist/feature-load.d.ts.map +1 -0
  76. package/dist/go-type-emitter.d.ts +33 -0
  77. package/dist/go-type-emitter.d.ts.map +1 -0
  78. package/dist/honey-response.d.ts +82 -0
  79. package/dist/honey-response.d.ts.map +1 -0
  80. package/dist/i18n-slot.d.ts +7 -0
  81. package/dist/i18n-slot.d.ts.map +1 -0
  82. package/dist/i18n.d.ts +26 -0
  83. package/dist/i18n.d.ts.map +1 -0
  84. package/dist/index.d.ts +470 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/init.d.ts +7 -0
  87. package/dist/init.d.ts.map +1 -0
  88. package/dist/input.d.ts +6 -0
  89. package/dist/input.d.ts.map +1 -0
  90. package/dist/ip-restrict.d.ts +12 -0
  91. package/dist/ip-restrict.d.ts.map +1 -0
  92. package/dist/logger.d.ts +45 -0
  93. package/dist/logger.d.ts.map +1 -0
  94. package/dist/meta-spec.d.ts +81 -0
  95. package/dist/meta-spec.d.ts.map +1 -0
  96. package/dist/middleware.d.ts +60 -0
  97. package/dist/middleware.d.ts.map +1 -0
  98. package/dist/node-request.d.ts +59 -0
  99. package/dist/node-request.d.ts.map +1 -0
  100. package/dist/node.d.ts +13 -0
  101. package/dist/node.d.ts.map +1 -0
  102. package/dist/openapi/register.d.ts +3 -0
  103. package/dist/openapi/register.d.ts.map +1 -0
  104. package/dist/openapi/scalar.d.ts +12 -0
  105. package/dist/openapi/scalar.d.ts.map +1 -0
  106. package/dist/openapi/spec-factory.d.ts +31 -0
  107. package/dist/openapi/spec-factory.d.ts.map +1 -0
  108. package/dist/openapi/spec.d.ts +19 -0
  109. package/dist/openapi/spec.d.ts.map +1 -0
  110. package/dist/openapi/swagger.d.ts +12 -0
  111. package/dist/openapi/swagger.d.ts.map +1 -0
  112. package/dist/plugin.d.ts +167 -0
  113. package/dist/plugin.d.ts.map +1 -0
  114. package/dist/powered-by.d.ts +7 -0
  115. package/dist/powered-by.d.ts.map +1 -0
  116. package/dist/pretty-json.d.ts +10 -0
  117. package/dist/pretty-json.d.ts.map +1 -0
  118. package/dist/proxy.d.ts +51 -0
  119. package/dist/proxy.d.ts.map +1 -0
  120. package/dist/python-type-emitter.d.ts +11 -0
  121. package/dist/python-type-emitter.d.ts.map +1 -0
  122. package/dist/realtime/buffer.d.ts +18 -0
  123. package/dist/realtime/buffer.d.ts.map +1 -0
  124. package/dist/realtime/bus.d.ts +11 -0
  125. package/dist/realtime/bus.d.ts.map +1 -0
  126. package/dist/realtime/longpoll.d.ts +23 -0
  127. package/dist/realtime/longpoll.d.ts.map +1 -0
  128. package/dist/realtime/protocol.d.ts +50 -0
  129. package/dist/realtime/protocol.d.ts.map +1 -0
  130. package/dist/realtime/route.d.ts +42 -0
  131. package/dist/realtime/route.d.ts.map +1 -0
  132. package/dist/realtime/runtime.d.ts +74 -0
  133. package/dist/realtime/runtime.d.ts.map +1 -0
  134. package/dist/request-id.d.ts +12 -0
  135. package/dist/request-id.d.ts.map +1 -0
  136. package/dist/request-to-curl.d.ts +9 -0
  137. package/dist/request-to-curl.d.ts.map +1 -0
  138. package/dist/response.d.ts +57 -0
  139. package/dist/response.d.ts.map +1 -0
  140. package/dist/rust-type-emitter.d.ts +32 -0
  141. package/dist/rust-type-emitter.d.ts.map +1 -0
  142. package/dist/secure-headers.d.ts +16 -0
  143. package/dist/secure-headers.d.ts.map +1 -0
  144. package/dist/serve-register.d.ts +2 -0
  145. package/dist/serve-register.d.ts.map +1 -0
  146. package/dist/serve-slot.d.ts +6 -0
  147. package/dist/serve-slot.d.ts.map +1 -0
  148. package/dist/serve.d.ts +21 -0
  149. package/dist/serve.d.ts.map +1 -0
  150. package/dist/server-timing.d.ts +9 -0
  151. package/dist/server-timing.d.ts.map +1 -0
  152. package/dist/static.d.ts +12 -0
  153. package/dist/static.d.ts.map +1 -0
  154. package/dist/telemetry/otel.d.ts +59 -0
  155. package/dist/telemetry/otel.d.ts.map +1 -0
  156. package/dist/testing.d.ts +24 -0
  157. package/dist/testing.d.ts.map +1 -0
  158. package/dist/timeout.d.ts +7 -0
  159. package/dist/timeout.d.ts.map +1 -0
  160. package/dist/tree.d.ts +90 -0
  161. package/dist/tree.d.ts.map +1 -0
  162. package/dist/ts-type-emitter.d.ts +4 -0
  163. package/dist/ts-type-emitter.d.ts.map +1 -0
  164. package/dist/type-emitter.d.ts +8 -0
  165. package/dist/type-emitter.d.ts.map +1 -0
  166. package/dist/type-extractor.d.ts +39 -0
  167. package/dist/type-extractor.d.ts.map +1 -0
  168. package/dist/types.d.ts +451 -0
  169. package/dist/types.d.ts.map +1 -0
  170. package/dist/validation.d.ts +18 -0
  171. package/dist/validation.d.ts.map +1 -0
  172. package/dist/ws/bun.d.ts +28 -0
  173. package/dist/ws/bun.d.ts.map +1 -0
  174. package/dist/ws/cloudflare.d.ts +55 -0
  175. package/dist/ws/cloudflare.d.ts.map +1 -0
  176. package/dist/ws/deno.d.ts +13 -0
  177. package/dist/ws/deno.d.ts.map +1 -0
  178. package/dist/ws/node.d.ts +10 -0
  179. package/dist/ws/node.d.ts.map +1 -0
  180. package/dist/yaml.d.ts +4 -0
  181. package/dist/yaml.d.ts.map +1 -0
  182. package/docs/api-ref/go.md +82 -82
  183. package/docs/api-ref/python.md +82 -82
  184. package/docs/api-ref/rust.md +82 -82
  185. package/docs/api-ref/typescript.md +82 -82
  186. package/docs/invalidate-spec.md +13 -13
  187. package/docs/meta-spec.md +513 -0
  188. package/docs/packaging.md +85 -0
  189. package/docs/sdk.md +87 -73
  190. package/package.json +195 -51
  191. package/src/body-limit.ts +2 -1
  192. package/src/build/index.ts +2 -9
  193. package/src/cli.ts +2 -3
  194. package/src/client/http.ts +204 -223
  195. package/src/client/index.ts +6 -14
  196. package/src/client/sdk.ts +24 -17
  197. package/src/client/types.ts +4 -9
  198. package/src/client/ws.ts +3 -5
  199. package/src/client-mcp/server.ts +1 -4
  200. package/src/cloudflare/realtime.ts +8 -10
  201. package/src/codegen-go-cli.ts +74 -67
  202. package/src/codegen-go.ts +71 -51
  203. package/src/codegen-ir.ts +16 -27
  204. package/src/codegen-loaders.ts +5 -8
  205. package/src/codegen-mcp.ts +9 -27
  206. package/src/codegen-python.ts +47 -27
  207. package/src/codegen-rust.ts +110 -66
  208. package/src/codegen-sanitize.ts +1 -7
  209. package/src/codegen-schema-naming.ts +8 -2
  210. package/src/codegen.ts +299 -196
  211. package/src/context.ts +91 -95
  212. package/src/cookie-sign.ts +5 -13
  213. package/src/cookie.ts +1 -2
  214. package/src/cors.ts +4 -6
  215. package/src/crypto.ts +1 -4
  216. package/src/csrf.ts +3 -3
  217. package/src/curl-logger.ts +14 -32
  218. package/src/detect-runtime.ts +1 -3
  219. package/src/errors.ts +1 -3
  220. package/src/etag.ts +3 -4
  221. package/src/go-type-emitter.ts +45 -40
  222. package/src/honey-response.ts +1 -3
  223. package/src/i18n.ts +3 -12
  224. package/src/index.ts +1168 -1412
  225. package/src/ip-restrict.ts +2 -1
  226. package/src/logger.ts +13 -13
  227. package/src/meta-spec.ts +0 -0
  228. package/src/middleware.ts +111 -79
  229. package/src/node-request.ts +2 -1
  230. package/src/node.ts +9 -10
  231. package/src/openapi/register.ts +1 -2
  232. package/src/openapi/scalar.ts +9 -9
  233. package/src/openapi/spec-factory.ts +2 -2
  234. package/src/openapi/spec.ts +26 -19
  235. package/src/openapi/swagger.ts +9 -9
  236. package/src/plugin.ts +226 -256
  237. package/src/powered-by.ts +2 -1
  238. package/src/pretty-json.ts +2 -1
  239. package/src/proxy.ts +1 -3
  240. package/src/python-type-emitter.ts +37 -12
  241. package/src/realtime/route.ts +1 -1
  242. package/src/realtime/runtime.ts +9 -12
  243. package/src/request-id.ts +3 -4
  244. package/src/request-to-curl.ts +1 -4
  245. package/src/response.ts +150 -199
  246. package/src/rust-type-emitter.ts +66 -25
  247. package/src/secure-headers.ts +2 -1
  248. package/src/serve.ts +3 -12
  249. package/src/server-timing.ts +2 -1
  250. package/src/static.ts +3 -4
  251. package/src/telemetry/otel.ts +1 -6
  252. package/src/testing.ts +2 -11
  253. package/src/timeout.ts +2 -1
  254. package/src/tree.ts +12 -27
  255. package/src/ts-type-emitter.ts +71 -15
  256. package/src/type-emitter.ts +226 -237
  257. package/src/type-extractor.ts +260 -334
  258. package/src/types.ts +168 -68
  259. package/src/validation.ts +7 -30
  260. package/src/ws/bun.ts +2 -9
  261. package/src/ws/cloudflare.ts +13 -16
  262. package/src/ws/deno.ts +31 -40
  263. package/src/ws/node.ts +4 -19
@@ -1,9 +1,9 @@
1
- import type { StandardSchemaLike } from "./types.ts";
1
+ import type { StandardSchemaLike } from "./types.ts"
2
2
 
3
- const SAFE_KEY_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
3
+ const SAFE_KEY_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/
4
4
 
5
5
  function quoteKey(key: string): string {
6
- return SAFE_KEY_RE.test(key) ? key : `"${key}"`;
6
+ return SAFE_KEY_RE.test(key) ? key : `"${key}"`
7
7
  }
8
8
 
9
9
  /** Wrap element type in parens when it contains union/intersection before appending [] */
@@ -17,13 +17,13 @@ function arrayOf(el: string): string {
17
17
  * Unknown vendors return "unknown".
18
18
  */
19
19
  export function emitSchemaType(schema: StandardSchemaLike): string {
20
- const vendor = schema["~standard"].vendor;
21
- if (vendor === "zod") return emitZod(schema);
22
- if (vendor === "valibot") return emitValibot(schema);
23
- if (vendor === "arktype") return emitArkType(schema);
24
- if (vendor === "yup") return emitYup(schema);
25
- if (vendor === "effect") return emitEffect(schema);
26
- return "unknown";
20
+ const vendor = schema["~standard"].vendor
21
+ if (vendor === "zod") return emitZod(schema)
22
+ if (vendor === "valibot") return emitValibot(schema)
23
+ if (vendor === "arktype") return emitArkType(schema)
24
+ if (vendor === "yup") return emitYup(schema)
25
+ if (vendor === "effect") return emitEffect(schema)
26
+ return "unknown"
27
27
  }
28
28
 
29
29
  /* ---- Zod emitter (handles both full zod and zod/mini) ---- */
@@ -32,7 +32,14 @@ export function emitSchemaType(schema: StandardSchemaLike): string {
32
32
  function zodIsOptional(def: Record<string, unknown>): boolean {
33
33
  const t = (def.typeName as string) ?? (def.type as string)
34
34
  if (t === "ZodOptional" || t === "optional") return true
35
- if (t === "ZodNullable" || t === "nullable" || t === "ZodDefault" || t === "default" || t === "ZodCatch" || t === "catch") {
35
+ if (
36
+ t === "ZodNullable" ||
37
+ t === "nullable" ||
38
+ t === "ZodDefault" ||
39
+ t === "default" ||
40
+ t === "ZodCatch" ||
41
+ t === "catch"
42
+ ) {
36
43
  const inner = def.innerType as unknown
37
44
  if (inner) return zodIsOptional(zodDef(inner))
38
45
  }
@@ -40,485 +47,467 @@ function zodIsOptional(def: Record<string, unknown>): boolean {
40
47
  }
41
48
 
42
49
  function zodDef(schema: unknown): Record<string, unknown> {
43
- const s = schema as Record<string, unknown>;
44
- return (s._def ?? s.def) as Record<string, unknown>;
50
+ const s = schema as Record<string, unknown>
51
+ return (s._def ?? s.def) as Record<string, unknown>
45
52
  }
46
53
 
47
54
  function emitZod(schema: unknown): string {
48
- const def = zodDef(schema);
49
- if (!def) return "unknown";
50
- const typeName = (def.typeName ?? def.type) as string;
55
+ const def = zodDef(schema)
56
+ if (!def) return "unknown"
57
+ const typeName = (def.typeName ?? def.type) as string
51
58
 
52
59
  switch (typeName) {
53
60
  case "ZodString":
54
61
  case "string":
55
- return "string";
62
+ return "string"
56
63
  case "ZodNumber":
57
64
  case "number":
58
- return "number";
65
+ return "number"
59
66
  case "ZodBoolean":
60
67
  case "boolean":
61
- return "boolean";
68
+ return "boolean"
62
69
  case "ZodBigInt":
63
70
  case "bigint":
64
- return "bigint";
71
+ return "bigint"
65
72
  case "ZodDate":
66
73
  case "date":
67
- return "Date";
74
+ return "Date"
68
75
  case "ZodUndefined":
69
76
  case "undefined":
70
- return "undefined";
77
+ return "undefined"
71
78
  case "ZodNull":
72
79
  case "null":
73
- return "null";
80
+ return "null"
74
81
  case "ZodVoid":
75
82
  case "void":
76
- return "void";
83
+ return "void"
77
84
  case "ZodAny":
78
85
  case "ZodUnknown":
79
86
  case "any":
80
87
  case "unknown":
81
- return "unknown";
88
+ return "unknown"
82
89
  case "ZodNever":
83
90
  case "never":
84
- return "never";
91
+ return "never"
85
92
  case "ZodLiteral":
86
93
  case "literal": {
87
94
  /* v4: single value, v3: values array */
88
- const val = def.value as unknown;
89
- if (val !== undefined)
90
- return typeof val === "string" ? `"${val}"` : String(val);
91
- const values = def.values as unknown[];
95
+ const val = def.value as unknown
96
+ if (val !== undefined) return typeof val === "string" ? `"${val}"` : String(val)
97
+ const values = def.values as unknown[]
92
98
  if (values.length === 1) {
93
- const v0 = values[0];
94
- return typeof v0 === "string" ? `"${v0}"` : String(v0);
99
+ const v0 = values[0]
100
+ return typeof v0 === "string" ? `"${v0}"` : String(v0)
95
101
  }
96
- return values
97
- .map((v0) => (typeof v0 === "string" ? `"${v0}"` : String(v0)))
98
- .join(" | ");
102
+ return values.map((v0) => (typeof v0 === "string" ? `"${v0}"` : String(v0))).join(" | ")
99
103
  }
100
104
  case "ZodEnum":
101
105
  case "enum": {
102
106
  /* v4: values array, v3/mini: entries record */
103
- const vals = (def.values ?? def.entries) as unknown;
104
- if (Array.isArray(vals)) return vals.map((v0) => `"${v0}"`).join(" | ");
107
+ const vals = (def.values ?? def.entries) as unknown
108
+ if (Array.isArray(vals)) return vals.map((v0) => `"${v0}"`).join(" | ")
105
109
  return Object.values(vals as Record<string, string>)
106
110
  .map((v0) => `"${v0}"`)
107
- .join(" | ");
111
+ .join(" | ")
108
112
  }
109
113
  case "ZodObject":
110
114
  case "object": {
111
- const rawShape = def.shape as
112
- | Record<string, unknown>
113
- | (() => Record<string, unknown>);
114
- const shape = typeof rawShape === "function" ? rawShape() : rawShape;
115
- const keys = Object.keys(shape);
116
- if (keys.length === 0) return "{}";
115
+ const rawShape = def.shape as Record<string, unknown> | (() => Record<string, unknown>)
116
+ const shape = typeof rawShape === "function" ? rawShape() : rawShape
117
+ const keys = Object.keys(shape)
118
+ if (keys.length === 0) return "{}"
117
119
  return `{ ${keys
118
120
  .map((k) => {
119
- const propDef = zodDef(shape[k]);
120
- const isOpt = propDef && zodIsOptional(propDef);
121
- return `${quoteKey(k)}${isOpt ? "?" : ""}: ${emitZod(shape[k])}`;
121
+ const propDef = zodDef(shape[k])
122
+ const isOpt = propDef && zodIsOptional(propDef)
123
+ return `${quoteKey(k)}${isOpt ? "?" : ""}: ${emitZod(shape[k])}`
122
124
  })
123
- .join("; ")} }`;
125
+ .join("; ")} }`
124
126
  }
125
127
  case "ZodArray":
126
128
  /* v4: _def.type is the element schema */
127
- return arrayOf(emitZod((def.type ?? def.element) as unknown));
129
+ return arrayOf(emitZod((def.type ?? def.element) as unknown))
128
130
  case "array":
129
- return arrayOf(emitZod(def.element as unknown));
131
+ return arrayOf(emitZod(def.element as unknown))
130
132
  case "ZodOptional":
131
133
  case "optional":
132
- return `${emitZod(def.innerType as unknown)} | undefined`;
134
+ return `${emitZod(def.innerType as unknown)} | undefined`
133
135
  case "ZodNullable":
134
136
  case "nullable":
135
- return `${emitZod(def.innerType as unknown)} | null`;
137
+ return `${emitZod(def.innerType as unknown)} | null`
136
138
  case "ZodUnion":
137
139
  case "ZodDiscriminatedUnion":
138
140
  case "union":
139
- return (def.options as unknown[]).map((o) => emitZod(o)).join(" | ");
141
+ return (def.options as unknown[]).map((o) => emitZod(o)).join(" | ")
140
142
  case "ZodIntersection":
141
143
  case "intersection":
142
- return `${emitZod(def.left as unknown)} & ${emitZod(def.right as unknown)}`;
144
+ return `${emitZod(def.left as unknown)} & ${emitZod(def.right as unknown)}`
143
145
  case "ZodRecord":
144
146
  case "record":
145
- return `Partial<Record<${emitZod(def.keyType as unknown)}, ${emitZod(def.valueType as unknown)}>>`;
147
+ return `Partial<Record<${emitZod(def.keyType as unknown)}, ${emitZod(def.valueType as unknown)}>>`
146
148
  case "ZodTuple":
147
149
  case "tuple":
148
- return `[${(def.items as unknown[]).map((i) => emitZod(i)).join(", ")}]`;
150
+ return `[${(def.items as unknown[]).map((i) => emitZod(i)).join(", ")}]`
149
151
  case "ZodDefault":
150
152
  case "ZodCatch":
151
153
  case "default":
152
154
  case "catch":
153
- return emitZod(def.innerType as unknown);
155
+ return emitZod(def.innerType as unknown)
154
156
  case "ZodReadonly":
155
157
  case "readonly":
156
- return `Readonly<${emitZod(def.innerType as unknown)}>`;
158
+ return `Readonly<${emitZod(def.innerType as unknown)}>`
157
159
  case "ZodPipeline":
158
160
  case "pipe":
159
- return emitZod(def.out as unknown);
161
+ return emitZod(def.out as unknown)
160
162
  case "ZodBranded":
161
- return emitZod(def.type as unknown);
163
+ return emitZod(def.type as unknown)
162
164
  case "ZodLazy":
163
165
  case "lazy":
164
- return "unknown";
166
+ return "unknown"
165
167
  default:
166
- return "unknown";
168
+ return "unknown"
167
169
  }
168
170
  }
169
171
 
170
172
  /* ---- Valibot emitter ---- */
171
173
 
172
174
  function emitValibot(schema: unknown): string {
173
- const s = schema as Record<string, unknown>;
174
- const type = s.type as string | undefined;
175
- if (!type) return "unknown";
175
+ const s = schema as Record<string, unknown>
176
+ const type = s.type as string | undefined
177
+ if (!type) return "unknown"
176
178
 
177
179
  switch (type) {
178
180
  case "string":
179
- return "string";
181
+ return "string"
180
182
  case "number":
181
- return "number";
183
+ return "number"
182
184
  case "boolean":
183
- return "boolean";
185
+ return "boolean"
184
186
  case "bigint":
185
- return "bigint";
187
+ return "bigint"
186
188
  case "date":
187
- return "Date";
189
+ return "Date"
188
190
  case "undefined":
189
- return "undefined";
191
+ return "undefined"
190
192
  case "null":
191
- return "null";
193
+ return "null"
192
194
  case "void":
193
- return "void";
195
+ return "void"
194
196
  case "any":
195
197
  case "unknown":
196
- return "unknown";
198
+ return "unknown"
197
199
  case "never":
198
- return "never";
200
+ return "never"
199
201
  case "literal": {
200
- const val = s.literal as unknown;
201
- return typeof val === "string" ? `"${val}"` : String(val);
202
+ const val = s.literal as unknown
203
+ return typeof val === "string" ? `"${val}"` : String(val)
202
204
  }
203
205
  case "enum": {
204
- const enumObj = s.enum as Record<string, string>;
206
+ const enumObj = s.enum as Record<string, string>
205
207
  return Object.values(enumObj)
206
208
  .map((val) => `"${val}"`)
207
- .join(" | ");
209
+ .join(" | ")
208
210
  }
209
211
  case "picklist": {
210
- const options = s.options as unknown[];
211
- return options
212
- .map((val) => (typeof val === "string" ? `"${val}"` : String(val)))
213
- .join(" | ");
212
+ const options = s.options as unknown[]
213
+ return options.map((val) => (typeof val === "string" ? `"${val}"` : String(val))).join(" | ")
214
214
  }
215
215
  case "object": {
216
- const entries = s.entries as Record<string, unknown>;
217
- const keys = Object.keys(entries);
218
- if (keys.length === 0) return "{}";
216
+ const entries = s.entries as Record<string, unknown>
217
+ const keys = Object.keys(entries)
218
+ if (keys.length === 0) return "{}"
219
219
  return `{ ${keys
220
220
  .map((k) => {
221
- const propType = (entries[k] as Record<string, unknown>).type as
222
- | string
223
- | undefined;
224
- const isOpt = propType === "optional" || propType === "nullish";
225
- return `${quoteKey(k)}${isOpt ? "?" : ""}: ${emitValibot(entries[k])}`;
221
+ const propType = (entries[k] as Record<string, unknown>).type as string | undefined
222
+ const isOpt = propType === "optional" || propType === "nullish"
223
+ return `${quoteKey(k)}${isOpt ? "?" : ""}: ${emitValibot(entries[k])}`
226
224
  })
227
- .join("; ")} }`;
225
+ .join("; ")} }`
228
226
  }
229
227
  case "array":
230
- return arrayOf(emitValibot(s.item as unknown));
228
+ return arrayOf(emitValibot(s.item as unknown))
231
229
  case "optional":
232
- return `${emitValibot(s.wrapped as unknown)} | undefined`;
230
+ return `${emitValibot(s.wrapped as unknown)} | undefined`
233
231
  case "nullable":
234
- return `${emitValibot(s.wrapped as unknown)} | null`;
232
+ return `${emitValibot(s.wrapped as unknown)} | null`
235
233
  case "nullish":
236
- return `${emitValibot(s.wrapped as unknown)} | null | undefined`;
234
+ return `${emitValibot(s.wrapped as unknown)} | null | undefined`
237
235
  case "union":
238
- return (s.options as unknown[]).map((o) => emitValibot(o)).join(" | ");
236
+ return (s.options as unknown[]).map((o) => emitValibot(o)).join(" | ")
239
237
  case "intersect":
240
- return (s.options as unknown[]).map((o) => emitValibot(o)).join(" & ");
238
+ return (s.options as unknown[]).map((o) => emitValibot(o)).join(" & ")
241
239
  case "record":
242
- return `Record<${emitValibot(s.key as unknown)}, ${emitValibot(s.value as unknown)}>`;
240
+ return `Record<${emitValibot(s.key as unknown)}, ${emitValibot(s.value as unknown)}>`
243
241
  case "tuple":
244
- return `[${(s.items as unknown[]).map((i) => emitValibot(i)).join(", ")}]`;
242
+ return `[${(s.items as unknown[]).map((i) => emitValibot(i)).join(", ")}]`
245
243
  default:
246
- return "unknown";
244
+ return "unknown"
247
245
  }
248
246
  }
249
247
 
250
248
  /* ---- ArkType emitter ---- */
251
249
 
252
250
  function emitArkType(schema: unknown): string {
253
- const s = schema as Record<string, unknown>;
254
- const json = s.json as unknown;
255
- if (json === undefined || json === null) return "unknown";
256
- return emitArkJson(json);
251
+ const s = schema as Record<string, unknown>
252
+ const json = s.json as unknown
253
+ if (json === undefined || json === null) return "unknown"
254
+ return emitArkJson(json)
257
255
  }
258
256
 
259
- type ArkEntry = { key: string; value: unknown };
257
+ type ArkEntry = { key: string; value: unknown }
260
258
 
261
259
  function isBooleanUnion(node: unknown[]): boolean {
262
- if (node.length !== 2) return false;
260
+ if (node.length !== 2) return false
263
261
  const units = node.map((n) => {
264
262
  if (typeof n === "object" && n !== null && "unit" in n) {
265
- return (n as Record<string, unknown>).unit;
263
+ return (n as Record<string, unknown>).unit
266
264
  }
267
- return undefined;
268
- });
269
- return (
270
- (units[0] === false && units[1] === true) ||
271
- (units[0] === true && units[1] === false)
272
- );
265
+ return undefined
266
+ })
267
+ return (units[0] === false && units[1] === true) || (units[0] === true && units[1] === false)
273
268
  }
274
269
 
275
270
  function emitArkJson(node: unknown): string {
276
- if (typeof node === "string") return mapArkDomain(node);
271
+ if (typeof node === "string") return mapArkDomain(node)
277
272
 
278
273
  if (Array.isArray(node)) {
279
- if (node.length === 0) return "never";
280
- if (isBooleanUnion(node)) return "boolean";
281
- return node.map((n) => emitArkJson(n)).join(" | ");
274
+ if (node.length === 0) return "never"
275
+ if (isBooleanUnion(node)) return "boolean"
276
+ return node.map((n) => emitArkJson(n)).join(" | ")
282
277
  }
283
278
 
284
- const obj = node as Record<string, unknown>;
279
+ const obj = node as Record<string, unknown>
285
280
 
286
281
  if ("unit" in obj) {
287
- const val = obj.unit;
288
- if (val === null) return "null";
282
+ const val = obj.unit
283
+ if (val === null) return "null"
289
284
  /* arktype serializes undefined as the string "undefined" in JSON */
290
- if (val === "undefined") return "undefined";
291
- return typeof val === "string" ? `"${val}"` : String(val);
285
+ if (val === "undefined") return "undefined"
286
+ return typeof val === "string" ? `"${val}"` : String(val)
292
287
  }
293
288
 
294
289
  if ("sequence" in obj) {
295
- return arrayOf(emitArkJson(obj.sequence));
290
+ return arrayOf(emitArkJson(obj.sequence))
296
291
  }
297
292
 
298
293
  if ("proto" in obj) {
299
- return mapArkProto(obj.proto as string);
294
+ return mapArkProto(obj.proto as string)
300
295
  }
301
296
 
302
297
  if ("domain" in obj) {
303
- const domain = obj.domain as string;
298
+ const domain = obj.domain as string
304
299
 
305
300
  if (domain === "object") {
306
- const required = (obj.required as ArkEntry[] | undefined) ?? [];
307
- const optional = (obj.optional as ArkEntry[] | undefined) ?? [];
308
- if (required.length === 0 && optional.length === 0) return "{}";
309
- const parts: string[] = [];
301
+ const required = (obj.required as ArkEntry[] | undefined) ?? []
302
+ const optional = (obj.optional as ArkEntry[] | undefined) ?? []
303
+ if (required.length === 0 && optional.length === 0) return "{}"
304
+ const parts: string[] = []
310
305
  for (const entry of required) {
311
- parts.push(
312
- `${quoteKey(String(entry.key))}: ${emitArkJson(entry.value)}`,
313
- );
306
+ parts.push(`${quoteKey(String(entry.key))}: ${emitArkJson(entry.value)}`)
314
307
  }
315
308
  for (const entry of optional) {
316
- parts.push(
317
- `${quoteKey(String(entry.key))}?: ${emitArkJson(entry.value)}`,
318
- );
309
+ parts.push(`${quoteKey(String(entry.key))}?: ${emitArkJson(entry.value)}`)
319
310
  }
320
- return `{ ${parts.join("; ")} }`;
311
+ return `{ ${parts.join("; ")} }`
321
312
  }
322
313
 
323
- return mapArkDomain(domain);
314
+ return mapArkDomain(domain)
324
315
  }
325
316
 
326
- return "unknown";
317
+ return "unknown"
327
318
  }
328
319
 
329
320
  function mapArkDomain(domain: string): string {
330
321
  switch (domain) {
331
322
  case "string":
332
- return "string";
323
+ return "string"
333
324
  case "number":
334
325
  case "integer":
335
- return "number";
326
+ return "number"
336
327
  case "boolean":
337
- return "boolean";
328
+ return "boolean"
338
329
  case "bigint":
339
- return "bigint";
330
+ return "bigint"
340
331
  case "symbol":
341
- return "symbol";
332
+ return "symbol"
342
333
  case "undefined":
343
- return "undefined";
334
+ return "undefined"
344
335
  case "null":
345
- return "null";
336
+ return "null"
346
337
  case "object":
347
- return "object";
338
+ return "object"
348
339
  default:
349
- return "unknown";
340
+ return "unknown"
350
341
  }
351
342
  }
352
343
 
353
344
  function mapArkProto(proto: string): string {
354
345
  switch (proto) {
355
346
  case "Date":
356
- return "Date";
347
+ return "Date"
357
348
  case "Array":
358
- return "unknown[]";
349
+ return "unknown[]"
359
350
  case "RegExp":
360
- return "RegExp";
351
+ return "RegExp"
361
352
  case "Map":
362
- return "Map<unknown, unknown>";
353
+ return "Map<unknown, unknown>"
363
354
  case "Set":
364
- return "Set<unknown>";
355
+ return "Set<unknown>"
365
356
  default:
366
- return "unknown";
357
+ return "unknown"
367
358
  }
368
359
  }
369
360
 
370
361
  /* ---- Yup emitter ---- */
371
362
 
372
363
  type YupDesc = {
373
- fields?: Record<string, YupDesc>;
374
- innerType?: YupDesc | YupDesc[];
375
- nullable?: boolean;
376
- oneOf?: unknown[];
377
- optional?: boolean;
378
- type: string;
379
- };
364
+ fields?: Record<string, YupDesc>
365
+ innerType?: YupDesc | YupDesc[]
366
+ nullable?: boolean
367
+ oneOf?: unknown[]
368
+ optional?: boolean
369
+ type: string
370
+ }
380
371
 
381
372
  function emitYup(schema: unknown): string {
382
- const s = schema as Record<string, unknown>;
383
- if (typeof s.describe !== "function") return "unknown";
384
- const desc = s.describe() as YupDesc;
385
- return emitYupDesc(desc);
373
+ const s = schema as Record<string, unknown>
374
+ if (typeof s.describe !== "function") return "unknown"
375
+ const desc = s.describe() as YupDesc
376
+ return emitYupDesc(desc)
386
377
  }
387
378
 
388
379
  function emitYupDesc(desc: YupDesc): string {
389
- let base = emitYupBase(desc);
390
- if (desc.nullable) base = `${base} | null`;
391
- return base;
380
+ let base = emitYupBase(desc)
381
+ if (desc.nullable) base = `${base} | null`
382
+ return base
392
383
  }
393
384
 
394
385
  function emitYupBase(desc: YupDesc): string {
395
386
  switch (desc.type) {
396
387
  case "string":
397
- return "string";
388
+ return "string"
398
389
  case "number":
399
- return "number";
390
+ return "number"
400
391
  case "boolean":
401
- return "boolean";
392
+ return "boolean"
402
393
  case "date":
403
- return "Date";
394
+ return "Date"
404
395
  case "object": {
405
- if (!desc.fields) return "{}";
406
- const keys = Object.keys(desc.fields);
407
- if (keys.length === 0) return "{}";
396
+ if (!desc.fields) return "{}"
397
+ const keys = Object.keys(desc.fields)
398
+ if (keys.length === 0) return "{}"
408
399
  const parts = keys.map((k) => {
409
- const field = desc.fields?.[k];
410
- if (!field) return `${quoteKey(k)}: unknown`;
411
- const opt = field.optional ? "?" : "";
412
- return `${quoteKey(k)}${opt}: ${emitYupDesc(field)}`;
413
- });
414
- return `{ ${parts.join("; ")} }`;
400
+ const field = desc.fields?.[k]
401
+ if (!field) return `${quoteKey(k)}: unknown`
402
+ const opt = field.optional ? "?" : ""
403
+ return `${quoteKey(k)}${opt}: ${emitYupDesc(field)}`
404
+ })
405
+ return `{ ${parts.join("; ")} }`
415
406
  }
416
407
  case "array": {
417
- if (!desc.innerType || Array.isArray(desc.innerType)) return "unknown[]";
418
- return arrayOf(emitYupDesc(desc.innerType));
408
+ if (!desc.innerType || Array.isArray(desc.innerType)) return "unknown[]"
409
+ return arrayOf(emitYupDesc(desc.innerType))
419
410
  }
420
411
  case "tuple": {
421
- if (!Array.isArray(desc.innerType)) return "unknown";
422
- return `[${desc.innerType.map((i) => emitYupDesc(i)).join(", ")}]`;
412
+ if (!Array.isArray(desc.innerType)) return "unknown"
413
+ return `[${desc.innerType.map((i) => emitYupDesc(i)).join(", ")}]`
423
414
  }
424
415
  case "mixed": {
425
416
  if (desc.oneOf && desc.oneOf.length > 0) {
426
- return desc.oneOf
427
- .map((val) => (typeof val === "string" ? `"${val}"` : String(val)))
428
- .join(" | ");
417
+ return desc.oneOf.map((val) => (typeof val === "string" ? `"${val}"` : String(val))).join(" | ")
429
418
  }
430
- return "unknown";
419
+ return "unknown"
431
420
  }
432
421
  case "lazy":
433
- return "unknown";
422
+ return "unknown"
434
423
  default:
435
- return "unknown";
424
+ return "unknown"
436
425
  }
437
426
  }
438
427
 
439
428
  /* ---- Effect Schema emitter ---- */
440
429
 
441
430
  type EffectAST = {
442
- _tag: string;
443
- elements?: Array<{ isOptional: boolean; type: EffectAST }>;
444
- indexSignatures?: Array<{ parameter: EffectAST; type: EffectAST }>;
445
- literal?: unknown;
431
+ _tag: string
432
+ elements?: Array<{ isOptional: boolean; type: EffectAST }>
433
+ indexSignatures?: Array<{ parameter: EffectAST; type: EffectAST }>
434
+ literal?: unknown
446
435
  propertySignatures?: Array<{
447
- isOptional: boolean;
448
- name: string;
449
- type: EffectAST;
450
- }>;
451
- rest?: Array<{ type: EffectAST }>;
452
- types?: EffectAST[];
453
- };
436
+ isOptional: boolean
437
+ name: string
438
+ type: EffectAST
439
+ }>
440
+ rest?: Array<{ type: EffectAST }>
441
+ types?: EffectAST[]
442
+ }
454
443
 
455
444
  function emitEffect(schema: unknown): string {
456
- const s = schema as Record<string, unknown>;
457
- const ast = s.ast as EffectAST | undefined;
458
- if (!ast) return "unknown";
459
- return emitEffectAst(ast);
445
+ const s = schema as Record<string, unknown>
446
+ const ast = s.ast as EffectAST | undefined
447
+ if (!ast) return "unknown"
448
+ return emitEffectAst(ast)
460
449
  }
461
450
 
462
451
  function emitEffectAst(ast: EffectAST): string {
463
452
  switch (ast._tag) {
464
453
  case "StringKeyword":
465
- return "string";
454
+ return "string"
466
455
  case "NumberKeyword":
467
- return "number";
456
+ return "number"
468
457
  case "BooleanKeyword":
469
- return "boolean";
458
+ return "boolean"
470
459
  case "BigIntKeyword":
471
- return "bigint";
460
+ return "bigint"
472
461
  case "SymbolKeyword":
473
- return "symbol";
462
+ return "symbol"
474
463
  case "UndefinedKeyword":
475
- return "undefined";
464
+ return "undefined"
476
465
  case "VoidKeyword":
477
- return "void";
466
+ return "void"
478
467
  case "UnknownKeyword":
479
468
  case "AnyKeyword":
480
- return "unknown";
469
+ return "unknown"
481
470
  case "NeverKeyword":
482
- return "never";
471
+ return "never"
483
472
  case "ObjectKeyword":
484
- return "object";
473
+ return "object"
485
474
  case "Literal": {
486
- const val = ast.literal;
487
- if (val === null) return "null";
488
- return typeof val === "string" ? `"${val}"` : String(val);
475
+ const val = ast.literal
476
+ if (val === null) return "null"
477
+ return typeof val === "string" ? `"${val}"` : String(val)
489
478
  }
490
479
  case "Union":
491
- return (ast.types ?? []).map((t) => emitEffectAst(t)).join(" | ");
480
+ return (ast.types ?? []).map((t) => emitEffectAst(t)).join(" | ")
492
481
  case "TypeLiteral": {
493
- const props = ast.propertySignatures ?? [];
494
- const idxSigs = ast.indexSignatures ?? [];
495
- if (props.length === 0 && idxSigs.length === 0) return "{}";
482
+ const props = ast.propertySignatures ?? []
483
+ const idxSigs = ast.indexSignatures ?? []
484
+ if (props.length === 0 && idxSigs.length === 0) return "{}"
496
485
  if (props.length === 0 && idxSigs.length === 1) {
497
- return `Record<${emitEffectAst(idxSigs[0].parameter)}, ${emitEffectAst(idxSigs[0].type)}>`;
486
+ return `Record<${emitEffectAst(idxSigs[0].parameter)}, ${emitEffectAst(idxSigs[0].type)}>`
498
487
  }
499
488
  const parts = props.map((p) => {
500
- const opt = p.isOptional ? "?" : "";
501
- return `${quoteKey(p.name as string)}${opt}: ${emitEffectAst(p.type)}`;
502
- });
503
- return `{ ${parts.join("; ")} }`;
489
+ const opt = p.isOptional ? "?" : ""
490
+ return `${quoteKey(p.name as string)}${opt}: ${emitEffectAst(p.type)}`
491
+ })
492
+ return `{ ${parts.join("; ")} }`
504
493
  }
505
494
  case "TupleType": {
506
- const elems = ast.elements ?? [];
507
- const rest = ast.rest;
495
+ const elems = ast.elements ?? []
496
+ const rest = ast.rest
508
497
  if (elems.length === 0 && rest && rest.length === 1) {
509
- return arrayOf(emitEffectAst(rest[0].type));
498
+ return arrayOf(emitEffectAst(rest[0].type))
510
499
  }
511
500
  if (elems.length > 0 && (!rest || rest.length === 0)) {
512
- return `[${elems.map((e) => emitEffectAst(e.type)).join(", ")}]`;
501
+ return `[${elems.map((e) => emitEffectAst(e.type)).join(", ")}]`
513
502
  }
514
- if (elems.length === 0) return "unknown[]";
515
- return `[${elems.map((e) => emitEffectAst(e.type)).join(", ")}]`;
503
+ if (elems.length === 0) return "unknown[]"
504
+ return `[${elems.map((e) => emitEffectAst(e.type)).join(", ")}]`
516
505
  }
517
506
  case "Declaration":
518
- return "unknown";
507
+ return "unknown"
519
508
  case "Suspend":
520
- return "unknown";
509
+ return "unknown"
521
510
  default:
522
- return "unknown";
511
+ return "unknown"
523
512
  }
524
513
  }