@lovrozagar/honey 0.7.1 → 0.7.2
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 +4 -0
- package/bin/honey.js +24 -1
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +12 -3
- package/dist/codegen.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +17 -0
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +12 -3
- package/src/index.ts +43 -1
- package/src/plugin.ts +15 -0
package/src/codegen.ts
CHANGED
|
@@ -851,12 +851,21 @@ export function deduplicateSchemas(spec: OpenApiSpec): OpenApiSpec {
|
|
|
851
851
|
const mergedSchemas: Record<string, Record<string, unknown>> = { ...existing, ...extractedSchemas }
|
|
852
852
|
|
|
853
853
|
/* a hoisted nested schema whose every user became a component $ref is still referenced from
|
|
854
|
-
that component; one referenced from nowhere is dropped
|
|
854
|
+
that component; one referenced from nowhere is dropped. A kept hoisted schema can itself
|
|
855
|
+
reference hoisted schemas (an object nested in a shared object), so keep closing over the
|
|
856
|
+
references until no new one appears. */
|
|
855
857
|
const referenced = new Set<string>()
|
|
856
858
|
collectComponentRefs(paths, referenced)
|
|
857
859
|
collectComponentRefs(mergedSchemas, referenced)
|
|
858
|
-
|
|
859
|
-
|
|
860
|
+
let added = true
|
|
861
|
+
while (added) {
|
|
862
|
+
added = false
|
|
863
|
+
for (const [name, schema] of Object.entries(hoistedSchemas)) {
|
|
864
|
+
if (Object.hasOwn(mergedSchemas, name) || !referenced.has(name)) continue
|
|
865
|
+
mergedSchemas[name] = schema
|
|
866
|
+
collectComponentRefs(schema, referenced)
|
|
867
|
+
added = true
|
|
868
|
+
}
|
|
860
869
|
}
|
|
861
870
|
|
|
862
871
|
const components: OpenApiSpec["components"] = {
|
package/src/index.ts
CHANGED
|
@@ -72,7 +72,7 @@ import { getI18nRuntime } from "./i18n-slot.ts"
|
|
|
72
72
|
import { bindInternalHandler, epochCached, getOpenApiRuntime } from "./openapi/spec-factory.ts"
|
|
73
73
|
import type { ServedArtifact } from "./openapi/spec-factory.ts"
|
|
74
74
|
import type { MetaSpecSource } from "./meta-spec-merge.ts"
|
|
75
|
-
import { getServeRuntime } from "./serve-slot.ts"
|
|
75
|
+
import { getServeRuntime, isCodegenProcess } from "./serve-slot.ts"
|
|
76
76
|
import type { HoneyServeOptions, ServeHandle } from "./serve.ts"
|
|
77
77
|
|
|
78
78
|
export { clientInfo, HoneyContext } from "./context.ts"
|
|
@@ -370,6 +370,8 @@ type HoneyGraph = {
|
|
|
370
370
|
settings: AppSettings<unknown>
|
|
371
371
|
/** registered after routeTree() with no leaf in the loaded tree — stale generated file */
|
|
372
372
|
unexpected: Set<RouteId>
|
|
373
|
+
/** the loaded tree came in while `honey generate` loaded the app: a stale one is replaced, not fatal */
|
|
374
|
+
unloadIfStale: boolean
|
|
373
375
|
wsRecords: Map<RouteId, WSRouteHandler>
|
|
374
376
|
}
|
|
375
377
|
|
|
@@ -398,6 +400,7 @@ function createGraph(): HoneyGraph {
|
|
|
398
400
|
served: new Set(),
|
|
399
401
|
settings: createSettings(),
|
|
400
402
|
unexpected: new Set(),
|
|
403
|
+
unloadIfStale: false,
|
|
401
404
|
wsRecords: new Map(),
|
|
402
405
|
}
|
|
403
406
|
}
|
|
@@ -1292,6 +1295,11 @@ export class Honey<
|
|
|
1292
1295
|
}
|
|
1293
1296
|
}
|
|
1294
1297
|
if (problems.length > 0) {
|
|
1298
|
+
/* generation rewrites this file from the registered routes; serving it stale is the error */
|
|
1299
|
+
if (g.unloadIfStale) {
|
|
1300
|
+
this._unloadTree()
|
|
1301
|
+
return this._finalize()
|
|
1302
|
+
}
|
|
1295
1303
|
throw new Error(`Route tree out of date — regenerate it (\`honey generate\`):\n ${problems.join("\n ")}`)
|
|
1296
1304
|
}
|
|
1297
1305
|
|
|
@@ -1640,6 +1648,16 @@ export class Honey<
|
|
|
1640
1648
|
* registers as its gateway catch-all. Must be called before any route is registered.
|
|
1641
1649
|
*/
|
|
1642
1650
|
routeTree(tree: RouteTree): this {
|
|
1651
|
+
/* `honey generate` loads the app that imports the very file it is about to rewrite: a tree
|
|
1652
|
+
from an older honey is ignored there, and the routes the app registers are used instead */
|
|
1653
|
+
const generating = isCodegenProcess()
|
|
1654
|
+
if (generating) {
|
|
1655
|
+
try {
|
|
1656
|
+
assertTreeFormat(tree)
|
|
1657
|
+
} catch {
|
|
1658
|
+
return this
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1643
1661
|
assertTreeFormat(tree)
|
|
1644
1662
|
const g = this._graph
|
|
1645
1663
|
if (g.loaded !== null) throw new Error("routeTree() was already called on this app")
|
|
@@ -1657,6 +1675,7 @@ export class Honey<
|
|
|
1657
1675
|
g.root = freezeTree(tree.root)
|
|
1658
1676
|
g.rootShared = true
|
|
1659
1677
|
g.loaded = new Map()
|
|
1678
|
+
g.unloadIfStale = generating
|
|
1660
1679
|
for (const id of Object.keys(tree.routes)) g.loaded.set(id, { ...tree.routes[id] })
|
|
1661
1680
|
if (hasWsLeaf(g.root)) g.hasWs = true
|
|
1662
1681
|
/* internal routes mounted before the tree was loaded move onto the loaded topology */
|
|
@@ -1798,6 +1817,29 @@ export class Honey<
|
|
|
1798
1817
|
return tree
|
|
1799
1818
|
}
|
|
1800
1819
|
|
|
1820
|
+
/** @internal — drop the loaded tree and route by the registered routes alone. */
|
|
1821
|
+
_unloadTree(): void {
|
|
1822
|
+
const g = this._graph
|
|
1823
|
+
const http = [...g.records.values(), ...g.catchAll.values()]
|
|
1824
|
+
const ws = [...g.wsRecords.values()]
|
|
1825
|
+
g.records.clear()
|
|
1826
|
+
g.catchAll.clear()
|
|
1827
|
+
g.wsRecords.clear()
|
|
1828
|
+
g.unexpected.clear()
|
|
1829
|
+
g.loaded = null
|
|
1830
|
+
g.unloadIfStale = false
|
|
1831
|
+
g.root = createNode()
|
|
1832
|
+
g.rootShared = false
|
|
1833
|
+
g.hasWs = false
|
|
1834
|
+
for (const r of http) {
|
|
1835
|
+
delete r.ca
|
|
1836
|
+
const { method, segments } = patternOf(r.id as RouteId)
|
|
1837
|
+
this._addRoute(method, segments, r)
|
|
1838
|
+
}
|
|
1839
|
+
for (const r of ws) this._addWsRoute(patternOf(r.id as RouteId).segments, r)
|
|
1840
|
+
this._bumpEpoch()
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1801
1843
|
/** @internal — swap the loaded tree, re-binding every registered route to it. */
|
|
1802
1844
|
_replaceLoadedTree(tree: RouteTree): void {
|
|
1803
1845
|
const g = this._graph
|
package/src/plugin.ts
CHANGED
|
@@ -533,9 +533,24 @@ export async function generateAndWrite(
|
|
|
533
533
|
const unfilteredSpec = (what: string): Promise<OpenApiSpecInput> => {
|
|
534
534
|
if (!app) throw new Error(`${what} generation requires a configured app`)
|
|
535
535
|
const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
|
|
536
|
+
/* routes name schemes the openApi outputs declare; checked against all of them, so a declared
|
|
537
|
+
scheme is not reported as missing. The document the SDK reads stays without them, as it
|
|
538
|
+
always was, so generated SDK auth does not change. */
|
|
539
|
+
const schemes: Record<string, unknown> = {}
|
|
540
|
+
for (const entry of cg.openApi || []) {
|
|
541
|
+
for (const [name, scheme] of Object.entries(entry.securitySchemes ?? {})) {
|
|
542
|
+
if (!Object.hasOwn(schemes, name)) schemes[name] = scheme
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const declared = Object.keys(schemes).length > 0
|
|
536
546
|
unfiltered ??= generateOpenApi(app, {
|
|
537
547
|
info: primaryOA ? { title: primaryOA.title, version: primaryOA.version } : { title: "API", version: "1.0.0" },
|
|
538
548
|
invalidate: primaryOA ? "off" : cg.invalidate,
|
|
549
|
+
...(declared ? { securitySchemes: schemes } : {}),
|
|
550
|
+
}).then((spec) => {
|
|
551
|
+
if (!declared || !spec.components?.securitySchemes) return spec
|
|
552
|
+
const { securitySchemes: _schemes, ...components } = spec.components
|
|
553
|
+
return { ...spec, components }
|
|
539
554
|
})
|
|
540
555
|
return unfiltered
|
|
541
556
|
}
|