@lovrozagar/honey 0.1.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 +51 -0
- package/docs/api-ref/go.md +399 -0
- package/docs/api-ref/python.md +399 -0
- package/docs/api-ref/rust.md +399 -0
- package/docs/api-ref/typescript.md +399 -0
- package/docs/invalidate-spec.md +303 -0
- package/docs/sdk.md +722 -0
- package/package.json +120 -0
- package/src/accepts.ts +78 -0
- package/src/body-limit.ts +100 -0
- package/src/build/index.ts +174 -0
- package/src/cli-go/auth.go +15 -0
- package/src/cli-go/config.go +165 -0
- package/src/cli-go/errors.go +57 -0
- package/src/cli-go/multipart.go +55 -0
- package/src/cli-go/output.go +109 -0
- package/src/cli-go/root.go +30 -0
- package/src/cli-go/stream.go +88 -0
- package/src/cli-go/version.go +5 -0
- package/src/cli.ts +204 -0
- package/src/client/error.ts +27 -0
- package/src/client/http.ts +502 -0
- package/src/client/index.ts +127 -0
- package/src/client/sdk.ts +265 -0
- package/src/client/sse.ts +102 -0
- package/src/client/types.ts +211 -0
- package/src/client/ws.ts +115 -0
- package/src/client-go/errors.go +207 -0
- package/src/client-go/invalidation.go +373 -0
- package/src/client-go/realtime.go +317 -0
- package/src/client-go/result.go +20 -0
- package/src/client-go/runtime.go +413 -0
- package/src/client-go/sse.go +149 -0
- package/src/client-go/transport.go +452 -0
- package/src/client-go/ws.go +104 -0
- package/src/client-mcp/README.md +10 -0
- package/src/client-mcp/server.ts +94 -0
- package/src/client-mcp/types.ts +19 -0
- package/src/client-python/_errors.py +115 -0
- package/src/client-python/_invalidation.py +578 -0
- package/src/client-python/_realtime.py +156 -0
- package/src/client-python/_runtime.py +469 -0
- package/src/client-python/_sse.py +99 -0
- package/src/client-python/_transport.py +335 -0
- package/src/client-python/_ws.py +131 -0
- package/src/client-python/py.typed +0 -0
- package/src/client-rust/errors.rs +200 -0
- package/src/client-rust/invalidation.rs +441 -0
- package/src/client-rust/invalidation_sync.rs +306 -0
- package/src/client-rust/realtime.rs +695 -0
- package/src/client-rust/result.rs +22 -0
- package/src/client-rust/runtime.rs +547 -0
- package/src/client-rust/runtime_sync.rs +452 -0
- package/src/client-rust/sse.rs +167 -0
- package/src/client-rust/ws.rs +143 -0
- package/src/cloudflare/realtime.ts +236 -0
- package/src/codegen-go-cli.ts +1180 -0
- package/src/codegen-go.ts +1010 -0
- package/src/codegen-hash.ts +8 -0
- package/src/codegen-ir.ts +517 -0
- package/src/codegen-loaders.ts +53 -0
- package/src/codegen-mcp.ts +364 -0
- package/src/codegen-python.ts +1028 -0
- package/src/codegen-rust.ts +1652 -0
- package/src/codegen-sanitize.ts +67 -0
- package/src/codegen-schema-naming.ts +146 -0
- package/src/codegen.ts +5015 -0
- package/src/context.ts +210 -0
- package/src/cookie-sign.ts +58 -0
- package/src/cookie.ts +89 -0
- package/src/cors.ts +96 -0
- package/src/crypto.ts +19 -0
- package/src/csrf.ts +54 -0
- package/src/curl-logger.ts +235 -0
- package/src/detect-runtime.ts +19 -0
- package/src/error.ts +52 -0
- package/src/errors.ts +87 -0
- package/src/etag.ts +74 -0
- package/src/feature-load.ts +23 -0
- package/src/go-type-emitter.ts +404 -0
- package/src/honey-response.ts +354 -0
- package/src/i18n-slot.ts +20 -0
- package/src/i18n.ts +234 -0
- package/src/index.ts +3843 -0
- package/src/init.ts +149 -0
- package/src/input.ts +8 -0
- package/src/ip-restrict.ts +192 -0
- package/src/logger.ts +149 -0
- package/src/middleware.ts +199 -0
- package/src/node-request.ts +240 -0
- package/src/node.ts +212 -0
- package/src/openapi/register.ts +19 -0
- package/src/openapi/scalar.ts +33 -0
- package/src/openapi/spec-factory.ts +46 -0
- package/src/openapi/spec.ts +31 -0
- package/src/openapi/swagger.ts +34 -0
- package/src/plugin.ts +771 -0
- package/src/powered-by.ts +17 -0
- package/src/pretty-json.ts +39 -0
- package/src/proxy.ts +155 -0
- package/src/python-type-emitter.ts +144 -0
- package/src/realtime/buffer.ts +101 -0
- package/src/realtime/bus.ts +93 -0
- package/src/realtime/longpoll.ts +148 -0
- package/src/realtime/protocol.ts +128 -0
- package/src/realtime/route.ts +104 -0
- package/src/realtime/runtime.ts +430 -0
- package/src/request-id.ts +23 -0
- package/src/request-to-curl.ts +34 -0
- package/src/response.ts +414 -0
- package/src/rust-type-emitter.ts +412 -0
- package/src/secure-headers.ts +69 -0
- package/src/serve-register.ts +8 -0
- package/src/serve-slot.ts +20 -0
- package/src/serve.ts +141 -0
- package/src/server-timing.ts +66 -0
- package/src/static.ts +60 -0
- package/src/telemetry/otel.ts +139 -0
- package/src/testing.ts +114 -0
- package/src/timeout.ts +36 -0
- package/src/tree.ts +464 -0
- package/src/ts-type-emitter.ts +106 -0
- package/src/type-emitter.ts +524 -0
- package/src/type-extractor.ts +749 -0
- package/src/types.ts +638 -0
- package/src/validation.ts +300 -0
- package/src/ws/bun.ts +89 -0
- package/src/ws/cloudflare.ts +133 -0
- package/src/ws/deno.ts +109 -0
- package/src/ws/node.ts +161 -0
- package/src/yaml.ts +80 -0
package/src/ws/node.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type RawSocket,
|
|
3
|
+
type WSAdapter,
|
|
4
|
+
type WSContext,
|
|
5
|
+
WSContextImpl,
|
|
6
|
+
type WSHandler,
|
|
7
|
+
} from "./cloudflare.ts"
|
|
8
|
+
|
|
9
|
+
import type { WSAdapter, WSHandler } from "./cloudflare.ts"
|
|
10
|
+
import { WSContextImpl } from "./cloudflare.ts"
|
|
11
|
+
|
|
12
|
+
type WsModule = {
|
|
13
|
+
WebSocketServer: new (opts: {
|
|
14
|
+
noServer: true
|
|
15
|
+
perMessageDeflate: boolean
|
|
16
|
+
}) => {
|
|
17
|
+
handleUpgrade(req: unknown, socket: unknown, head: unknown, cb: (ws: NodeWS) => void): void
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type NodeWS = {
|
|
22
|
+
close(code?: number, reason?: string): void
|
|
23
|
+
on(event: "close", cb: (code: number, reason: Buffer) => void): void
|
|
24
|
+
on(event: "error", cb: (err: unknown) => void): void
|
|
25
|
+
on(event: "message", cb: (data: Buffer | ArrayBuffer | Buffer[], isBinary: boolean) => void): void
|
|
26
|
+
on(event: "pong", cb: () => void): void
|
|
27
|
+
ping(): void
|
|
28
|
+
readyState: number
|
|
29
|
+
send(data: ArrayBuffer | Buffer | Uint8Array | string): void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type NodeUpgradeData = {
|
|
33
|
+
head: Buffer
|
|
34
|
+
req: unknown
|
|
35
|
+
socket: unknown
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Node.js WebSocket adapter.
|
|
40
|
+
* Requires the `ws` package. Creates a no-server WebSocketServer internally.
|
|
41
|
+
* Reads __nodeUpgrade from env (placed there by serve()).
|
|
42
|
+
*/
|
|
43
|
+
type WssInstance = {
|
|
44
|
+
handleUpgrade(req: unknown, socket: unknown, head: unknown, cb: (ws: NodeWS) => void): void
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type KeepaliveConfig = {
|
|
48
|
+
interval: number
|
|
49
|
+
timeout: number
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function nodeWebSocket(opts?: { keepalive?: KeepaliveConfig }): WSAdapter {
|
|
53
|
+
let wss: WssInstance | null = null
|
|
54
|
+
let wssReady: Promise<void> | null = null
|
|
55
|
+
|
|
56
|
+
const ensureWss = async (): Promise<WssInstance> => {
|
|
57
|
+
if (wss) return wss
|
|
58
|
+
if (!wssReady) {
|
|
59
|
+
wssReady = import("ws").then((mod) => {
|
|
60
|
+
const wsModule = mod as unknown as WsModule
|
|
61
|
+
wss = new wsModule.WebSocketServer({ noServer: true, perMessageDeflate: false })
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
await wssReady
|
|
65
|
+
if (!wss) throw new Error("Failed to initialize WebSocketServer")
|
|
66
|
+
return wss
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
async upgrade(_req: Request, env: unknown, handler: WSHandler<unknown>) {
|
|
71
|
+
const server = await ensureWss()
|
|
72
|
+
|
|
73
|
+
const nodeEnv = env as Record<string, unknown>
|
|
74
|
+
const upgrade = nodeEnv.__nodeUpgrade as NodeUpgradeData
|
|
75
|
+
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
try {
|
|
78
|
+
server.handleUpgrade(upgrade.req, upgrade.socket, upgrade.head, (ws: NodeWS) => {
|
|
79
|
+
const socket = new WSContextImpl(ws)
|
|
80
|
+
|
|
81
|
+
ws.on("message", (data: Buffer | ArrayBuffer | Buffer[], isBinary: boolean) => {
|
|
82
|
+
if (!isBinary) {
|
|
83
|
+
/* text frame — decode to string to match other runtimes */
|
|
84
|
+
const text = Buffer.isBuffer(data) ? data.toString("utf-8") : String(data)
|
|
85
|
+
handler.onMessage?.(undefined, socket, text)
|
|
86
|
+
} else if (Buffer.isBuffer(data)) {
|
|
87
|
+
/* binary frame — slice from pool to get exact bytes */
|
|
88
|
+
handler.onMessage?.(
|
|
89
|
+
undefined,
|
|
90
|
+
socket,
|
|
91
|
+
data.buffer.slice(
|
|
92
|
+
data.byteOffset,
|
|
93
|
+
data.byteOffset + data.byteLength,
|
|
94
|
+
) as ArrayBuffer,
|
|
95
|
+
)
|
|
96
|
+
} else if (Array.isArray(data)) {
|
|
97
|
+
const merged = Buffer.concat(data)
|
|
98
|
+
handler.onMessage?.(
|
|
99
|
+
undefined,
|
|
100
|
+
socket,
|
|
101
|
+
merged.buffer.slice(
|
|
102
|
+
merged.byteOffset,
|
|
103
|
+
merged.byteOffset + merged.byteLength,
|
|
104
|
+
) as ArrayBuffer,
|
|
105
|
+
)
|
|
106
|
+
} else {
|
|
107
|
+
handler.onMessage?.(undefined, socket, data)
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
/* keepalive ping/pong */
|
|
112
|
+
let pingTimer: ReturnType<typeof setInterval> | undefined
|
|
113
|
+
let pongTimeout: ReturnType<typeof setTimeout> | undefined
|
|
114
|
+
|
|
115
|
+
if (opts?.keepalive) {
|
|
116
|
+
const { interval, timeout } = opts.keepalive
|
|
117
|
+
ws.on("pong", () => {
|
|
118
|
+
if (pongTimeout !== undefined) {
|
|
119
|
+
clearTimeout(pongTimeout)
|
|
120
|
+
pongTimeout = undefined
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
pingTimer = setInterval(() => {
|
|
124
|
+
if (ws.readyState !== 1) {
|
|
125
|
+
clearInterval(pingTimer)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
ws.ping()
|
|
129
|
+
pongTimeout = setTimeout(() => {
|
|
130
|
+
ws.close(1001, "keepalive timeout")
|
|
131
|
+
}, timeout)
|
|
132
|
+
}, interval)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
ws.on("close", (code: number, reason: Buffer) => {
|
|
136
|
+
if (pingTimer !== undefined) clearInterval(pingTimer)
|
|
137
|
+
if (pongTimeout !== undefined) clearTimeout(pongTimeout)
|
|
138
|
+
handler.onClose?.(undefined, socket, code, reason.toString())
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
ws.on("error", (err: unknown) => {
|
|
142
|
+
if (pingTimer !== undefined) clearInterval(pingTimer)
|
|
143
|
+
if (pongTimeout !== undefined) clearTimeout(pongTimeout)
|
|
144
|
+
handler.onError?.(undefined, socket, err)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
handler.onOpen?.(undefined, socket)
|
|
148
|
+
|
|
149
|
+
/* Node's Response rejects status 101 (Fetch spec: 200-599 only).
|
|
150
|
+
Create a valid Response and override status for the sentinel check. */
|
|
151
|
+
const resp = new Response(null)
|
|
152
|
+
Object.defineProperty(resp, "status", { value: 101 })
|
|
153
|
+
resolve({ response: resp, socket })
|
|
154
|
+
})
|
|
155
|
+
} catch (err) {
|
|
156
|
+
reject(err)
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
},
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/yaml.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** JSON-compatible YAML 1.2 emitter — same document as JSON.stringify, different encoding. */
|
|
2
|
+
|
|
3
|
+
const INDENT = " "
|
|
4
|
+
|
|
5
|
+
export function yamlSiblingPath(jsonPath: string): string {
|
|
6
|
+
if (jsonPath.endsWith(".yaml") || jsonPath.endsWith(".yml")) return jsonPath.replace(/\.yml$/, ".yaml")
|
|
7
|
+
return jsonPath.endsWith(".json") ? `${jsonPath.slice(0, -5)}.yaml` : `${jsonPath}.yaml`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function toYaml(value: unknown): string {
|
|
11
|
+
return `${emit(value, 0)}\n`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function emit(value: unknown, indent: number): string {
|
|
15
|
+
if (value === null || value === undefined) return "null"
|
|
16
|
+
if (typeof value === "boolean") return value ? "true" : "false"
|
|
17
|
+
if (typeof value === "number") {
|
|
18
|
+
if (!Number.isFinite(value)) return JSON.stringify(String(value))
|
|
19
|
+
return Object.is(value, -0) ? "-0" : String(value)
|
|
20
|
+
}
|
|
21
|
+
if (typeof value === "string") return emitString(value)
|
|
22
|
+
if (Array.isArray(value)) return emitArray(value, indent)
|
|
23
|
+
if (typeof value === "object") return emitObject(value as Record<string, unknown>, indent)
|
|
24
|
+
return JSON.stringify(String(value))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function emitString(value: string): string {
|
|
28
|
+
if (value === "") return '""'
|
|
29
|
+
if (needsQuotes(value)) return JSON.stringify(value)
|
|
30
|
+
return value
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function needsQuotes(value: string): boolean {
|
|
34
|
+
if (/^[-?:{},[\],&*#|!>'%@`]/.test(value)) return true
|
|
35
|
+
if (/[\n\r\t]/.test(value)) return true
|
|
36
|
+
if (/^\s|\s$/.test(value)) return true
|
|
37
|
+
if (value.includes(": ") || value.includes(" #")) return true
|
|
38
|
+
if (/^(true|false|null|yes|no|on|off)$/i.test(value)) return true
|
|
39
|
+
if (/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(value)) return true
|
|
40
|
+
if (/^\d/.test(value)) return true
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isNonEmptyCollection(value: unknown): boolean {
|
|
45
|
+
if (Array.isArray(value)) return value.length > 0
|
|
46
|
+
return value !== null && typeof value === "object" && Object.keys(value).length > 0
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function emitArray(value: unknown[], indent: number): string {
|
|
50
|
+
if (value.length === 0) return "[]"
|
|
51
|
+
const pad = INDENT.repeat(indent)
|
|
52
|
+
const childPad = INDENT.repeat(indent + 1)
|
|
53
|
+
return value
|
|
54
|
+
.map((item) => {
|
|
55
|
+
if (isNonEmptyCollection(item)) {
|
|
56
|
+
const inner = emit(item, indent + 1)
|
|
57
|
+
const lines = inner.split("\n")
|
|
58
|
+
const first = lines[0]?.startsWith(childPad) ? lines[0].slice(childPad.length) : (lines[0] ?? "")
|
|
59
|
+
return [`${pad}- ${first}`, ...lines.slice(1)].join("\n")
|
|
60
|
+
}
|
|
61
|
+
return `${pad}- ${emit(item, 0)}`
|
|
62
|
+
})
|
|
63
|
+
.join("\n")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function emitObject(value: Record<string, unknown>, indent: number): string {
|
|
67
|
+
const keys = Object.keys(value)
|
|
68
|
+
if (keys.length === 0) return "{}"
|
|
69
|
+
const pad = INDENT.repeat(indent)
|
|
70
|
+
return keys
|
|
71
|
+
.map((key) => {
|
|
72
|
+
const child = value[key]
|
|
73
|
+
const renderedKey = needsQuotes(key) || key === "" ? JSON.stringify(key) : key
|
|
74
|
+
if (isNonEmptyCollection(child)) {
|
|
75
|
+
return `${pad}${renderedKey}:\n${emit(child, indent + 1)}`
|
|
76
|
+
}
|
|
77
|
+
return `${pad}${renderedKey}: ${emit(child, 0)}`
|
|
78
|
+
})
|
|
79
|
+
.join("\n")
|
|
80
|
+
}
|