@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.
- package/README.md +1596 -6
- package/dist/accepts.d.ts +6 -0
- package/dist/accepts.d.ts.map +1 -0
- package/dist/body-limit.d.ts +22 -0
- package/dist/body-limit.d.ts.map +1 -0
- package/dist/build/index.d.ts +42 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/client/error.d.ts +14 -0
- package/dist/client/error.d.ts.map +1 -0
- package/dist/client/http.d.ts +88 -0
- package/dist/client/http.d.ts.map +1 -0
- package/dist/client/index.d.ts +22 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/sdk.d.ts +34 -0
- package/dist/client/sdk.d.ts.map +1 -0
- package/dist/client/sse.d.ts +10 -0
- package/dist/client/sse.d.ts.map +1 -0
- package/dist/client/types.d.ts +124 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/ws.d.ts +15 -0
- package/dist/client/ws.d.ts.map +1 -0
- package/dist/client-mcp/server.d.ts +10 -0
- package/dist/client-mcp/server.d.ts.map +1 -0
- package/dist/client-mcp/types.d.ts +16 -0
- package/dist/client-mcp/types.d.ts.map +1 -0
- package/dist/cloudflare/realtime.d.ts +30 -0
- package/dist/cloudflare/realtime.d.ts.map +1 -0
- package/dist/codegen-go-cli.d.ts +22 -0
- package/dist/codegen-go-cli.d.ts.map +1 -0
- package/dist/codegen-go.d.ts +29 -0
- package/dist/codegen-go.d.ts.map +1 -0
- package/dist/codegen-hash.d.ts +3 -0
- package/dist/codegen-hash.d.ts.map +1 -0
- package/dist/codegen-ir.d.ts +123 -0
- package/dist/codegen-ir.d.ts.map +1 -0
- package/dist/codegen-loaders.d.ts +12 -0
- package/dist/codegen-loaders.d.ts.map +1 -0
- package/dist/codegen-mcp.d.ts +13 -0
- package/dist/codegen-mcp.d.ts.map +1 -0
- package/dist/codegen-python.d.ts +21 -0
- package/dist/codegen-python.d.ts.map +1 -0
- package/dist/codegen-rust.d.ts +18 -0
- package/dist/codegen-rust.d.ts.map +1 -0
- package/dist/codegen-sanitize.d.ts +3 -0
- package/dist/codegen-sanitize.d.ts.map +1 -0
- package/dist/codegen-schema-naming.d.ts +22 -0
- package/dist/codegen-schema-naming.d.ts.map +1 -0
- package/dist/codegen.d.ts +178 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/context.d.ts +56 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/cookie-sign.d.ts +3 -0
- package/dist/cookie-sign.d.ts.map +1 -0
- package/dist/cookie.d.ts +12 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cors.d.ts +13 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/crypto.d.ts +2 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/csrf.d.ts +9 -0
- package/dist/csrf.d.ts.map +1 -0
- package/dist/curl-logger.d.ts +33 -0
- package/dist/curl-logger.d.ts.map +1 -0
- package/dist/detect-runtime.d.ts +16 -0
- package/dist/detect-runtime.d.ts.map +1 -0
- package/dist/error.d.ts +21 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/etag.d.ts +9 -0
- package/dist/etag.d.ts.map +1 -0
- package/dist/feature-load.d.ts +3 -0
- package/dist/feature-load.d.ts.map +1 -0
- package/dist/go-type-emitter.d.ts +33 -0
- package/dist/go-type-emitter.d.ts.map +1 -0
- package/dist/honey-response.d.ts +82 -0
- package/dist/honey-response.d.ts.map +1 -0
- package/dist/i18n-slot.d.ts +7 -0
- package/dist/i18n-slot.d.ts.map +1 -0
- package/dist/i18n.d.ts +26 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/index.d.ts +470 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/init.d.ts +7 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/input.d.ts +6 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/ip-restrict.d.ts +12 -0
- package/dist/ip-restrict.d.ts.map +1 -0
- package/dist/logger.d.ts +45 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/meta-spec.d.ts +81 -0
- package/dist/meta-spec.d.ts.map +1 -0
- package/dist/middleware.d.ts +60 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/node-request.d.ts +59 -0
- package/dist/node-request.d.ts.map +1 -0
- package/dist/node.d.ts +13 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/openapi/register.d.ts +3 -0
- package/dist/openapi/register.d.ts.map +1 -0
- package/dist/openapi/scalar.d.ts +12 -0
- package/dist/openapi/scalar.d.ts.map +1 -0
- package/dist/openapi/spec-factory.d.ts +31 -0
- package/dist/openapi/spec-factory.d.ts.map +1 -0
- package/dist/openapi/spec.d.ts +19 -0
- package/dist/openapi/spec.d.ts.map +1 -0
- package/dist/openapi/swagger.d.ts +12 -0
- package/dist/openapi/swagger.d.ts.map +1 -0
- package/dist/plugin.d.ts +167 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/powered-by.d.ts +7 -0
- package/dist/powered-by.d.ts.map +1 -0
- package/dist/pretty-json.d.ts +10 -0
- package/dist/pretty-json.d.ts.map +1 -0
- package/dist/proxy.d.ts +51 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/python-type-emitter.d.ts +11 -0
- package/dist/python-type-emitter.d.ts.map +1 -0
- package/dist/realtime/buffer.d.ts +18 -0
- package/dist/realtime/buffer.d.ts.map +1 -0
- package/dist/realtime/bus.d.ts +11 -0
- package/dist/realtime/bus.d.ts.map +1 -0
- package/dist/realtime/longpoll.d.ts +23 -0
- package/dist/realtime/longpoll.d.ts.map +1 -0
- package/dist/realtime/protocol.d.ts +50 -0
- package/dist/realtime/protocol.d.ts.map +1 -0
- package/dist/realtime/route.d.ts +42 -0
- package/dist/realtime/route.d.ts.map +1 -0
- package/dist/realtime/runtime.d.ts +74 -0
- package/dist/realtime/runtime.d.ts.map +1 -0
- package/dist/request-id.d.ts +12 -0
- package/dist/request-id.d.ts.map +1 -0
- package/dist/request-to-curl.d.ts +9 -0
- package/dist/request-to-curl.d.ts.map +1 -0
- package/dist/response.d.ts +57 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/rust-type-emitter.d.ts +32 -0
- package/dist/rust-type-emitter.d.ts.map +1 -0
- package/dist/secure-headers.d.ts +16 -0
- package/dist/secure-headers.d.ts.map +1 -0
- package/dist/serve-register.d.ts +2 -0
- package/dist/serve-register.d.ts.map +1 -0
- package/dist/serve-slot.d.ts +6 -0
- package/dist/serve-slot.d.ts.map +1 -0
- package/dist/serve.d.ts +21 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/server-timing.d.ts +9 -0
- package/dist/server-timing.d.ts.map +1 -0
- package/dist/static.d.ts +12 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/telemetry/otel.d.ts +59 -0
- package/dist/telemetry/otel.d.ts.map +1 -0
- package/dist/testing.d.ts +24 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/timeout.d.ts +7 -0
- package/dist/timeout.d.ts.map +1 -0
- package/dist/tree.d.ts +90 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/ts-type-emitter.d.ts +4 -0
- package/dist/ts-type-emitter.d.ts.map +1 -0
- package/dist/type-emitter.d.ts +8 -0
- package/dist/type-emitter.d.ts.map +1 -0
- package/dist/type-extractor.d.ts +39 -0
- package/dist/type-extractor.d.ts.map +1 -0
- package/dist/types.d.ts +451 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/validation.d.ts +18 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/ws/bun.d.ts +28 -0
- package/dist/ws/bun.d.ts.map +1 -0
- package/dist/ws/cloudflare.d.ts +55 -0
- package/dist/ws/cloudflare.d.ts.map +1 -0
- package/dist/ws/deno.d.ts +13 -0
- package/dist/ws/deno.d.ts.map +1 -0
- package/dist/ws/node.d.ts +10 -0
- package/dist/ws/node.d.ts.map +1 -0
- package/dist/yaml.d.ts +4 -0
- package/dist/yaml.d.ts.map +1 -0
- package/docs/api-ref/go.md +82 -82
- package/docs/api-ref/python.md +82 -82
- package/docs/api-ref/rust.md +82 -82
- package/docs/api-ref/typescript.md +82 -82
- package/docs/invalidate-spec.md +13 -13
- package/docs/meta-spec.md +513 -0
- package/docs/packaging.md +85 -0
- package/docs/sdk.md +87 -73
- package/package.json +195 -51
- package/src/body-limit.ts +2 -1
- package/src/build/index.ts +2 -9
- package/src/cli.ts +2 -3
- package/src/client/http.ts +204 -223
- package/src/client/index.ts +6 -14
- package/src/client/sdk.ts +24 -17
- package/src/client/types.ts +4 -9
- package/src/client/ws.ts +3 -5
- package/src/client-mcp/server.ts +1 -4
- package/src/cloudflare/realtime.ts +8 -10
- package/src/codegen-go-cli.ts +74 -67
- package/src/codegen-go.ts +71 -51
- package/src/codegen-ir.ts +16 -27
- package/src/codegen-loaders.ts +5 -8
- package/src/codegen-mcp.ts +9 -27
- package/src/codegen-python.ts +47 -27
- package/src/codegen-rust.ts +110 -66
- package/src/codegen-sanitize.ts +1 -7
- package/src/codegen-schema-naming.ts +8 -2
- package/src/codegen.ts +299 -196
- package/src/context.ts +91 -95
- package/src/cookie-sign.ts +5 -13
- package/src/cookie.ts +1 -2
- package/src/cors.ts +4 -6
- package/src/crypto.ts +1 -4
- package/src/csrf.ts +3 -3
- package/src/curl-logger.ts +14 -32
- package/src/detect-runtime.ts +1 -3
- package/src/errors.ts +1 -3
- package/src/etag.ts +3 -4
- package/src/go-type-emitter.ts +45 -40
- package/src/honey-response.ts +1 -3
- package/src/i18n.ts +3 -12
- package/src/index.ts +1168 -1412
- package/src/ip-restrict.ts +2 -1
- package/src/logger.ts +13 -13
- package/src/meta-spec.ts +0 -0
- package/src/middleware.ts +111 -79
- package/src/node-request.ts +2 -1
- package/src/node.ts +9 -10
- package/src/openapi/register.ts +1 -2
- package/src/openapi/scalar.ts +9 -9
- package/src/openapi/spec-factory.ts +2 -2
- package/src/openapi/spec.ts +26 -19
- package/src/openapi/swagger.ts +9 -9
- package/src/plugin.ts +226 -256
- package/src/powered-by.ts +2 -1
- package/src/pretty-json.ts +2 -1
- package/src/proxy.ts +1 -3
- package/src/python-type-emitter.ts +37 -12
- package/src/realtime/route.ts +1 -1
- package/src/realtime/runtime.ts +9 -12
- package/src/request-id.ts +3 -4
- package/src/request-to-curl.ts +1 -4
- package/src/response.ts +150 -199
- package/src/rust-type-emitter.ts +66 -25
- package/src/secure-headers.ts +2 -1
- package/src/serve.ts +3 -12
- package/src/server-timing.ts +2 -1
- package/src/static.ts +3 -4
- package/src/telemetry/otel.ts +1 -6
- package/src/testing.ts +2 -11
- package/src/timeout.ts +2 -1
- package/src/tree.ts +12 -27
- package/src/ts-type-emitter.ts +71 -15
- package/src/type-emitter.ts +226 -237
- package/src/type-extractor.ts +260 -334
- package/src/types.ts +168 -68
- package/src/validation.ts +7 -30
- package/src/ws/bun.ts +2 -9
- package/src/ws/cloudflare.ts +13 -16
- package/src/ws/deno.ts +31 -40
- package/src/ws/node.ts +4 -19
package/src/client/index.ts
CHANGED
|
@@ -30,9 +30,7 @@ export { createTypedWebSocket } from "./ws.ts"
|
|
|
30
30
|
|
|
31
31
|
const HTTP_METHODS = new Set(["delete", "get", "patch", "post", "put"])
|
|
32
32
|
|
|
33
|
-
export function createClient<T>(
|
|
34
|
-
config: ClientConfig & { throwOnError: true },
|
|
35
|
-
): HoneyClient<InferRoutes<T>, true>
|
|
33
|
+
export function createClient<T>(config: ClientConfig & { throwOnError: true }): HoneyClient<InferRoutes<T>, true>
|
|
36
34
|
export function createClient<T>(
|
|
37
35
|
config: Omit<ClientConfig, "throwOnError"> & { throwOnError?: false },
|
|
38
36
|
): HoneyClient<InferRoutes<T>, false>
|
|
@@ -49,17 +47,13 @@ export function createClient<T, TThrow extends boolean = false>(
|
|
|
49
47
|
if (prop === "$isClientError") return isClientError
|
|
50
48
|
|
|
51
49
|
if (prop === "$url") {
|
|
52
|
-
return (
|
|
53
|
-
path
|
|
54
|
-
input?: { params?: Record<string, string>; search?: Record<string, unknown> },
|
|
55
|
-
) => http.buildUrl(path, input ?? {})
|
|
50
|
+
return (path: string, input?: { params?: Record<string, string>; search?: Record<string, unknown> }) =>
|
|
51
|
+
http.buildUrl(path, input ?? {})
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
if (prop === "$path") {
|
|
59
|
-
return (
|
|
60
|
-
path
|
|
61
|
-
input?: { params?: Record<string, string>; search?: Record<string, unknown> },
|
|
62
|
-
) => http.buildPath(path, input ?? {})
|
|
55
|
+
return (path: string, input?: { params?: Record<string, string>; search?: Record<string, unknown> }) =>
|
|
56
|
+
http.buildPath(path, input ?? {})
|
|
63
57
|
}
|
|
64
58
|
|
|
65
59
|
if (prop === "ws") {
|
|
@@ -97,9 +91,7 @@ export function createClient<T, TThrow extends boolean = false>(
|
|
|
97
91
|
let restPromise: Promise<unknown> | undefined
|
|
98
92
|
const lazyRest = (): Promise<unknown> => {
|
|
99
93
|
if (!restPromise) {
|
|
100
|
-
restPromise = shouldThrow
|
|
101
|
-
? http.request(method, path, opts)
|
|
102
|
-
: http.requestSafe(method, path, opts)
|
|
94
|
+
restPromise = shouldThrow ? http.request(method, path, opts) : http.requestSafe(method, path, opts)
|
|
103
95
|
}
|
|
104
96
|
return restPromise
|
|
105
97
|
}
|
package/src/client/sdk.ts
CHANGED
|
@@ -39,14 +39,20 @@ export function resolveInvalidationTargets(
|
|
|
39
39
|
): string[] {
|
|
40
40
|
const resolved: string[] = []
|
|
41
41
|
for (const target of targets) {
|
|
42
|
-
if (!params || !target.includes(":")) {
|
|
42
|
+
if (!params || !target.includes(":")) {
|
|
43
|
+
resolved.push(target)
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
43
46
|
const spaceIdx = target.indexOf(" ")
|
|
44
47
|
const targetMethod = target.slice(0, spaceIdx)
|
|
45
48
|
const targetPath = target.slice(spaceIdx + 1)
|
|
46
49
|
let hasUnresolved = false
|
|
47
50
|
const replaced = targetPath.replace(/:(\w+)/g, (match, key: string) => {
|
|
48
51
|
const val = params[key]
|
|
49
|
-
if (val === undefined) {
|
|
52
|
+
if (val === undefined) {
|
|
53
|
+
hasUnresolved = true
|
|
54
|
+
return match
|
|
55
|
+
}
|
|
50
56
|
return encodeURIComponent(val)
|
|
51
57
|
})
|
|
52
58
|
if (hasUnresolved) continue
|
|
@@ -64,9 +70,7 @@ export function pathMatchesPattern(concretePath: string, pattern: string): boole
|
|
|
64
70
|
if (!re) {
|
|
65
71
|
/* split on :param placeholders, escape each literal segment's metachars, rejoin with [^/]+ */
|
|
66
72
|
const parts = pattern.split(/:[^/]+/g)
|
|
67
|
-
const escaped = parts
|
|
68
|
-
.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
69
|
-
.join("[^/]+")
|
|
73
|
+
const escaped = parts.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[^/]+")
|
|
70
74
|
re = new RegExp(`^${escaped}$`)
|
|
71
75
|
patternRegexCache.set(pattern, re)
|
|
72
76
|
}
|
|
@@ -75,12 +79,12 @@ export function pathMatchesPattern(concretePath: string, pattern: string): boole
|
|
|
75
79
|
|
|
76
80
|
/* two-tier stale lookup: exact concrete match, then pattern fallback; sweeps expired entries in one pass */
|
|
77
81
|
export function lookupStale(
|
|
78
|
-
staleMap: Map<string, { by: string[]
|
|
82
|
+
staleMap: Map<string, { by: string[]; seq: number; until: number }>,
|
|
79
83
|
concreteSelector: string,
|
|
80
84
|
concretePath: string,
|
|
81
85
|
method: string,
|
|
82
86
|
now: number,
|
|
83
|
-
): { by: string[]
|
|
87
|
+
): { by: string[]; isStale: boolean } {
|
|
84
88
|
const allBy: string[] = []
|
|
85
89
|
const expired: string[] = []
|
|
86
90
|
|
|
@@ -89,7 +93,10 @@ export function lookupStale(
|
|
|
89
93
|
else if (exact) expired.push(concreteSelector)
|
|
90
94
|
|
|
91
95
|
for (const [key, entry] of staleMap) {
|
|
92
|
-
if (entry.until <= now) {
|
|
96
|
+
if (entry.until <= now) {
|
|
97
|
+
expired.push(key)
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
93
100
|
if (!key.includes(":")) continue
|
|
94
101
|
const spaceIdx = key.indexOf(" ")
|
|
95
102
|
const keyMethod = key.slice(0, spaceIdx)
|
|
@@ -111,9 +118,7 @@ export function createSDK<T = Record<string, Record<string, (...args: unknown[])
|
|
|
111
118
|
const http = new HTTPClient(config)
|
|
112
119
|
const staleTime = config.invalidation?.staleTime ?? 0
|
|
113
120
|
const hasInvalidation = staleTime > 0
|
|
114
|
-
const staleUntil = hasInvalidation
|
|
115
|
-
? new Map<string, { by: string[], seq: number, until: number }>()
|
|
116
|
-
: null
|
|
121
|
+
const staleUntil = hasInvalidation ? new Map<string, { by: string[]; seq: number; until: number }>() : null
|
|
117
122
|
|
|
118
123
|
let invalidationSeq = 0
|
|
119
124
|
|
|
@@ -156,14 +161,16 @@ export function createSDK<T = Record<string, Record<string, (...args: unknown[])
|
|
|
156
161
|
requestMeta = { invalidatedBy: by, isStale, selector: concreteSelector, seqSnapshot: invalidationSeq }
|
|
157
162
|
}
|
|
158
163
|
|
|
159
|
-
const result =
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
const result =
|
|
165
|
+
config.throwOnError === true
|
|
166
|
+
? await http.request(method, path, opts, requestMeta)
|
|
167
|
+
: await http.requestSafe(method, path, opts, requestMeta)
|
|
162
168
|
|
|
163
169
|
if (staleUntil) {
|
|
164
|
-
const isSuccess =
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
const isSuccess =
|
|
171
|
+
config.throwOnError === true
|
|
172
|
+
? true
|
|
173
|
+
: (result as { status: number }).status >= 200 && (result as { status: number }).status < 300
|
|
167
174
|
|
|
168
175
|
if (isSuccess) {
|
|
169
176
|
if (entry.invalidate && entry.invalidate.length > 0) {
|
package/src/client/types.ts
CHANGED
|
@@ -57,11 +57,7 @@ export type OutputFor<TRoutes, P extends string, M extends string> =
|
|
|
57
57
|
|
|
58
58
|
/** Check if a route returns SSE (text/event-stream in output) */
|
|
59
59
|
export type IsSSE<TRoutes, P extends string, M extends string> =
|
|
60
|
-
OutputDefFor<TRoutes, P, M> extends infer O
|
|
61
|
-
? O extends { "text/event-stream": unknown }
|
|
62
|
-
? true
|
|
63
|
-
: false
|
|
64
|
-
: false
|
|
60
|
+
OutputDefFor<TRoutes, P, M> extends infer O ? (O extends { "text/event-stream": unknown } ? true : false) : false
|
|
65
61
|
|
|
66
62
|
/** Extract errorsByStatus from route record if available */
|
|
67
63
|
type ErrorsByStatusFor<TRoutes, P extends string, M extends string> = P extends keyof TRoutes
|
|
@@ -109,8 +105,8 @@ type ErrorVariants<TErrorsByStatus> = {
|
|
|
109
105
|
export type ClientResult<TData, TErrorsByStatus = never> =
|
|
110
106
|
| { data: TData; error: null; response: Response; status: number }
|
|
111
107
|
| (HasStatusErrors<TErrorsByStatus> extends false
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
? { data: null; error: unknown; response: Response; status: number }
|
|
109
|
+
: ErrorVariants<TErrorsByStatus>)
|
|
114
110
|
|
|
115
111
|
/** Resolve return type based on transport + throw mode */
|
|
116
112
|
export type ReturnFor<TRoutes, P extends string, M extends string, TThrow extends boolean = true> =
|
|
@@ -121,8 +117,7 @@ export type ReturnFor<TRoutes, P extends string, M extends string, TThrow extend
|
|
|
121
117
|
: Promise<ClientResult<OutputFor<TRoutes, P, M>, ErrorsByStatusFor<TRoutes, P, M>>>
|
|
122
118
|
|
|
123
119
|
/** Build the client input type — merge route input with params from path */
|
|
124
|
-
export type ClientInput<TRoutes, P extends string, M extends string> = InputFor<TRoutes, P, M> &
|
|
125
|
-
ParamsInput<P>
|
|
120
|
+
export type ClientInput<TRoutes, P extends string, M extends string> = InputFor<TRoutes, P, M> & ParamsInput<P>
|
|
126
121
|
|
|
127
122
|
/** Extract params input if path has params */
|
|
128
123
|
type ParamsInput<P extends string> =
|
package/src/client/ws.ts
CHANGED
|
@@ -55,10 +55,7 @@ export function createTypedWebSocket(
|
|
|
55
55
|
break
|
|
56
56
|
case "close":
|
|
57
57
|
wrapped = (e: Event) =>
|
|
58
|
-
(handler as (code: number, reason: string) => void)(
|
|
59
|
-
(e as CloseEvent).code,
|
|
60
|
-
(e as CloseEvent).reason,
|
|
61
|
-
)
|
|
58
|
+
(handler as (code: number, reason: string) => void)((e as CloseEvent).code, (e as CloseEvent).reason)
|
|
62
59
|
break
|
|
63
60
|
case "error":
|
|
64
61
|
wrapped = (e: Event) => (handler as (error: unknown) => void)(e)
|
|
@@ -80,7 +77,8 @@ export function createTypedWebSocket(
|
|
|
80
77
|
|
|
81
78
|
function toWsData(data: ArrayBuffer | ArrayBufferView | string): string | Uint8Array<ArrayBuffer> {
|
|
82
79
|
if (typeof data === "string") return data
|
|
83
|
-
const view =
|
|
80
|
+
const view =
|
|
81
|
+
data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
84
82
|
const copy = new Uint8Array(view.byteLength)
|
|
85
83
|
copy.set(view)
|
|
86
84
|
return copy
|
package/src/client-mcp/server.ts
CHANGED
|
@@ -11,10 +11,7 @@
|
|
|
11
11
|
/* eslint-disable @typescript-eslint/no-deprecated */
|
|
12
12
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js"
|
|
13
13
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
14
|
-
import {
|
|
15
|
-
CallToolRequestSchema,
|
|
16
|
-
ListToolsRequestSchema,
|
|
17
|
-
} from "@modelcontextprotocol/sdk/types.js"
|
|
14
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"
|
|
18
15
|
import type { Tool, ToolResult } from "./types.ts"
|
|
19
16
|
|
|
20
17
|
type ServerError = Error & { status?: number; body?: unknown; data?: unknown }
|
|
@@ -42,9 +42,7 @@ type Attachment = {
|
|
|
42
42
|
const DEFAULT_BUFFER_SIZE = 100
|
|
43
43
|
const BUFFER_TTL_MS = 30_000
|
|
44
44
|
|
|
45
|
-
export function createRealtimeHandlers<TEnv = unknown>(
|
|
46
|
-
config: RealtimeHandlerConfig<TEnv>,
|
|
47
|
-
): RealtimeHandlers {
|
|
45
|
+
export function createRealtimeHandlers<TEnv = unknown>(config: RealtimeHandlerConfig<TEnv>): RealtimeHandlers {
|
|
48
46
|
const bufferSize = config.reconnectBuffer ?? DEFAULT_BUFFER_SIZE
|
|
49
47
|
const buffer = new ReconnectBuffer({ size: bufferSize })
|
|
50
48
|
const bus = createBus()
|
|
@@ -70,7 +68,7 @@ export function createRealtimeHandlers<TEnv = unknown>(
|
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
function sendFrame(ws: WebSocket, frame: ServerFrame): void {
|
|
73
|
-
(ws as unknown as { send(data: string): void }).send(encodeServerFrame(frame))
|
|
71
|
+
;(ws as unknown as { send(data: string): void }).send(encodeServerFrame(frame))
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
function getRouteHandler(): ((c: unknown, conn: ConnContext) => void | Promise<void>) | null {
|
|
@@ -85,7 +83,7 @@ export function createRealtimeHandlers<TEnv = unknown>(
|
|
|
85
83
|
return createConnContext({
|
|
86
84
|
bus,
|
|
87
85
|
closeFn: (reason) => {
|
|
88
|
-
(ws as unknown as { close(code?: number, reason?: string): void }).close(1000, reason ?? "")
|
|
86
|
+
;(ws as unknown as { close(code?: number, reason?: string): void }).close(1000, reason ?? "")
|
|
89
87
|
},
|
|
90
88
|
id: attachment.connId,
|
|
91
89
|
sendFn: (payload) => {
|
|
@@ -109,7 +107,9 @@ export function createRealtimeHandlers<TEnv = unknown>(
|
|
|
109
107
|
userId = await config.onAuth(req)
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
const pair = new (
|
|
110
|
+
const pair = new (
|
|
111
|
+
globalThis as unknown as { WebSocketPair: new () => { 0: WebSocket; 1: WebSocket } }
|
|
112
|
+
).WebSocketPair()
|
|
113
113
|
const client = pair[0]
|
|
114
114
|
const server = pair[1]
|
|
115
115
|
|
|
@@ -120,9 +120,7 @@ export function createRealtimeHandlers<TEnv = unknown>(
|
|
|
120
120
|
knownTokens.add(reconnectToken)
|
|
121
121
|
|
|
122
122
|
const attachment: Attachment = { connId, reconnectToken, userId }
|
|
123
|
-
;(server as unknown as { serializeAttachment(data: string): void }).serializeAttachment(
|
|
124
|
-
JSON.stringify(attachment),
|
|
125
|
-
)
|
|
123
|
+
;(server as unknown as { serializeAttachment(data: string): void }).serializeAttachment(JSON.stringify(attachment))
|
|
126
124
|
|
|
127
125
|
sendFrame(server, { reconnectToken, t: "ready" })
|
|
128
126
|
|
|
@@ -215,7 +213,7 @@ export function createRealtimeHandlers<TEnv = unknown>(
|
|
|
215
213
|
|
|
216
214
|
function handleError(ws: WebSocket, _err: unknown): Promise<void> {
|
|
217
215
|
try {
|
|
218
|
-
(ws as unknown as { close(code?: number, reason?: string): void }).close(1011, "internal error")
|
|
216
|
+
;(ws as unknown as { close(code?: number, reason?: string): void }).close(1011, "internal error")
|
|
219
217
|
} catch {
|
|
220
218
|
/* swallow — ws may already be closed */
|
|
221
219
|
}
|
package/src/codegen-go-cli.ts
CHANGED
|
@@ -82,11 +82,11 @@ type BodyShape =
|
|
|
82
82
|
| { kind: "json-flat"; scalars: BodyScalarInfo[]; required: boolean }
|
|
83
83
|
| { kind: "json-complex"; required: boolean }
|
|
84
84
|
| {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
kind: "multipart"
|
|
86
|
+
binaryFields: { name: string; required: boolean }[]
|
|
87
|
+
scalarFields: BodyScalarInfo[]
|
|
88
|
+
useGenericFileFlag: boolean
|
|
89
|
+
}
|
|
90
90
|
|
|
91
91
|
type CommandInfo = {
|
|
92
92
|
opId: string
|
|
@@ -163,16 +163,7 @@ let runtimeCache: Map<string, string> | null = null
|
|
|
163
163
|
/** Reads static .go runtime files from ./cli-go/ and caches them. */
|
|
164
164
|
export function loadGoCliRuntimeTemplates(): Map<string, string> {
|
|
165
165
|
if (runtimeCache) return runtimeCache
|
|
166
|
-
const names = [
|
|
167
|
-
"config.go",
|
|
168
|
-
"auth.go",
|
|
169
|
-
"output.go",
|
|
170
|
-
"errors.go",
|
|
171
|
-
"stream.go",
|
|
172
|
-
"multipart.go",
|
|
173
|
-
"version.go",
|
|
174
|
-
"root.go",
|
|
175
|
-
]
|
|
166
|
+
const names = ["config.go", "auth.go", "output.go", "errors.go", "stream.go", "multipart.go", "version.go", "root.go"]
|
|
176
167
|
const cache = new Map<string, string>()
|
|
177
168
|
for (const name of names) {
|
|
178
169
|
const filePath = fileURLToPath(new URL(`./cli-go/${name}`, import.meta.url))
|
|
@@ -190,10 +181,7 @@ export function loadGoCliRuntimeTemplates(): Map<string, string> {
|
|
|
190
181
|
|
|
191
182
|
/* ── param + body helpers ── */
|
|
192
183
|
|
|
193
|
-
function getPathParams(
|
|
194
|
-
op: Record<string, unknown>,
|
|
195
|
-
rawPath: string,
|
|
196
|
-
): ParamInfo[] {
|
|
184
|
+
function getPathParams(op: Record<string, unknown>, rawPath: string): ParamInfo[] {
|
|
197
185
|
const declared = extractOpenApiPathParams(rawPath)
|
|
198
186
|
const byName = new Map<string, Record<string, unknown>>()
|
|
199
187
|
const parameters = (op.parameters as Array<Record<string, unknown>> | undefined) ?? []
|
|
@@ -333,9 +321,11 @@ function hasJsonResponse(op: Record<string, unknown>): boolean {
|
|
|
333
321
|
|
|
334
322
|
/* ── command collection ── */
|
|
335
323
|
|
|
336
|
-
function collectCLIMethods(
|
|
337
|
-
|
|
338
|
-
|
|
324
|
+
function collectCLIMethods(spec: Record<string, unknown>): {
|
|
325
|
+
groups: Map<string, ResourceGroup>
|
|
326
|
+
skipped: string[]
|
|
327
|
+
serviceMap: Record<string, Record<string, unknown>>
|
|
328
|
+
} {
|
|
339
329
|
toIR(spec as Parameters<typeof toIR>[0])
|
|
340
330
|
const { serviceMap } = collectSDKMethods(spec as Parameters<typeof collectSDKMethods>[0])
|
|
341
331
|
const resolved = resolveRefs(spec as Parameters<typeof resolveRefs>[0]) as unknown as OpenApiSpec
|
|
@@ -609,12 +599,7 @@ function emitResourceFile(group: ResourceGroup, options: GoCLIOptions): string {
|
|
|
609
599
|
}
|
|
610
600
|
|
|
611
601
|
/** Emits var declarations for every flag-backing Go variable + the cobra.Command literal. */
|
|
612
|
-
function emitCommand(
|
|
613
|
-
l: string[],
|
|
614
|
-
group: ResourceGroup,
|
|
615
|
-
cmd: CommandInfo,
|
|
616
|
-
options: GoCLIOptions,
|
|
617
|
-
): void {
|
|
602
|
+
function emitCommand(l: string[], group: ResourceGroup, cmd: CommandInfo, options: GoCLIOptions): void {
|
|
618
603
|
/* flag-backing vars */
|
|
619
604
|
for (const p of cmd.pathParams) {
|
|
620
605
|
l.push(`var ${cmd.cmdVarName}${goPascal(p.name)}Var string`)
|
|
@@ -689,7 +674,9 @@ function emitFlagRegistrations(l: string[], cmd: CommandInfo): void {
|
|
|
689
674
|
const v = `${cmd.cmdVarName}${goPascal(p.name)}Var`
|
|
690
675
|
/* flag docstring references original param name for discoverability */
|
|
691
676
|
l.push(`\t/* Path flag — Use: ${JSON.stringify(p.name)} */`)
|
|
692
|
-
l.push(
|
|
677
|
+
l.push(
|
|
678
|
+
`\t${cmd.cmdVarName}.Flags().StringVar(&${v}, ${JSON.stringify(p.flagName)}, "", ${JSON.stringify(`Path parameter ${p.name}`)})`,
|
|
679
|
+
)
|
|
693
680
|
l.push(`\t${cmd.cmdVarName}.MarkFlagRequired(${JSON.stringify(p.flagName)})`)
|
|
694
681
|
}
|
|
695
682
|
for (const q of cmd.queryParams) {
|
|
@@ -697,7 +684,9 @@ function emitFlagRegistrations(l: string[], cmd: CommandInfo): void {
|
|
|
697
684
|
emitQueryFlag(l, cmd, q)
|
|
698
685
|
}
|
|
699
686
|
if (cmd.body.kind === "json-flat" || cmd.body.kind === "json-complex") {
|
|
700
|
-
l.push(
|
|
687
|
+
l.push(
|
|
688
|
+
`\t${cmd.cmdVarName}.Flags().StringVar(&${cmd.cmdVarName}DataVar, "data", "", "Request body: JSON literal, @file, or - for stdin")`,
|
|
689
|
+
)
|
|
701
690
|
}
|
|
702
691
|
if (cmd.body.kind === "json-flat") {
|
|
703
692
|
for (const s of cmd.body.scalars) {
|
|
@@ -717,7 +706,9 @@ function emitFlagRegistrations(l: string[], cmd: CommandInfo): void {
|
|
|
717
706
|
} else {
|
|
718
707
|
for (const f of cmd.body.binaryFields) {
|
|
719
708
|
const v = `${cmd.cmdVarName}${goPascal(f.name)}Var`
|
|
720
|
-
l.push(
|
|
709
|
+
l.push(
|
|
710
|
+
`\t${cmd.cmdVarName}.Flags().StringVar(&${v}, ${JSON.stringify(toFlagName(f.name))}, "", ${JSON.stringify(`Path to ${f.name} file`)})`,
|
|
711
|
+
)
|
|
721
712
|
if (f.required) {
|
|
722
713
|
l.push(`\t${cmd.cmdVarName}.MarkFlagRequired(${JSON.stringify(toFlagName(f.name))})`)
|
|
723
714
|
}
|
|
@@ -725,16 +716,17 @@ function emitFlagRegistrations(l: string[], cmd: CommandInfo): void {
|
|
|
725
716
|
}
|
|
726
717
|
}
|
|
727
718
|
if (cmd.hasLastEventId) {
|
|
728
|
-
l.push(
|
|
719
|
+
l.push(
|
|
720
|
+
`\t${cmd.cmdVarName}.Flags().StringVar(&${cmd.cmdVarName}LastEventIDVar, "last-event-id", "", "SSE Last-Event-ID resume token")`,
|
|
721
|
+
)
|
|
729
722
|
}
|
|
730
723
|
}
|
|
731
724
|
|
|
732
725
|
function emitQueryFlag(l: string[], cmd: CommandInfo, q: ParamInfo): void {
|
|
733
726
|
const v = `${cmd.cmdVarName}${goPascal(q.name)}Var`
|
|
734
727
|
const t = q.schema.type
|
|
735
|
-
const help =
|
|
736
|
-
? `Query param ${q.name} (one of: ${q.enumValues.join(", ")})`
|
|
737
|
-
: `Query param ${q.name}`
|
|
728
|
+
const help =
|
|
729
|
+
q.enumValues.length > 0 ? `Query param ${q.name} (one of: ${q.enumValues.join(", ")})` : `Query param ${q.name}`
|
|
738
730
|
const helpStr = JSON.stringify(help)
|
|
739
731
|
|
|
740
732
|
if (t === "integer") {
|
|
@@ -745,14 +737,18 @@ function emitQueryFlag(l: string[], cmd: CommandInfo, q: ParamInfo): void {
|
|
|
745
737
|
l.push(`\t${cmd.cmdVarName}.Flags().Float64Var(&${v}, ${JSON.stringify(q.flagName)}, ${def}, ${helpStr})`)
|
|
746
738
|
} else if (t === "boolean") {
|
|
747
739
|
const def = q.defaultValue === true
|
|
748
|
-
l.push(
|
|
740
|
+
l.push(
|
|
741
|
+
`\t${cmd.cmdVarName}.Flags().BoolVar(&${v}, ${JSON.stringify(q.flagName)}, ${def ? "true" : "false"}, ${helpStr})`,
|
|
742
|
+
)
|
|
749
743
|
} else if (t === "array") {
|
|
750
744
|
const defArr = Array.isArray(q.defaultValue) ? q.defaultValue : []
|
|
751
745
|
const defStr = `[]string{${defArr.map((x) => JSON.stringify(String(x))).join(", ")}}`
|
|
752
746
|
l.push(`\t${cmd.cmdVarName}.Flags().StringSliceVar(&${v}, ${JSON.stringify(q.flagName)}, ${defStr}, ${helpStr})`)
|
|
753
747
|
} else {
|
|
754
748
|
const def = typeof q.defaultValue === "string" ? q.defaultValue : ""
|
|
755
|
-
l.push(
|
|
749
|
+
l.push(
|
|
750
|
+
`\t${cmd.cmdVarName}.Flags().StringVar(&${v}, ${JSON.stringify(q.flagName)}, ${JSON.stringify(def)}, ${helpStr})`,
|
|
751
|
+
)
|
|
756
752
|
}
|
|
757
753
|
if (q.required) {
|
|
758
754
|
l.push(`\t${cmd.cmdVarName}.MarkFlagRequired(${JSON.stringify(q.flagName)})`)
|
|
@@ -761,9 +757,10 @@ function emitQueryFlag(l: string[], cmd: CommandInfo, q: ParamInfo): void {
|
|
|
761
757
|
|
|
762
758
|
function emitBodyScalarFlag(l: string[], cmd: CommandInfo, s: BodyScalarInfo): void {
|
|
763
759
|
const v = `${cmd.cmdVarName}${goPascal(s.propName)}Var`
|
|
764
|
-
const help =
|
|
765
|
-
|
|
766
|
-
|
|
760
|
+
const help =
|
|
761
|
+
s.enumValues.length > 0
|
|
762
|
+
? `Body field ${s.propName} (one of: ${s.enumValues.join(", ")})`
|
|
763
|
+
: `Body field ${s.propName}`
|
|
767
764
|
const helpStr = JSON.stringify(help)
|
|
768
765
|
if (s.schemaType === "integer") {
|
|
769
766
|
l.push(`\t${cmd.cmdVarName}.Flags().Int64Var(&${v}, ${JSON.stringify(s.flagName)}, 0, ${helpStr})`)
|
|
@@ -809,7 +806,9 @@ function emitPreRunE(cmd: CommandInfo): string[] {
|
|
|
809
806
|
if (s.schemaType !== "string") continue
|
|
810
807
|
const v = `${cmd.cmdVarName}${goPascal(s.propName)}Var`
|
|
811
808
|
const values = s.enumValues.map((x) => JSON.stringify(x)).join(", ")
|
|
812
|
-
lines.push(
|
|
809
|
+
lines.push(
|
|
810
|
+
`if cmd.Flags().Changed(${JSON.stringify(s.flagName)}) && !slices.Contains([]string{${values}}, ${v}) {`,
|
|
811
|
+
)
|
|
813
812
|
lines.push(`\treturn fmt.Errorf("--${s.flagName} must be one of: ${s.enumValues.join(", ")}")`)
|
|
814
813
|
lines.push(`}`)
|
|
815
814
|
}
|
|
@@ -858,12 +857,16 @@ function emitRunE(l: string[], cmd: CommandInfo, _options: GoCLIOptions): void {
|
|
|
858
857
|
l.push(`${ind}\tdataBytes, derr := cli.ReadDataFlag(${cmd.cmdVarName}DataVar)`)
|
|
859
858
|
l.push(`${ind}\tif derr != nil { return derr }`)
|
|
860
859
|
l.push(`${ind}\tif len(dataBytes) > 0 {`)
|
|
861
|
-
l.push(
|
|
860
|
+
l.push(
|
|
861
|
+
`${ind}\t\tif jerr := json.Unmarshal(dataBytes, &merged); jerr != nil { return fmt.Errorf("parse --data: %w", jerr) }`,
|
|
862
|
+
)
|
|
862
863
|
l.push(`${ind}\t}`)
|
|
863
864
|
l.push(`${ind}}`)
|
|
864
865
|
for (const s of cmd.body.scalars) {
|
|
865
866
|
const v = `${cmd.cmdVarName}${goPascal(s.propName)}Var`
|
|
866
|
-
l.push(
|
|
867
|
+
l.push(
|
|
868
|
+
`${ind}if cmd.Flags().Changed(${JSON.stringify(s.flagName)}) { merged[${JSON.stringify(s.propName)}] = ${v} }`,
|
|
869
|
+
)
|
|
867
870
|
}
|
|
868
871
|
l.push(`${ind}bodyBytes, merr := json.Marshal(merged)`)
|
|
869
872
|
l.push(`${ind}if merr != nil { return merr }`)
|
|
@@ -879,15 +882,21 @@ function emitRunE(l: string[], cmd: CommandInfo, _options: GoCLIOptions): void {
|
|
|
879
882
|
for (const s of cmd.body.scalarFields) {
|
|
880
883
|
const v = `${cmd.cmdVarName}${goPascal(s.propName)}Var`
|
|
881
884
|
if (s.schemaType === "string") {
|
|
882
|
-
l.push(
|
|
885
|
+
l.push(
|
|
886
|
+
`${ind}if cmd.Flags().Changed(${JSON.stringify(s.flagName)}) { fields[${JSON.stringify(s.propName)}] = ${v} }`,
|
|
887
|
+
)
|
|
883
888
|
} else {
|
|
884
|
-
l.push(
|
|
889
|
+
l.push(
|
|
890
|
+
`${ind}if cmd.Flags().Changed(${JSON.stringify(s.flagName)}) { fields[${JSON.stringify(s.propName)}] = fmt.Sprint(${v}) }`,
|
|
891
|
+
)
|
|
885
892
|
}
|
|
886
893
|
}
|
|
887
894
|
l.push(`${ind}files := map[string]string{}`)
|
|
888
895
|
if (cmd.body.useGenericFileFlag) {
|
|
889
896
|
const bin = cmd.body.binaryFields[0]
|
|
890
|
-
l.push(
|
|
897
|
+
l.push(
|
|
898
|
+
`${ind}if ${cmd.cmdVarName}FileVar != "" { files[${JSON.stringify(bin.name)}] = ${cmd.cmdVarName}FileVar }`,
|
|
899
|
+
)
|
|
891
900
|
} else {
|
|
892
901
|
for (const f of cmd.body.binaryFields) {
|
|
893
902
|
const v = `${cmd.cmdVarName}${goPascal(f.name)}Var`
|
|
@@ -908,7 +917,9 @@ function emitRunE(l: string[], cmd: CommandInfo, _options: GoCLIOptions): void {
|
|
|
908
917
|
l.push(`${ind}req.Header.Set("Accept", "text/event-stream")`)
|
|
909
918
|
l.push(`${ind}if apiKey != "" { req.Header.Set("Authorization", "Bearer "+apiKey) }`)
|
|
910
919
|
if (cmd.hasLastEventId) {
|
|
911
|
-
l.push(
|
|
920
|
+
l.push(
|
|
921
|
+
`${ind}if ${cmd.cmdVarName}LastEventIDVar != "" { req.Header.Set("Last-Event-ID", ${cmd.cmdVarName}LastEventIDVar) }`,
|
|
922
|
+
)
|
|
912
923
|
}
|
|
913
924
|
l.push(`${ind}resp, herr := httpClient.Do(req)`)
|
|
914
925
|
l.push(`${ind}if herr != nil { return herr }`)
|
|
@@ -941,7 +952,9 @@ function emitRunE(l: string[], cmd: CommandInfo, _options: GoCLIOptions): void {
|
|
|
941
952
|
l.push(`${ind}body, berr := io.ReadAll(resp.Body)`)
|
|
942
953
|
l.push(`${ind}if berr != nil { return berr }`)
|
|
943
954
|
l.push(`${ind}if resp.StatusCode >= 400 {`)
|
|
944
|
-
l.push(
|
|
955
|
+
l.push(
|
|
956
|
+
`${ind}\treturn &sdk.StatusError{StatusCode: resp.StatusCode, Body: body, Response: resp, Message: string(body)}`,
|
|
957
|
+
)
|
|
945
958
|
l.push(`${ind}}`)
|
|
946
959
|
if (cmd.has204) {
|
|
947
960
|
l.push(`${ind}if resp.StatusCode == http.StatusNoContent { return nil }`)
|
|
@@ -970,11 +983,16 @@ function buildPathExpr(cmd: CommandInfo): string {
|
|
|
970
983
|
function querySetStmt(q: ParamInfo, v: string): string {
|
|
971
984
|
const name = JSON.stringify(q.name)
|
|
972
985
|
switch (q.schema.type) {
|
|
973
|
-
case "integer":
|
|
974
|
-
|
|
975
|
-
case "
|
|
976
|
-
|
|
977
|
-
|
|
986
|
+
case "integer":
|
|
987
|
+
return `q.Set(${name}, fmt.Sprintf("%d", ${v}))`
|
|
988
|
+
case "number":
|
|
989
|
+
return `q.Set(${name}, fmt.Sprintf("%g", ${v}))`
|
|
990
|
+
case "boolean":
|
|
991
|
+
return `q.Set(${name}, fmt.Sprintf("%t", ${v}))`
|
|
992
|
+
case "array":
|
|
993
|
+
return `for _, v := range ${v} { q.Add(${name}, v) }`
|
|
994
|
+
default:
|
|
995
|
+
return `q.Set(${name}, ${v})`
|
|
978
996
|
}
|
|
979
997
|
}
|
|
980
998
|
|
|
@@ -1087,11 +1105,7 @@ function emitReadme(spec: OpenApiSpec, options: GoCLIOptions): string {
|
|
|
1087
1105
|
|
|
1088
1106
|
/* ── embedded SDK copy ── */
|
|
1089
1107
|
|
|
1090
|
-
function copyEmbeddedSDK(
|
|
1091
|
-
spec: Record<string, unknown>,
|
|
1092
|
-
options: GoCLIOptions,
|
|
1093
|
-
outFiles: Record<string, string>,
|
|
1094
|
-
): void {
|
|
1108
|
+
function copyEmbeddedSDK(spec: Record<string, unknown>, options: GoCLIOptions, outFiles: Record<string, string>): void {
|
|
1095
1109
|
const sdkModule = `${resolveModulePath(options)}/internal/sdk`
|
|
1096
1110
|
const sdkGen = generateGoSDK(spec, { modulePath: sdkModule })
|
|
1097
1111
|
for (const [name, content] of Object.entries(sdkGen.files)) {
|
|
@@ -1107,11 +1121,7 @@ function copyEmbeddedSDK(
|
|
|
1107
1121
|
* When embedding, add a small sse_export.go into internal/sdk/.
|
|
1108
1122
|
* When using external SDK, we still need the same symbol — emit an adapter file. */
|
|
1109
1123
|
|
|
1110
|
-
function emitSSEExportShim(
|
|
1111
|
-
options: GoCLIOptions,
|
|
1112
|
-
files: Record<string, string>,
|
|
1113
|
-
hasEmbedded: boolean,
|
|
1114
|
-
): void {
|
|
1124
|
+
function emitSSEExportShim(options: GoCLIOptions, files: Record<string, string>, hasEmbedded: boolean): void {
|
|
1115
1125
|
const shim = [
|
|
1116
1126
|
`// Code generated by honey. DO NOT EDIT.`,
|
|
1117
1127
|
`package sdk`,
|
|
@@ -1137,10 +1147,7 @@ function emitSSEExportShim(
|
|
|
1137
1147
|
|
|
1138
1148
|
/* ── public entrypoint ── */
|
|
1139
1149
|
|
|
1140
|
-
export function generateGoCLI(
|
|
1141
|
-
spec: Record<string, unknown>,
|
|
1142
|
-
options: GoCLIOptions,
|
|
1143
|
-
): GeneratedGoCLI {
|
|
1150
|
+
export function generateGoCLI(spec: Record<string, unknown>, options: GoCLIOptions): GeneratedGoCLI {
|
|
1144
1151
|
const resolved = resolveRefs(spec as Parameters<typeof resolveRefs>[0]) as unknown as OpenApiSpec
|
|
1145
1152
|
const { groups, skipped, serviceMap } = collectCLIMethods(spec)
|
|
1146
1153
|
|