@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/secure-headers.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { namedMiddleware } from "./middleware.ts"
|
|
1
2
|
import type { MiddlewareFn } from "./middleware.ts"
|
|
2
3
|
|
|
3
4
|
type SecureHeadersOptions = {
|
|
@@ -65,5 +66,5 @@ export function secureHeaders(options?: SecureHeadersOptions): MiddlewareFn<{},
|
|
|
65
66
|
return response
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
return mw
|
|
69
|
+
return namedMiddleware("secureHeaders", mw)
|
|
69
70
|
}
|
package/src/serve.ts
CHANGED
|
@@ -87,25 +87,16 @@ export async function startHoneyServer(
|
|
|
87
87
|
}
|
|
88
88
|
).Deno
|
|
89
89
|
const ac = new AbortController()
|
|
90
|
-
const server = DenoNs.serve(
|
|
91
|
-
{ hostname, port, signal: ac.signal },
|
|
92
|
-
(req) => listening.fetch(req, env),
|
|
93
|
-
)
|
|
90
|
+
const server = DenoNs.serve({ hostname, port, signal: ac.signal }, (req) => listening.fetch(req, env))
|
|
94
91
|
const bound = server.addr?.port ?? port
|
|
95
92
|
return {
|
|
96
93
|
async close() {
|
|
97
94
|
ac.abort()
|
|
98
95
|
if (server.shutdown) {
|
|
99
|
-
await Promise.race([
|
|
100
|
-
server.shutdown(),
|
|
101
|
-
new Promise<void>((r) => setTimeout(r, 1_000)),
|
|
102
|
-
])
|
|
96
|
+
await Promise.race([server.shutdown(), new Promise<void>((r) => setTimeout(r, 1_000))])
|
|
103
97
|
return
|
|
104
98
|
}
|
|
105
|
-
await Promise.race([
|
|
106
|
-
server.finished ?? Promise.resolve(),
|
|
107
|
-
new Promise<void>((r) => setTimeout(r, 1_000)),
|
|
108
|
-
])
|
|
99
|
+
await Promise.race([server.finished ?? Promise.resolve(), new Promise<void>((r) => setTimeout(r, 1_000))])
|
|
109
100
|
},
|
|
110
101
|
hostname,
|
|
111
102
|
port: bound,
|
package/src/server-timing.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { namedMiddleware } from "./middleware.ts"
|
|
1
2
|
import type { MiddlewareFn } from "./middleware.ts"
|
|
2
3
|
|
|
3
4
|
export type Timing = {
|
|
@@ -62,5 +63,5 @@ export function serverTiming(): MiddlewareFn<{}, { timing: Timing }> {
|
|
|
62
63
|
return response
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
return mw
|
|
66
|
+
return namedMiddleware("serverTiming", mw)
|
|
66
67
|
}
|
package/src/static.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { namedMiddleware } from "./middleware.ts"
|
|
1
2
|
import type { MiddlewareFn } from "./middleware.ts"
|
|
2
3
|
|
|
3
4
|
type StaticConfig<TCtx> = {
|
|
@@ -9,9 +10,7 @@ type StaticConfig<TCtx> = {
|
|
|
9
10
|
|
|
10
11
|
const TRAVERSAL = /(?:^|\/)\.\.\//
|
|
11
12
|
|
|
12
|
-
export function staticFiles<TCtx extends { req: Request }>(
|
|
13
|
-
config: StaticConfig<TCtx>,
|
|
14
|
-
): MiddlewareFn<TCtx, {}> {
|
|
13
|
+
export function staticFiles<TCtx extends { req: Request }>(config: StaticConfig<TCtx>): MiddlewareFn<TCtx, {}> {
|
|
15
14
|
const prefix = config.prefix ?? "/"
|
|
16
15
|
|
|
17
16
|
const mw: MiddlewareFn<TCtx, {}> = async (ctx, next) => {
|
|
@@ -56,5 +55,5 @@ export function staticFiles<TCtx extends { req: Request }>(
|
|
|
56
55
|
return response
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
return mw
|
|
58
|
+
return namedMiddleware("staticFiles", mw)
|
|
60
59
|
}
|
package/src/telemetry/otel.ts
CHANGED
|
@@ -18,12 +18,7 @@ type TelemetryAdapter = {
|
|
|
18
18
|
onNotFound?(ctx: { method: string; path: string; req: Request }): void
|
|
19
19
|
onRequest?(ctx: { env: unknown; req: Request }): void
|
|
20
20
|
onResponse?(ctx: { duration: number; req: Request; status: number }): void
|
|
21
|
-
onRoute?(ctx: {
|
|
22
|
-
method: string
|
|
23
|
-
params: Record<string, string>
|
|
24
|
-
path: string
|
|
25
|
-
req: Request
|
|
26
|
-
}): void
|
|
21
|
+
onRoute?(ctx: { method: string; params: Record<string, string>; path: string; req: Request }): void
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
export function otelAdapter(options: { tracer: Tracer }): TelemetryAdapter {
|
package/src/testing.ts
CHANGED
|
@@ -18,12 +18,7 @@ type TestClient = {
|
|
|
18
18
|
request(method: string, path: string, opts?: TestRequestOptions): Promise<Response>
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function buildRequest(
|
|
22
|
-
method: string,
|
|
23
|
-
path: string,
|
|
24
|
-
baseUrl: string,
|
|
25
|
-
opts?: TestRequestOptions,
|
|
26
|
-
): Request {
|
|
21
|
+
function buildRequest(method: string, path: string, baseUrl: string, opts?: TestRequestOptions): Request {
|
|
27
22
|
const url = new URL(path, baseUrl)
|
|
28
23
|
|
|
29
24
|
if (opts?.search) {
|
|
@@ -70,11 +65,7 @@ export function testClient<TEnv>(
|
|
|
70
65
|
const baseUrl = "http://localhost"
|
|
71
66
|
const jar = new Map<string, string>()
|
|
72
67
|
|
|
73
|
-
async function doRequest(
|
|
74
|
-
method: string,
|
|
75
|
-
path: string,
|
|
76
|
-
opts?: TestRequestOptions,
|
|
77
|
-
): Promise<Response> {
|
|
68
|
+
async function doRequest(method: string, path: string, opts?: TestRequestOptions): Promise<Response> {
|
|
78
69
|
const mergedHeaders = { ...opts?.headers }
|
|
79
70
|
|
|
80
71
|
if (options.cookies && jar.size > 0) {
|
package/src/timeout.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { namedMiddleware } from "./middleware.ts"
|
|
1
2
|
import { HoneyError } from "./error.ts"
|
|
2
3
|
import type { MiddlewareFn } from "./middleware.ts"
|
|
3
4
|
import { EK, SK } from "./types.ts"
|
|
@@ -32,5 +33,5 @@ export function timeout(opts: TimeoutOptions): MiddlewareFn<{}, {}> {
|
|
|
32
33
|
})
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
return mw
|
|
36
|
+
return namedMiddleware("timeout", mw)
|
|
36
37
|
}
|
package/src/tree.ts
CHANGED
|
@@ -112,18 +112,12 @@ function splitSegments(path: string): string[] {
|
|
|
112
112
|
return path.split("/").filter((s) => s.length > 0)
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
export function insertRoute(
|
|
116
|
-
root: TreeNode,
|
|
117
|
-
method: HttpMethod | "ALL",
|
|
118
|
-
path: string,
|
|
119
|
-
handler: RouteHandler,
|
|
120
|
-
): void {
|
|
115
|
+
export function insertRoute(root: TreeNode, method: HttpMethod | "ALL", path: string, handler: RouteHandler): void {
|
|
121
116
|
bumpGeneration(root)
|
|
122
117
|
const segments = splitSegments(path)
|
|
123
118
|
let node = root
|
|
124
119
|
|
|
125
120
|
for (const seg of segments) {
|
|
126
|
-
|
|
127
121
|
if (seg.startsWith("*")) {
|
|
128
122
|
const name = seg.length > 1 ? seg.slice(1) : "*"
|
|
129
123
|
if (node.w !== null && node.w.n !== name) {
|
|
@@ -145,9 +139,7 @@ export function insertRoute(
|
|
|
145
139
|
if (seg.startsWith(":")) {
|
|
146
140
|
const name = seg.endsWith("?") ? seg.slice(1, -1) : seg.slice(1)
|
|
147
141
|
if (node.d !== null && node.d.n !== name) {
|
|
148
|
-
throw new Error(
|
|
149
|
-
`Route "${path}": param name conflict — expected ":${node.d.n}" but got ":${name}"`,
|
|
150
|
-
)
|
|
142
|
+
throw new Error(`Route "${path}": param name conflict — expected ":${node.d.n}" but got ":${name}"`)
|
|
151
143
|
}
|
|
152
144
|
if (node.d === null) {
|
|
153
145
|
node.d = { c: createNode(), n: name }
|
|
@@ -270,7 +262,6 @@ export function insertWsRoute(root: TreeNode, path: string, handler: WSRouteHand
|
|
|
270
262
|
let node = root
|
|
271
263
|
|
|
272
264
|
for (const seg of segments) {
|
|
273
|
-
|
|
274
265
|
if (seg.startsWith("*")) {
|
|
275
266
|
throw new Error("Wildcard segments not supported for WebSocket routes")
|
|
276
267
|
}
|
|
@@ -278,9 +269,7 @@ export function insertWsRoute(root: TreeNode, path: string, handler: WSRouteHand
|
|
|
278
269
|
if (seg.startsWith(":")) {
|
|
279
270
|
const name = seg.slice(1)
|
|
280
271
|
if (node.d !== null && node.d.n !== name) {
|
|
281
|
-
throw new Error(
|
|
282
|
-
`Route "${path}": param name conflict — expected ":${node.d.n}" but got ":${name}"`,
|
|
283
|
-
)
|
|
272
|
+
throw new Error(`Route "${path}": param name conflict — expected ":${node.d.n}" but got ":${name}"`)
|
|
284
273
|
}
|
|
285
274
|
if (node.d === null) {
|
|
286
275
|
node.d = { c: createNode(), n: name }
|
|
@@ -364,13 +353,13 @@ function mergeNodes(target: TreeNode, source: TreeNode, path: string): void {
|
|
|
364
353
|
}
|
|
365
354
|
|
|
366
355
|
/* merge static children — shallow-copy s to avoid mutating shared empty objects */
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
356
|
+
if (source.s && Object.keys(source.s).length > 0) {
|
|
357
|
+
let detached = false
|
|
358
|
+
for (const [seg, child] of Object.entries(source.s)) {
|
|
359
|
+
const targetChild = target.s[seg]
|
|
360
|
+
if (targetChild !== undefined) {
|
|
361
|
+
mergeNodes(targetChild, child, `${path}/${seg}`)
|
|
362
|
+
} else {
|
|
374
363
|
if (!detached) {
|
|
375
364
|
target.s = Object.assign(Object.create(null) as Record<string, TreeNode>, target.s)
|
|
376
365
|
detached = true
|
|
@@ -384,9 +373,7 @@ function mergeNodes(target: TreeNode, source: TreeNode, path: string): void {
|
|
|
384
373
|
if (source.d !== null && source.d !== undefined) {
|
|
385
374
|
if (target.d !== null && target.d !== undefined) {
|
|
386
375
|
if (target.d.n !== source.d.n) {
|
|
387
|
-
throw new Error(
|
|
388
|
-
`Merge conflict: param name mismatch at ${path}: "${target.d.n}" vs "${source.d.n}"`,
|
|
389
|
-
)
|
|
376
|
+
throw new Error(`Merge conflict: param name mismatch at ${path}: "${target.d.n}" vs "${source.d.n}"`)
|
|
390
377
|
}
|
|
391
378
|
mergeNodes(target.d.c, source.d.c, `${path}/:${target.d.n}`)
|
|
392
379
|
} else {
|
|
@@ -398,9 +385,7 @@ function mergeNodes(target: TreeNode, source: TreeNode, path: string): void {
|
|
|
398
385
|
if (source.w !== null && source.w !== undefined) {
|
|
399
386
|
if (target.w !== null && target.w !== undefined) {
|
|
400
387
|
if (target.w.n !== source.w.n) {
|
|
401
|
-
throw new Error(
|
|
402
|
-
`Merge conflict: wildcard name mismatch at ${path}: "${target.w.n}" vs "${source.w.n}"`,
|
|
403
|
-
)
|
|
388
|
+
throw new Error(`Merge conflict: wildcard name mismatch at ${path}: "${target.w.n}" vs "${source.w.n}"`)
|
|
404
389
|
}
|
|
405
390
|
for (const [method, handler] of Object.entries(source.w.m)) {
|
|
406
391
|
if (method in target.w.m) {
|
package/src/ts-type-emitter.ts
CHANGED
|
@@ -4,16 +4,75 @@ import type { IRSchema } from "./codegen-ir.ts"
|
|
|
4
4
|
|
|
5
5
|
/* TS keywords that are valid identifiers but require quoting as object property keys */
|
|
6
6
|
const TS_RESERVED = new Set([
|
|
7
|
-
"break",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
7
|
+
"break",
|
|
8
|
+
"case",
|
|
9
|
+
"catch",
|
|
10
|
+
"class",
|
|
11
|
+
"const",
|
|
12
|
+
"continue",
|
|
13
|
+
"debugger",
|
|
14
|
+
"default",
|
|
15
|
+
"delete",
|
|
16
|
+
"do",
|
|
17
|
+
"else",
|
|
18
|
+
"enum",
|
|
19
|
+
"export",
|
|
20
|
+
"extends",
|
|
21
|
+
"false",
|
|
22
|
+
"finally",
|
|
23
|
+
"for",
|
|
24
|
+
"function",
|
|
25
|
+
"if",
|
|
26
|
+
"import",
|
|
27
|
+
"in",
|
|
28
|
+
"instanceof",
|
|
29
|
+
"new",
|
|
30
|
+
"null",
|
|
31
|
+
"return",
|
|
32
|
+
"super",
|
|
33
|
+
"switch",
|
|
34
|
+
"this",
|
|
35
|
+
"throw",
|
|
36
|
+
"true",
|
|
37
|
+
"try",
|
|
38
|
+
"typeof",
|
|
39
|
+
"var",
|
|
40
|
+
"void",
|
|
41
|
+
"while",
|
|
42
|
+
"with",
|
|
43
|
+
"yield",
|
|
44
|
+
"let",
|
|
45
|
+
"static",
|
|
46
|
+
"implements",
|
|
47
|
+
"interface",
|
|
48
|
+
"package",
|
|
49
|
+
"private",
|
|
50
|
+
"protected",
|
|
51
|
+
"public",
|
|
52
|
+
"abstract",
|
|
53
|
+
"as",
|
|
54
|
+
"async",
|
|
55
|
+
"await",
|
|
56
|
+
"constructor",
|
|
57
|
+
"declare",
|
|
58
|
+
"from",
|
|
59
|
+
"get",
|
|
60
|
+
"infer",
|
|
61
|
+
"is",
|
|
62
|
+
"keyof",
|
|
63
|
+
"module",
|
|
64
|
+
"namespace",
|
|
65
|
+
"never",
|
|
66
|
+
"of",
|
|
67
|
+
"readonly",
|
|
68
|
+
"require",
|
|
69
|
+
"set",
|
|
70
|
+
"satisfies",
|
|
71
|
+
"symbol",
|
|
72
|
+
"type",
|
|
73
|
+
"unique",
|
|
74
|
+
"unknown",
|
|
75
|
+
"override",
|
|
17
76
|
])
|
|
18
77
|
|
|
19
78
|
export function irToTs(ir: IRSchema, depth = 0): string {
|
|
@@ -66,9 +125,7 @@ export function irToTs(ir: IRSchema, depth = 0): string {
|
|
|
66
125
|
|
|
67
126
|
function emitScalar(ir: Extract<IRSchema, { kind: "scalar" }>): string {
|
|
68
127
|
if (ir.enum) {
|
|
69
|
-
return ir.enum
|
|
70
|
-
.map((v) => (typeof v === "string" ? JSON.stringify(v) : String(v)))
|
|
71
|
-
.join(" | ")
|
|
128
|
+
return ir.enum.map((v) => (typeof v === "string" ? JSON.stringify(v) : String(v))).join(" | ")
|
|
72
129
|
}
|
|
73
130
|
|
|
74
131
|
if (ir.type === "string") return "string"
|
|
@@ -92,8 +149,7 @@ function emitObject(ir: Extract<IRSchema, { kind: "object" }>, depth: number): s
|
|
|
92
149
|
|
|
93
150
|
const entries = sortedFields.map((field) => {
|
|
94
151
|
const opt = field.required ? "" : "?"
|
|
95
|
-
const needsQuote =
|
|
96
|
-
!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(field.name) || TS_RESERVED.has(field.name)
|
|
152
|
+
const needsQuote = !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(field.name) || TS_RESERVED.has(field.name)
|
|
97
153
|
const key = needsQuote ? JSON.stringify(field.name) : field.name
|
|
98
154
|
return `${key}${opt}: ${irToTs(field.schema, depth + 1)}`
|
|
99
155
|
})
|