@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/plugin.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createHash } from "node:crypto"
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
3
|
-
import { dirname, extname, resolve } from "node:path"
|
|
1
|
+
import { createHash } from "node:crypto"
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
3
|
+
import { dirname, extname, resolve } from "node:path"
|
|
4
4
|
import {
|
|
5
5
|
generateManifest,
|
|
6
6
|
generateOpenApi,
|
|
@@ -10,28 +10,28 @@ import {
|
|
|
10
10
|
generateTypes,
|
|
11
11
|
prepareCodegen,
|
|
12
12
|
sanitizeOpenApiSpec,
|
|
13
|
-
} from "./codegen.ts"
|
|
14
|
-
import type { OpenApiRouteInfo, OpenApiSanitizeOptions, OpenApiSpecInput } from "./codegen.ts"
|
|
15
|
-
import type { Honey } from "./index.ts"
|
|
16
|
-
import type { ExtractedChainTypes } from "./type-extractor.ts"
|
|
17
|
-
import { toYaml, yamlSiblingPath } from "./yaml.ts"
|
|
13
|
+
} from "./codegen.ts"
|
|
14
|
+
import type { OpenApiRouteInfo, OpenApiSanitizeOptions, OpenApiSpecInput } from "./codegen.ts"
|
|
15
|
+
import type { Honey } from "./index.ts"
|
|
16
|
+
import type { ExtractedChainTypes } from "./type-extractor.ts"
|
|
17
|
+
import { toYaml, yamlSiblingPath } from "./yaml.ts"
|
|
18
18
|
|
|
19
19
|
/* ---- generateFromApp (standalone utility) ---- */
|
|
20
20
|
|
|
21
21
|
type HoneyPluginOptions = {
|
|
22
|
-
manifest?: { output: string }
|
|
22
|
+
manifest?: { output: string }
|
|
23
23
|
openApi?: {
|
|
24
|
-
info: { description?: string; title: string; version: string }
|
|
25
|
-
output: string
|
|
26
|
-
}
|
|
27
|
-
}
|
|
24
|
+
info: { description?: string; title: string; version: string }
|
|
25
|
+
output: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
28
|
|
|
29
29
|
type GeneratedArtifacts = {
|
|
30
|
-
manifest?: string
|
|
31
|
-
openApi?: string
|
|
32
|
-
openApiYaml?: string
|
|
33
|
-
routeTree: string
|
|
34
|
-
}
|
|
30
|
+
manifest?: string
|
|
31
|
+
openApi?: string
|
|
32
|
+
openApiYaml?: string
|
|
33
|
+
routeTree: string
|
|
34
|
+
}
|
|
35
35
|
|
|
36
36
|
export async function generateFromApp<
|
|
37
37
|
TEnv,
|
|
@@ -48,20 +48,20 @@ export async function generateFromApp<
|
|
|
48
48
|
const host = app as unknown as Honey<TEnv, TCtx, unknown, unknown, unknown, string, string>
|
|
49
49
|
const artifacts: GeneratedArtifacts = {
|
|
50
50
|
routeTree: generateRouteTreeFromApp(host),
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
|
|
53
53
|
if (options?.manifest) {
|
|
54
|
-
const manifest = generateManifest(host)
|
|
55
|
-
artifacts.manifest = JSON.stringify(manifest, null, 2)
|
|
54
|
+
const manifest = generateManifest(host)
|
|
55
|
+
artifacts.manifest = JSON.stringify(manifest, null, 2)
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (options?.openApi) {
|
|
59
|
-
const spec = await generateOpenApi(host, { info: options.openApi.info })
|
|
60
|
-
artifacts.openApi = JSON.stringify(spec, null, 2)
|
|
61
|
-
artifacts.openApiYaml = toYaml(spec)
|
|
59
|
+
const spec = await generateOpenApi(host, { info: options.openApi.info })
|
|
60
|
+
artifacts.openApi = JSON.stringify(spec, null, 2)
|
|
61
|
+
artifacts.openApiYaml = toYaml(spec)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
return artifacts
|
|
64
|
+
return artifacts
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/* ---- Config types ---- */
|
|
@@ -70,6 +70,8 @@ export interface HoneyOpenApiOutputConfig {
|
|
|
70
70
|
description?: string
|
|
71
71
|
filterRoutes?: (route: OpenApiRouteInfo) => boolean
|
|
72
72
|
path?: string
|
|
73
|
+
/** Named metaSpec profile selecting which emitted keys this document carries */
|
|
74
|
+
profile?: string
|
|
73
75
|
sanitize?: OpenApiSanitizeOptions
|
|
74
76
|
securitySchemes?: Record<string, unknown>
|
|
75
77
|
title: string
|
|
@@ -87,26 +89,26 @@ export interface HoneyGoCliConfig {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
export interface HoneySdkPortsConfig {
|
|
90
|
-
go?: { modulePath?: string; outDir: string }
|
|
91
|
-
python?: { outDir: string }
|
|
92
|
-
rust?: { crateName?: string; outDir: string }
|
|
93
|
-
typescript?: boolean | { outDir?: string }
|
|
92
|
+
go?: { modulePath?: string; outDir: string }
|
|
93
|
+
python?: { outDir: string }
|
|
94
|
+
rust?: { crateName?: string; outDir: string }
|
|
95
|
+
typescript?: boolean | { outDir?: string }
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
export interface HoneyCodegenConfig {
|
|
97
|
-
cli?: boolean | HoneyGoCliConfig
|
|
98
|
-
manifest?: boolean | string
|
|
99
|
-
mergeTree?: string
|
|
100
|
-
openApi?: HoneyOpenApiOutputConfig | HoneyOpenApiOutputConfig[]
|
|
101
|
-
sdk?: boolean | { name?: string; ports?: HoneySdkPortsConfig; specs?: string[] }
|
|
102
|
-
tree?: boolean | string
|
|
103
|
-
types?: boolean | string | { baseCtxName?: string; path?: string }
|
|
99
|
+
cli?: boolean | HoneyGoCliConfig
|
|
100
|
+
manifest?: boolean | string
|
|
101
|
+
mergeTree?: string
|
|
102
|
+
openApi?: HoneyOpenApiOutputConfig | HoneyOpenApiOutputConfig[]
|
|
103
|
+
sdk?: boolean | { name?: string; ports?: HoneySdkPortsConfig; specs?: string[] }
|
|
104
|
+
tree?: boolean | string
|
|
105
|
+
types?: boolean | string | { baseCtxName?: string; path?: string }
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
export interface HoneyVitePluginConfig {
|
|
107
|
-
app?: string
|
|
108
|
-
codegen?: HoneyCodegenConfig
|
|
109
|
-
watch?: string[]
|
|
109
|
+
app?: string
|
|
110
|
+
codegen?: HoneyCodegenConfig
|
|
111
|
+
watch?: string[]
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
/* ---- Resolved config ---- */
|
|
@@ -115,6 +117,8 @@ export type ResolvedOpenApiOutput = {
|
|
|
115
117
|
description?: string
|
|
116
118
|
filterRoutes?: (route: OpenApiRouteInfo) => boolean
|
|
117
119
|
path: string
|
|
120
|
+
/** Named metaSpec profile selecting which emitted keys this document carries */
|
|
121
|
+
profile?: string
|
|
118
122
|
sanitize?: OpenApiSanitizeOptions
|
|
119
123
|
securitySchemes?: Record<string, unknown>
|
|
120
124
|
title: string
|
|
@@ -132,88 +136,85 @@ export type ResolvedGoCliConfig = {
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
export type ResolvedSdkPorts = {
|
|
135
|
-
go?: { modulePath: string | undefined; outDir: string }
|
|
136
|
-
python?: { outDir: string }
|
|
137
|
-
rust?: { crateName: string | undefined; outDir: string }
|
|
138
|
-
typescript?: { outDir: string }
|
|
139
|
-
}
|
|
139
|
+
go?: { modulePath: string | undefined; outDir: string }
|
|
140
|
+
python?: { outDir: string }
|
|
141
|
+
rust?: { crateName: string | undefined; outDir: string }
|
|
142
|
+
typescript?: { outDir: string }
|
|
143
|
+
}
|
|
140
144
|
|
|
141
145
|
export interface ResolvedHoneyConfig {
|
|
142
|
-
app?: string
|
|
146
|
+
app?: string
|
|
143
147
|
codegen: {
|
|
144
|
-
cli: false | ResolvedGoCliConfig
|
|
145
|
-
manifest: false | string
|
|
146
|
-
mergeTree: string | undefined
|
|
147
|
-
openApi: false | ResolvedOpenApiOutput[]
|
|
148
|
-
sdk: false | { name: string; ports: ResolvedSdkPorts; specs?: string[] }
|
|
149
|
-
tree: false | string
|
|
150
|
-
types: false | { baseCtxName: string | undefined; path: string }
|
|
151
|
-
}
|
|
152
|
-
watch: string[]
|
|
148
|
+
cli: false | ResolvedGoCliConfig
|
|
149
|
+
manifest: false | string
|
|
150
|
+
mergeTree: string | undefined
|
|
151
|
+
openApi: false | ResolvedOpenApiOutput[]
|
|
152
|
+
sdk: false | { name: string; ports: ResolvedSdkPorts; specs?: string[] }
|
|
153
|
+
tree: false | string
|
|
154
|
+
types: false | { baseCtxName: string | undefined; path: string }
|
|
155
|
+
}
|
|
156
|
+
watch: string[]
|
|
153
157
|
}
|
|
154
158
|
|
|
155
|
-
export function resolveHoneyConfig(
|
|
156
|
-
raw
|
|
157
|
-
): ResolvedHoneyConfig {
|
|
158
|
-
const c = raw.codegen;
|
|
159
|
+
export function resolveHoneyConfig(raw: HoneyVitePluginConfig): ResolvedHoneyConfig {
|
|
160
|
+
const c = raw.codegen
|
|
159
161
|
|
|
160
162
|
const resolvePathFlag = (
|
|
161
163
|
val: boolean | string | undefined,
|
|
162
164
|
defaultPath: string,
|
|
163
165
|
defaultEnabled: boolean,
|
|
164
166
|
): false | string => {
|
|
165
|
-
if (val === false) return false
|
|
166
|
-
if (val === true || (val === undefined && defaultEnabled))
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
let types: false | { baseCtxName: string | undefined; path: string } = false;
|
|
167
|
+
if (val === false) return false
|
|
168
|
+
if (val === true || (val === undefined && defaultEnabled)) return defaultPath
|
|
169
|
+
if (typeof val === "string") return val
|
|
170
|
+
return false
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let types: false | { baseCtxName: string | undefined; path: string } = false
|
|
173
174
|
if (c?.types !== undefined && c.types !== false) {
|
|
174
175
|
if (typeof c.types === "string") {
|
|
175
|
-
types = { baseCtxName: undefined, path: c.types }
|
|
176
|
+
types = { baseCtxName: undefined, path: c.types }
|
|
176
177
|
} else if (c.types === true) {
|
|
177
|
-
types = { baseCtxName: undefined, path: "src/_gen/types.gen.d.ts" }
|
|
178
|
+
types = { baseCtxName: undefined, path: "src/_gen/types.gen.d.ts" }
|
|
178
179
|
} else {
|
|
179
180
|
types = {
|
|
180
181
|
baseCtxName: c.types.baseCtxName,
|
|
181
182
|
path: c.types.path ?? "src/_gen/types.gen.d.ts",
|
|
182
|
-
}
|
|
183
|
+
}
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
|
|
186
|
-
let sdk: false | { name: string; ports: ResolvedSdkPorts; specs?: string[] } = false
|
|
187
|
+
let sdk: false | { name: string; ports: ResolvedSdkPorts; specs?: string[] } = false
|
|
187
188
|
if (c?.sdk !== undefined && c.sdk !== false) {
|
|
188
189
|
if (typeof c.sdk === "string") {
|
|
189
190
|
throw new Error("codegen.sdk string form removed — pass object { name?, specs?, ports }")
|
|
190
191
|
}
|
|
191
192
|
if (c.sdk === true) {
|
|
192
|
-
sdk = { name: "SDK", ports: { typescript: { outDir: "src/_gen" } } }
|
|
193
|
+
sdk = { name: "SDK", ports: { typescript: { outDir: "src/_gen" } } }
|
|
193
194
|
} else {
|
|
194
|
-
const rawPorts = c.sdk.ports ?? { typescript: true }
|
|
195
|
-
const ports: ResolvedSdkPorts = {}
|
|
195
|
+
const rawPorts = c.sdk.ports ?? { typescript: true }
|
|
196
|
+
const ports: ResolvedSdkPorts = {}
|
|
196
197
|
if (rawPorts.typescript !== undefined && rawPorts.typescript !== false) {
|
|
197
198
|
if (rawPorts.typescript === true) {
|
|
198
|
-
ports.typescript = { outDir: "src/_gen" }
|
|
199
|
+
ports.typescript = { outDir: "src/_gen" }
|
|
199
200
|
} else {
|
|
200
|
-
ports.typescript = { outDir: rawPorts.typescript.outDir ?? "src/_gen" }
|
|
201
|
+
ports.typescript = { outDir: rawPorts.typescript.outDir ?? "src/_gen" }
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
if (rawPorts.python) {
|
|
204
|
-
ports.python = { outDir: rawPorts.python.outDir }
|
|
205
|
+
ports.python = { outDir: rawPorts.python.outDir }
|
|
205
206
|
}
|
|
206
207
|
if (rawPorts.go) {
|
|
207
|
-
ports.go = { modulePath: rawPorts.go.modulePath, outDir: rawPorts.go.outDir }
|
|
208
|
+
ports.go = { modulePath: rawPorts.go.modulePath, outDir: rawPorts.go.outDir }
|
|
208
209
|
}
|
|
209
210
|
if (rawPorts.rust) {
|
|
210
|
-
ports.rust = { crateName: rawPorts.rust.crateName, outDir: rawPorts.rust.outDir }
|
|
211
|
+
ports.rust = { crateName: rawPorts.rust.crateName, outDir: rawPorts.rust.outDir }
|
|
211
212
|
}
|
|
212
213
|
sdk = {
|
|
213
214
|
name: c.sdk.name ?? "SDK",
|
|
214
215
|
ports,
|
|
215
216
|
specs: c.sdk.specs,
|
|
216
|
-
}
|
|
217
|
+
}
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
|
|
@@ -224,6 +225,7 @@ export function resolveHoneyConfig(
|
|
|
224
225
|
description: entry.description,
|
|
225
226
|
filterRoutes: entry.filterRoutes,
|
|
226
227
|
path: entry.path ?? "src/_gen/openapi.gen.json",
|
|
228
|
+
profile: entry.profile,
|
|
227
229
|
sanitize: entry.sanitize,
|
|
228
230
|
securitySchemes: entry.securitySchemes,
|
|
229
231
|
title: entry.title,
|
|
@@ -234,9 +236,7 @@ export function resolveHoneyConfig(
|
|
|
234
236
|
let cli: false | ResolvedGoCliConfig = false
|
|
235
237
|
if (c?.cli !== undefined && c.cli !== false) {
|
|
236
238
|
if (c.cli === true) {
|
|
237
|
-
throw new Error(
|
|
238
|
-
"codegen.cli=true requires `out` and `binaryName` — pass an object { out, binaryName }",
|
|
239
|
-
)
|
|
239
|
+
throw new Error("codegen.cli=true requires `out` and `binaryName` — pass an object { out, binaryName }")
|
|
240
240
|
}
|
|
241
241
|
if (!c.cli.out || !c.cli.binaryName) {
|
|
242
242
|
throw new Error("codegen.cli requires `out` and `binaryName`")
|
|
@@ -256,11 +256,7 @@ export function resolveHoneyConfig(
|
|
|
256
256
|
app: raw.app,
|
|
257
257
|
codegen: {
|
|
258
258
|
cli,
|
|
259
|
-
manifest: resolvePathFlag(
|
|
260
|
-
c?.manifest,
|
|
261
|
-
"src/_gen/manifest.gen.json",
|
|
262
|
-
false,
|
|
263
|
-
),
|
|
259
|
+
manifest: resolvePathFlag(c?.manifest, "src/_gen/manifest.gen.json", false),
|
|
264
260
|
mergeTree: c?.mergeTree,
|
|
265
261
|
openApi,
|
|
266
262
|
sdk,
|
|
@@ -268,60 +264,61 @@ export function resolveHoneyConfig(
|
|
|
268
264
|
types,
|
|
269
265
|
},
|
|
270
266
|
watch: raw.watch ?? [],
|
|
271
|
-
}
|
|
267
|
+
}
|
|
272
268
|
}
|
|
273
269
|
|
|
274
270
|
/* ---- Config stash for CLI ---- */
|
|
275
271
|
|
|
276
|
-
let _lastConfig: HoneyVitePluginConfig | undefined
|
|
272
|
+
let _lastConfig: HoneyVitePluginConfig | undefined
|
|
277
273
|
|
|
278
274
|
export function getLastHoneyConfig(): HoneyVitePluginConfig | undefined {
|
|
279
|
-
return _lastConfig
|
|
275
|
+
return _lastConfig
|
|
280
276
|
}
|
|
281
277
|
|
|
282
278
|
/* ---- writeGenFile / writeGenJsonFile ---- */
|
|
283
279
|
|
|
284
280
|
function writeGenFile(filePath: string, body: string, generator: string): boolean {
|
|
285
|
-
const normalized = body.replace(/\n*$/, "\n")
|
|
286
|
-
const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12)
|
|
281
|
+
const normalized = body.replace(/\n*$/, "\n")
|
|
282
|
+
const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12)
|
|
287
283
|
|
|
288
|
-
const ext = filePath.endsWith(".d.ts") ? ".d.ts" : extname(filePath)
|
|
289
|
-
const header =
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
284
|
+
const ext = filePath.endsWith(".d.ts") ? ".d.ts" : extname(filePath)
|
|
285
|
+
const header =
|
|
286
|
+
ext === ".sql"
|
|
287
|
+
? `-- @generated by ${generator} — do not edit. checksum: ${hash}`
|
|
288
|
+
: `/* @generated by ${generator} — do not edit. checksum: ${hash} */`
|
|
289
|
+
const fullContent = `${header}\n${normalized}`
|
|
293
290
|
|
|
294
291
|
if (existsSync(filePath)) {
|
|
295
|
-
const existing = readFileSync(filePath, "utf-8")
|
|
296
|
-
const firstLine = existing.split("\n")[0] ?? ""
|
|
297
|
-
const match = firstLine.match(/checksum: ([0-9a-f]{12})/)
|
|
298
|
-
if (match?.[1] === hash) return false
|
|
292
|
+
const existing = readFileSync(filePath, "utf-8")
|
|
293
|
+
const firstLine = existing.split("\n")[0] ?? ""
|
|
294
|
+
const match = firstLine.match(/checksum: ([0-9a-f]{12})/)
|
|
295
|
+
if (match?.[1] === hash) return false
|
|
299
296
|
}
|
|
300
297
|
|
|
301
|
-
mkdirSync(dirname(filePath), { recursive: true })
|
|
302
|
-
writeFileSync(filePath, fullContent, "utf-8")
|
|
303
|
-
return true
|
|
298
|
+
mkdirSync(dirname(filePath), { recursive: true })
|
|
299
|
+
writeFileSync(filePath, fullContent, "utf-8")
|
|
300
|
+
return true
|
|
304
301
|
}
|
|
305
302
|
|
|
306
303
|
function writeGenJsonFile(filePath: string, data: unknown, generator: string): boolean {
|
|
307
|
-
const json = JSON.stringify(data, null, 2)
|
|
308
|
-
const hash = createHash("sha256").update(json).digest("hex").slice(0, 12)
|
|
309
|
-
const marker = `${generator} checksum:${hash}
|
|
304
|
+
const json = JSON.stringify(data, null, 2)
|
|
305
|
+
const hash = createHash("sha256").update(json).digest("hex").slice(0, 12)
|
|
306
|
+
const marker = `${generator} checksum:${hash}`
|
|
310
307
|
|
|
311
308
|
if (existsSync(filePath)) {
|
|
312
309
|
try {
|
|
313
|
-
const existing = readFileSync(filePath, "utf-8")
|
|
314
|
-
const parsed = JSON.parse(existing) as Record<string, unknown
|
|
315
|
-
if (parsed._generated === marker) return false
|
|
310
|
+
const existing = readFileSync(filePath, "utf-8")
|
|
311
|
+
const parsed = JSON.parse(existing) as Record<string, unknown>
|
|
312
|
+
if (parsed._generated === marker) return false
|
|
316
313
|
} catch {
|
|
317
314
|
/* invalid JSON — proceed to write */
|
|
318
315
|
}
|
|
319
316
|
}
|
|
320
317
|
|
|
321
|
-
const output = { _generated: marker, ...(data as Record<string, unknown>) }
|
|
322
|
-
mkdirSync(dirname(filePath), { recursive: true })
|
|
323
|
-
writeFileSync(filePath, `${JSON.stringify(output, null, 2)}\n`, "utf-8")
|
|
324
|
-
return true
|
|
318
|
+
const output = { _generated: marker, ...(data as Record<string, unknown>) }
|
|
319
|
+
mkdirSync(dirname(filePath), { recursive: true })
|
|
320
|
+
writeFileSync(filePath, `${JSON.stringify(output, null, 2)}\n`, "utf-8")
|
|
321
|
+
return true
|
|
325
322
|
}
|
|
326
323
|
|
|
327
324
|
function writeGenYamlFile(filePath: string, data: unknown, generator: string): boolean {
|
|
@@ -343,78 +340,65 @@ function writeGenYamlFile(filePath: string, data: unknown, generator: string): b
|
|
|
343
340
|
|
|
344
341
|
/* ---- Loaders ---- */
|
|
345
342
|
|
|
346
|
-
type HoneyApp = Honey<
|
|
347
|
-
|
|
348
|
-
unknown,
|
|
349
|
-
unknown,
|
|
350
|
-
unknown,
|
|
351
|
-
unknown,
|
|
352
|
-
string,
|
|
353
|
-
string
|
|
354
|
-
>;
|
|
355
|
-
type TreeResult = { root: import("./tree.ts").TreeNode };
|
|
343
|
+
type HoneyApp = Honey<unknown, unknown, unknown, unknown, unknown, string, string>
|
|
344
|
+
type TreeResult = { root: import("./tree.ts").TreeNode }
|
|
356
345
|
|
|
357
346
|
async function loadDefaultWithJiti(entryPath: string): Promise<unknown> {
|
|
358
|
-
const { createJiti } = await import("jiti")
|
|
359
|
-
const jiti = createJiti(entryPath, { fsCache: false, interopDefault: true, moduleCache: false })
|
|
360
|
-
const mod = (await jiti.import(entryPath)) as Record<string, unknown
|
|
347
|
+
const { createJiti } = await import("jiti")
|
|
348
|
+
const jiti = createJiti(entryPath, { fsCache: false, interopDefault: true, moduleCache: false })
|
|
349
|
+
const mod = (await jiti.import(entryPath)) as Record<string, unknown>
|
|
361
350
|
|
|
362
351
|
/* prefer named exports, then unwrap interop default */
|
|
363
|
-
if (mod.app && isHoneyApp(mod.app)) return mod.app
|
|
364
|
-
if (mod.tree && isRouteTree(mod.tree)) return mod.tree
|
|
352
|
+
if (mod.app && isHoneyApp(mod.app)) return mod.app
|
|
353
|
+
if (mod.tree && isRouteTree(mod.tree)) return mod.tree
|
|
365
354
|
if (mod.default) {
|
|
366
|
-
const def = mod.default as Record<string, unknown
|
|
355
|
+
const def = mod.default as Record<string, unknown>
|
|
367
356
|
/* interopDefault may wrap: { default: { app: Honey } } */
|
|
368
|
-
if (isHoneyApp(def)) return def
|
|
369
|
-
if (isRouteTree(def)) return def
|
|
370
|
-
if (def.app && isHoneyApp(def.app)) return def.app
|
|
371
|
-
if (def.tree && isRouteTree(def.tree)) return def.tree
|
|
357
|
+
if (isHoneyApp(def)) return def
|
|
358
|
+
if (isRouteTree(def)) return def
|
|
359
|
+
if (def.app && isHoneyApp(def.app)) return def.app
|
|
360
|
+
if (def.tree && isRouteTree(def.tree)) return def.tree
|
|
372
361
|
}
|
|
373
|
-
return undefined
|
|
362
|
+
return undefined
|
|
374
363
|
}
|
|
375
364
|
|
|
376
365
|
function isHoneyApp(val: unknown): val is HoneyApp {
|
|
377
|
-
if (val === null || typeof val !== "object") return false
|
|
378
|
-
return typeof (val as Record<string, unknown>).fetch === "function"
|
|
366
|
+
if (val === null || typeof val !== "object") return false
|
|
367
|
+
return typeof (val as Record<string, unknown>).fetch === "function"
|
|
379
368
|
}
|
|
380
369
|
|
|
381
370
|
function isRouteTree(val: unknown): val is TreeResult {
|
|
382
|
-
if (val === null || typeof val !== "object") return false
|
|
383
|
-
const obj = val as Record<string, unknown
|
|
384
|
-
return obj.root !== undefined && typeof obj.root === "object"
|
|
371
|
+
if (val === null || typeof val !== "object") return false
|
|
372
|
+
const obj = val as Record<string, unknown>
|
|
373
|
+
return obj.root !== undefined && typeof obj.root === "object"
|
|
385
374
|
}
|
|
386
375
|
|
|
387
376
|
/* ---- Generation ---- */
|
|
388
377
|
|
|
389
|
-
export async function generateAndWrite(
|
|
390
|
-
config: ResolvedHoneyConfig,
|
|
391
|
-
root: string,
|
|
392
|
-
): Promise<void> {
|
|
378
|
+
export async function generateAndWrite(config: ResolvedHoneyConfig, root: string): Promise<void> {
|
|
393
379
|
await prepareCodegen()
|
|
394
|
-
const cg = config.codegen
|
|
380
|
+
const cg = config.codegen
|
|
395
381
|
|
|
396
382
|
/* phase 1: route tree — from mergeTree source or app */
|
|
397
383
|
if (cg.tree && (cg.mergeTree || config.app)) {
|
|
398
|
-
const treeSrc = resolve(root, cg.mergeTree ?? config.app ?? "")
|
|
399
|
-
const exported = await loadDefaultWithJiti(treeSrc)
|
|
384
|
+
const treeSrc = resolve(root, cg.mergeTree ?? config.app ?? "")
|
|
385
|
+
const exported = await loadDefaultWithJiti(treeSrc)
|
|
400
386
|
|
|
401
|
-
let treeCode: string
|
|
387
|
+
let treeCode: string
|
|
402
388
|
if (isHoneyApp(exported)) {
|
|
403
|
-
treeCode = generateRouteTreeFromApp(exported)
|
|
389
|
+
treeCode = generateRouteTreeFromApp(exported)
|
|
404
390
|
} else if (isRouteTree(exported)) {
|
|
405
|
-
treeCode = generateRouteTreeFromRouteTree(exported)
|
|
391
|
+
treeCode = generateRouteTreeFromRouteTree(exported)
|
|
406
392
|
} else {
|
|
407
|
-
throw new Error(
|
|
408
|
-
`Expected Honey app or RouteTree default export in ${treeSrc}`,
|
|
409
|
-
);
|
|
393
|
+
throw new Error(`Expected Honey app or RouteTree default export in ${treeSrc}`)
|
|
410
394
|
}
|
|
411
395
|
|
|
412
|
-
writeGenFile(resolve(root, cg.tree), treeCode, "honey")
|
|
396
|
+
writeGenFile(resolve(root, cg.tree), treeCode, "honey")
|
|
413
397
|
}
|
|
414
398
|
|
|
415
399
|
/* phase 2: types, manifest, openapi, sdk, cli — app needed unless sdk has specs */
|
|
416
400
|
const sdkHasSpecs = cg.sdk && cg.sdk.specs && cg.sdk.specs.length > 0
|
|
417
|
-
const needsApp = cg.types || cg.manifest || cg.openApi || (cg.sdk && !sdkHasSpecs) || cg.cli
|
|
401
|
+
const needsApp = cg.types || cg.manifest || cg.openApi || (cg.sdk && !sdkHasSpecs) || cg.cli
|
|
418
402
|
|
|
419
403
|
let app: HoneyApp | undefined
|
|
420
404
|
let appPath: string | undefined
|
|
@@ -422,19 +406,19 @@ export async function generateAndWrite(
|
|
|
422
406
|
if (!config.app) {
|
|
423
407
|
throw new Error("No app configured — required for types/manifest/openapi/sdk without specs/cli")
|
|
424
408
|
}
|
|
425
|
-
appPath = resolve(root, config.app)
|
|
426
|
-
const appExported = await loadDefaultWithJiti(appPath)
|
|
409
|
+
appPath = resolve(root, config.app)
|
|
410
|
+
const appExported = await loadDefaultWithJiti(appPath)
|
|
427
411
|
if (!isHoneyApp(appExported)) {
|
|
428
|
-
throw new Error(`Expected Honey app default export in ${appPath}`)
|
|
412
|
+
throw new Error(`Expected Honey app default export in ${appPath}`)
|
|
429
413
|
}
|
|
430
|
-
app = appExported
|
|
414
|
+
app = appExported
|
|
431
415
|
}
|
|
432
416
|
|
|
433
417
|
/* manifest */
|
|
434
418
|
if (cg.manifest) {
|
|
435
419
|
if (!app) throw new Error("Manifest generation requires a configured app")
|
|
436
|
-
const manifest = generateManifest(app)
|
|
437
|
-
writeGenJsonFile(resolve(root, cg.manifest), manifest, "honey")
|
|
420
|
+
const manifest = generateManifest(app)
|
|
421
|
+
writeGenJsonFile(resolve(root, cg.manifest), manifest, "honey")
|
|
438
422
|
}
|
|
439
423
|
|
|
440
424
|
/* openapi */
|
|
@@ -448,10 +432,11 @@ export async function generateAndWrite(
|
|
|
448
432
|
title: entry.title,
|
|
449
433
|
version: entry.version,
|
|
450
434
|
},
|
|
435
|
+
profile: entry.profile,
|
|
451
436
|
securitySchemes: entry.securitySchemes,
|
|
452
|
-
})
|
|
437
|
+
})
|
|
453
438
|
if (entry.sanitize) {
|
|
454
|
-
spec = sanitizeOpenApiSpec(spec, entry.sanitize)
|
|
439
|
+
spec = sanitizeOpenApiSpec(spec, entry.sanitize)
|
|
455
440
|
}
|
|
456
441
|
const jsonPath = resolve(root, entry.path)
|
|
457
442
|
writeGenJsonFile(jsonPath, spec, "honey")
|
|
@@ -461,34 +446,30 @@ export async function generateAndWrite(
|
|
|
461
446
|
|
|
462
447
|
/* types */
|
|
463
448
|
if (cg.types) {
|
|
464
|
-
const typesPath = resolve(root, cg.types.path)
|
|
465
|
-
const typesDir = dirname(typesPath)
|
|
449
|
+
const typesPath = resolve(root, cg.types.path)
|
|
450
|
+
const typesDir = dirname(typesPath)
|
|
466
451
|
|
|
467
452
|
if (!appPath) {
|
|
468
453
|
throw new Error("Type generation requires a configured app")
|
|
469
454
|
}
|
|
470
|
-
const { extractChainTypes } = await import("./type-extractor.ts").catch(
|
|
471
|
-
(
|
|
472
|
-
|
|
473
|
-
'Type generation requires "ts-morph" — install it as a dev dependency',
|
|
474
|
-
);
|
|
475
|
-
},
|
|
476
|
-
);
|
|
455
|
+
const { extractChainTypes } = await import("./type-extractor.ts").catch(() => {
|
|
456
|
+
throw new Error('Type generation requires "ts-morph" — install it as a dev dependency')
|
|
457
|
+
})
|
|
477
458
|
|
|
478
459
|
/* prefer appBase (middleware-only, simpler type) over app (with routes) */
|
|
479
|
-
let extracted: ExtractedChainTypes
|
|
460
|
+
let extracted: ExtractedChainTypes
|
|
480
461
|
try {
|
|
481
462
|
extracted = await extractChainTypes({
|
|
482
463
|
entryPath: appPath,
|
|
483
464
|
exportName: "appBase",
|
|
484
465
|
outputDir: typesDir,
|
|
485
|
-
})
|
|
466
|
+
})
|
|
486
467
|
} catch {
|
|
487
468
|
extracted = await extractChainTypes({
|
|
488
469
|
entryPath: appPath,
|
|
489
470
|
exportName: "app",
|
|
490
471
|
outputDir: typesDir,
|
|
491
|
-
})
|
|
472
|
+
})
|
|
492
473
|
}
|
|
493
474
|
|
|
494
475
|
if (!app) throw new Error("Type generation requires a configured app")
|
|
@@ -499,15 +480,13 @@ export async function generateAndWrite(
|
|
|
499
480
|
inlineTapsType: extracted.base.tapsType,
|
|
500
481
|
routeMiddleware: extracted.routeMiddleware,
|
|
501
482
|
routeMiddlewareProps: extracted.routeMiddlewareProps,
|
|
502
|
-
})
|
|
503
|
-
writeGenFile(typesPath, typesCode, "honey")
|
|
483
|
+
})
|
|
484
|
+
writeGenFile(typesPath, typesCode, "honey")
|
|
504
485
|
}
|
|
505
486
|
|
|
506
487
|
/* sdk */
|
|
507
488
|
if (cg.sdk) {
|
|
508
|
-
const { generateOpenApi: genOA, generateSDK: genSDK, mergeSpecs } = await import(
|
|
509
|
-
"./codegen.ts"
|
|
510
|
-
);
|
|
489
|
+
const { generateOpenApi: genOA, generateSDK: genSDK, mergeSpecs } = await import("./codegen.ts")
|
|
511
490
|
|
|
512
491
|
let spec: OpenApiSpecInput
|
|
513
492
|
if (cg.sdk.specs && cg.sdk.specs.length > 0) {
|
|
@@ -521,8 +500,8 @@ export async function generateAndWrite(
|
|
|
521
500
|
const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
|
|
522
501
|
const info = primaryOA
|
|
523
502
|
? { title: primaryOA.title, version: primaryOA.version }
|
|
524
|
-
: { title: "API", version: "1.0.0" }
|
|
525
|
-
spec = await genOA(app, { info })
|
|
503
|
+
: { title: "API", version: "1.0.0" }
|
|
504
|
+
spec = await genOA(app, { info })
|
|
526
505
|
}
|
|
527
506
|
|
|
528
507
|
const ports = cg.sdk.ports
|
|
@@ -578,9 +557,7 @@ export async function generateAndWrite(
|
|
|
578
557
|
const { generateGoCLI } = await import("./codegen-go-cli.ts")
|
|
579
558
|
|
|
580
559
|
const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
|
|
581
|
-
const info = primaryOA
|
|
582
|
-
? { title: primaryOA.title, version: primaryOA.version }
|
|
583
|
-
: { title: "API", version: "1.0.0" }
|
|
560
|
+
const info = primaryOA ? { title: primaryOA.title, version: primaryOA.version } : { title: "API", version: "1.0.0" }
|
|
584
561
|
if (!app) throw new Error("CLI generation requires a configured app")
|
|
585
562
|
const spec = await generateOpenApi(app, { info })
|
|
586
563
|
|
|
@@ -604,114 +581,112 @@ export async function generateAndWrite(
|
|
|
604
581
|
|
|
605
582
|
/* ---- Vite plugin ---- */
|
|
606
583
|
|
|
607
|
-
const VIRTUAL_ROUTES = "virtual:honey/routes"
|
|
608
|
-
const VIRTUAL_MANIFEST = "virtual:honey/manifest"
|
|
609
|
-
const VIRTUAL_OPENAPI = "virtual:honey/openapi"
|
|
610
|
-
const RESOLVED_ROUTES = `\0${VIRTUAL_ROUTES}
|
|
611
|
-
const RESOLVED_MANIFEST = `\0${VIRTUAL_MANIFEST}
|
|
612
|
-
const RESOLVED_OPENAPI = `\0${VIRTUAL_OPENAPI}
|
|
584
|
+
const VIRTUAL_ROUTES = "virtual:honey/routes"
|
|
585
|
+
const VIRTUAL_MANIFEST = "virtual:honey/manifest"
|
|
586
|
+
const VIRTUAL_OPENAPI = "virtual:honey/openapi"
|
|
587
|
+
const RESOLVED_ROUTES = `\0${VIRTUAL_ROUTES}`
|
|
588
|
+
const RESOLVED_MANIFEST = `\0${VIRTUAL_MANIFEST}`
|
|
589
|
+
const RESOLVED_OPENAPI = `\0${VIRTUAL_OPENAPI}`
|
|
613
590
|
|
|
614
591
|
function matchesGlob(filePath: string, patterns: string[]): boolean {
|
|
615
592
|
for (const pattern of patterns) {
|
|
616
593
|
const re = pattern
|
|
617
594
|
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
618
595
|
.replace(/\*\*\//g, "(.+/)?")
|
|
619
|
-
.replace(/\*/g, "[^/]*")
|
|
620
|
-
if (new RegExp(`(^|/)${re}$`).test(filePath)) return true
|
|
596
|
+
.replace(/\*/g, "[^/]*")
|
|
597
|
+
if (new RegExp(`(^|/)${re}$`).test(filePath)) return true
|
|
621
598
|
}
|
|
622
|
-
return false
|
|
599
|
+
return false
|
|
623
600
|
}
|
|
624
601
|
|
|
625
602
|
export function honey(config: HoneyVitePluginConfig) {
|
|
626
|
-
_lastConfig = config
|
|
603
|
+
_lastConfig = config
|
|
627
604
|
|
|
628
|
-
const resolved = resolveHoneyConfig(config)
|
|
605
|
+
const resolved = resolveHoneyConfig(config)
|
|
629
606
|
|
|
630
|
-
let root = ""
|
|
607
|
+
let root = ""
|
|
631
608
|
|
|
632
609
|
const plugin: {
|
|
633
|
-
buildStart(): Promise<void
|
|
634
|
-
configResolved(cfg: { root: string }): void
|
|
610
|
+
buildStart(): Promise<void>
|
|
611
|
+
configResolved(cfg: { root: string }): void
|
|
635
612
|
hotUpdate(ctx: {
|
|
636
|
-
file: string
|
|
637
|
-
modules: unknown[]
|
|
613
|
+
file: string
|
|
614
|
+
modules: unknown[]
|
|
638
615
|
server: {
|
|
639
|
-
moduleGraph: { getModuleById(id: string): unknown }
|
|
640
|
-
reloadModule(mod: unknown): void
|
|
641
|
-
}
|
|
642
|
-
}): Promise<unknown[] | undefined
|
|
643
|
-
load(id: string): Promise<{ code: string; moduleType: string } | undefined
|
|
644
|
-
name: string
|
|
645
|
-
resolveId(id: string): string | undefined
|
|
646
|
-
transform(code: string, id: string): { code: string; map: null } | undefined
|
|
616
|
+
moduleGraph: { getModuleById(id: string): unknown }
|
|
617
|
+
reloadModule(mod: unknown): void
|
|
618
|
+
}
|
|
619
|
+
}): Promise<unknown[] | undefined>
|
|
620
|
+
load(id: string): Promise<{ code: string; moduleType: string } | undefined>
|
|
621
|
+
name: string
|
|
622
|
+
resolveId(id: string): string | undefined
|
|
623
|
+
transform(code: string, id: string): { code: string; map: null } | undefined
|
|
647
624
|
} = {
|
|
648
625
|
async buildStart() {
|
|
649
|
-
await generateAndWrite(resolved, root)
|
|
626
|
+
await generateAndWrite(resolved, root)
|
|
650
627
|
},
|
|
651
628
|
|
|
652
629
|
configResolved(cfg: { root: string }) {
|
|
653
|
-
root = cfg.root
|
|
630
|
+
root = cfg.root
|
|
654
631
|
},
|
|
655
632
|
|
|
656
633
|
async hotUpdate(ctx: {
|
|
657
|
-
file: string
|
|
658
|
-
modules: unknown[]
|
|
634
|
+
file: string
|
|
635
|
+
modules: unknown[]
|
|
659
636
|
server: {
|
|
660
|
-
moduleGraph: { getModuleById(id: string): unknown }
|
|
661
|
-
reloadModule(mod: unknown): void
|
|
662
|
-
}
|
|
637
|
+
moduleGraph: { getModuleById(id: string): unknown }
|
|
638
|
+
reloadModule(mod: unknown): void
|
|
639
|
+
}
|
|
663
640
|
}) {
|
|
664
|
-
const patterns = config.watch
|
|
665
|
-
if (!patterns || patterns.length === 0) return
|
|
666
|
-
if (!matchesGlob(ctx.file, patterns)) return
|
|
641
|
+
const patterns = config.watch
|
|
642
|
+
if (!patterns || patterns.length === 0) return
|
|
643
|
+
if (!matchesGlob(ctx.file, patterns)) return
|
|
667
644
|
|
|
668
|
-
await generateAndWrite(resolved, root)
|
|
645
|
+
await generateAndWrite(resolved, root)
|
|
669
646
|
|
|
670
|
-
const mod = ctx.server.moduleGraph.getModuleById(RESOLVED_ROUTES)
|
|
647
|
+
const mod = ctx.server.moduleGraph.getModuleById(RESOLVED_ROUTES)
|
|
671
648
|
if (mod) {
|
|
672
|
-
ctx.server.reloadModule(mod)
|
|
649
|
+
ctx.server.reloadModule(mod)
|
|
673
650
|
}
|
|
674
|
-
return []
|
|
651
|
+
return []
|
|
675
652
|
},
|
|
676
653
|
|
|
677
|
-
async load(
|
|
678
|
-
id: string,
|
|
679
|
-
): Promise<{ code: string; moduleType: string } | undefined> {
|
|
654
|
+
async load(id: string): Promise<{ code: string; moduleType: string } | undefined> {
|
|
680
655
|
if (id === RESOLVED_ROUTES) {
|
|
681
656
|
if (!resolved.codegen.mergeTree && !config.app) {
|
|
682
657
|
throw new Error("Route tree virtual module requires app or mergeTree")
|
|
683
658
|
}
|
|
684
659
|
const treeSrc = resolved.codegen.mergeTree
|
|
685
660
|
? resolve(root, resolved.codegen.mergeTree)
|
|
686
|
-
: resolve(root, config.app ?? "")
|
|
687
|
-
const exported = await loadDefaultWithJiti(treeSrc)
|
|
688
|
-
let code: string
|
|
661
|
+
: resolve(root, config.app ?? "")
|
|
662
|
+
const exported = await loadDefaultWithJiti(treeSrc)
|
|
663
|
+
let code: string
|
|
689
664
|
if (isHoneyApp(exported)) {
|
|
690
|
-
code = generateRouteTreeFromApp(exported)
|
|
665
|
+
code = generateRouteTreeFromApp(exported)
|
|
691
666
|
} else if (isRouteTree(exported)) {
|
|
692
|
-
code = generateRouteTreeFromRouteTree(exported)
|
|
667
|
+
code = generateRouteTreeFromRouteTree(exported)
|
|
693
668
|
} else {
|
|
694
|
-
throw new Error(`Expected Honey app or RouteTree in ${treeSrc}`)
|
|
669
|
+
throw new Error(`Expected Honey app or RouteTree in ${treeSrc}`)
|
|
695
670
|
}
|
|
696
|
-
return { code, moduleType: "js" }
|
|
671
|
+
return { code, moduleType: "js" }
|
|
697
672
|
}
|
|
698
673
|
if (id === RESOLVED_MANIFEST && resolved.codegen.manifest) {
|
|
699
674
|
if (!config.app) throw new Error("Manifest virtual module requires app")
|
|
700
|
-
const appPath = resolve(root, config.app)
|
|
701
|
-
const exported = await loadDefaultWithJiti(appPath)
|
|
675
|
+
const appPath = resolve(root, config.app)
|
|
676
|
+
const exported = await loadDefaultWithJiti(appPath)
|
|
702
677
|
if (isHoneyApp(exported)) {
|
|
703
|
-
const manifest = generateManifest(exported)
|
|
678
|
+
const manifest = generateManifest(exported)
|
|
704
679
|
return {
|
|
705
680
|
code: `export default ${JSON.stringify(manifest, null, 2)};`,
|
|
706
681
|
moduleType: "js",
|
|
707
|
-
}
|
|
682
|
+
}
|
|
708
683
|
}
|
|
709
684
|
}
|
|
710
685
|
if (id === RESOLVED_OPENAPI && resolved.codegen.openApi) {
|
|
711
686
|
const primary = resolved.codegen.openApi[0]
|
|
712
687
|
if (!config.app) throw new Error("OpenAPI virtual module requires app")
|
|
713
|
-
const appPath = resolve(root, config.app)
|
|
714
|
-
const exported = await loadDefaultWithJiti(appPath)
|
|
688
|
+
const appPath = resolve(root, config.app)
|
|
689
|
+
const exported = await loadDefaultWithJiti(appPath)
|
|
715
690
|
if (isHoneyApp(exported)) {
|
|
716
691
|
let spec = await generateOpenApi(exported, {
|
|
717
692
|
filterRoutes: primary.filterRoutes,
|
|
@@ -721,17 +696,17 @@ export function honey(config: HoneyVitePluginConfig) {
|
|
|
721
696
|
version: primary.version,
|
|
722
697
|
},
|
|
723
698
|
securitySchemes: primary.securitySchemes,
|
|
724
|
-
})
|
|
699
|
+
})
|
|
725
700
|
if (primary.sanitize) {
|
|
726
|
-
spec = sanitizeOpenApiSpec(spec, primary.sanitize)
|
|
701
|
+
spec = sanitizeOpenApiSpec(spec, primary.sanitize)
|
|
727
702
|
}
|
|
728
703
|
return {
|
|
729
704
|
code: `export default ${JSON.stringify(spec, null, 2)};`,
|
|
730
705
|
moduleType: "js",
|
|
731
|
-
}
|
|
706
|
+
}
|
|
732
707
|
}
|
|
733
708
|
}
|
|
734
|
-
return undefined
|
|
709
|
+
return undefined
|
|
735
710
|
},
|
|
736
711
|
|
|
737
712
|
name: "honey",
|
|
@@ -742,10 +717,7 @@ export function honey(config: HoneyVitePluginConfig) {
|
|
|
742
717
|
if (/\.openapi\s*\(|\.manifest\s*\(/.test(code) && !code.includes("@lovrozagar/honey/openapi")) {
|
|
743
718
|
inject.push('import { enableOpenApi } from "@lovrozagar/honey/openapi"', "enableOpenApi()")
|
|
744
719
|
}
|
|
745
|
-
if (
|
|
746
|
-
/(?<!Bun)(?<!Deno)\.serve\s*\(/.test(code) &&
|
|
747
|
-
!code.includes("@lovrozagar/honey/serve")
|
|
748
|
-
) {
|
|
720
|
+
if (/(?<!Bun)(?<!Deno)\.serve\s*\(/.test(code) && !code.includes("@lovrozagar/honey/serve")) {
|
|
749
721
|
inject.push('import { enableServe } from "@lovrozagar/honey/serve"', "enableServe()")
|
|
750
722
|
}
|
|
751
723
|
if (/\.errorI18n\s*\(/.test(code) && !code.includes("@lovrozagar/honey/i18n")) {
|
|
@@ -756,16 +728,14 @@ export function honey(config: HoneyVitePluginConfig) {
|
|
|
756
728
|
},
|
|
757
729
|
|
|
758
730
|
resolveId(id: string): string | undefined {
|
|
759
|
-
if (id === VIRTUAL_ROUTES) return RESOLVED_ROUTES
|
|
760
|
-
if (id === VIRTUAL_MANIFEST && resolved.codegen.manifest)
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
return RESOLVED_OPENAPI;
|
|
764
|
-
return undefined;
|
|
731
|
+
if (id === VIRTUAL_ROUTES) return RESOLVED_ROUTES
|
|
732
|
+
if (id === VIRTUAL_MANIFEST && resolved.codegen.manifest) return RESOLVED_MANIFEST
|
|
733
|
+
if (id === VIRTUAL_OPENAPI && resolved.codegen.openApi) return RESOLVED_OPENAPI
|
|
734
|
+
return undefined
|
|
765
735
|
},
|
|
766
|
-
}
|
|
736
|
+
}
|
|
767
737
|
|
|
768
|
-
return [plugin]
|
|
738
|
+
return [plugin]
|
|
769
739
|
}
|
|
770
740
|
|
|
771
|
-
export { generateRouteTree }
|
|
741
|
+
export { generateRouteTree }
|