-
Notifications
You must be signed in to change notification settings - Fork 1
Fix/kopai app docs warning #59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@kopai/app": minor | ||
| --- | ||
|
|
||
| Fix ugly warning displayed at /documentation |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,21 @@ import { printStartupBanner } from "./startup-banner.js"; | |
|
|
||
| const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
|
|
||
| function hasComponentSchemas( | ||
| doc: unknown | ||
| ): doc is { components: { schemas: Record<string, object> } } { | ||
| return ( | ||
| typeof doc === "object" && | ||
| doc !== null && | ||
| "components" in doc && | ||
| typeof doc.components === "object" && | ||
| doc.components !== null && | ||
| "schemas" in doc.components && | ||
| typeof doc.components.schemas === "object" && | ||
| doc.components.schemas !== null | ||
| ); | ||
| } | ||
|
|
||
| const apiServer = fastify({ | ||
| logger: { level: "warn" }, | ||
| }); | ||
|
|
@@ -46,7 +61,41 @@ apiServer.register(fastifySwagger, { | |
| if (uiRoutes.includes(url)) return { schema: { hide: true }, url }; | ||
| return jsonSchemaTransform({ schema, url, ...rest }); | ||
| }, | ||
| transformObject: jsonSchemaTransformObject, | ||
| transformObject: (input) => { | ||
| const result = jsonSchemaTransformObject(input); | ||
| // Fix: z.lazy() recursive schemas generate $ref to schema0 | ||
| // but fastify-type-provider-zod doesn't define it in components. | ||
| // Inject the missing schema definition and rename schema0 → AttributeValue. | ||
| const raw = JSON.stringify(result); | ||
| const renamed = raw.replaceAll( | ||
| "#/components/schemas/schema0", | ||
| "#/components/schemas/AttributeValue" | ||
| ); | ||
| const patched: unknown = JSON.parse(renamed); | ||
| if ( | ||
| hasComponentSchemas(patched) && | ||
| !patched.components.schemas.AttributeValue | ||
| ) { | ||
| patched.components.schemas.AttributeValue = { | ||
| anyOf: [ | ||
| { type: "string" }, | ||
| { type: "number" }, | ||
| { type: "boolean" }, | ||
| { | ||
| type: "array", | ||
| items: { $ref: "#/components/schemas/AttributeValue" }, | ||
| }, | ||
| { | ||
| type: "object", | ||
| additionalProperties: { | ||
| $ref: "#/components/schemas/AttributeValue", | ||
| }, | ||
| }, | ||
| ], | ||
| }; | ||
|
Comment on lines
+79
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find the AttributeValue Zod schema definition
rg -n 'AttributeValue' --type ts -B 3 -A 10 packages/app/src/Repository: kopai-app/kopai-mono Length of output: 2348 🏁 Script executed: #!/bin/bash
# Search for the Zod schema definition of AttributeValue
# Look for z.union, z.discriminatedUnion, z.lazy patterns
rg -n 'z\.(lazy|union|discriminatedUnion)' --type ts -B 2 -A 15 | grep -A 15 -B 2 -i attributeRepository: kopai-app/kopai-mono Length of output: 29488 🏁 Script executed: #!/bin/bash
# Alternative: search for where AttributeValue Zod type is defined
# Look for const or type declarations with AttributeValue
rg -n 'const.*AttributeValue|type.*AttributeValue' --type ts -A 10Repository: kopai-app/kopai-mono Length of output: 4753 🏁 Script executed: #!/bin/bash
# Verify the mapping by checking both schemas side-by-side
echo "=== Actual Zod schema in denormalized-signals-zod.ts ==="
sed -n '10,17p' packages/core/src/denormalized-signals-zod.ts
echo ""
echo "=== Hardcoded anyOf in server.ts ==="
sed -n '80,94p' packages/app/src/server.tsRepository: kopai-app/kopai-mono Length of output: 760 Hardcoded The hardcoded schema here currently matches the Consider deriving this schema from the Zod definition instead of maintaining it manually, or add a comment explicitly linking it to the source Zod schema to flag this coupling. 🤖 Prompt for AI Agents |
||
| } | ||
| return patched as ReturnType<typeof jsonSchemaTransformObject>; | ||
| }, | ||
| }); | ||
|
|
||
| apiServer.register(fastifySwaggerUI, { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: kopai-app/kopai-mono
Length of output: 11038
🏁 Script executed:
Repository: kopai-app/kopai-mono
Length of output: 1713
🏁 Script executed:
Repository: kopai-app/kopai-mono
Length of output: 336
schema0is an unstable internal implementation detail — coupling to library internals risks silent breakage.Three concrete concerns with this approach:
Multiple lazy schemas: The codebase contains many
z.lazy()schemas across multiple files. While onlyschema0appears in the current Swagger output, if any route uses an unregisteredz.lazy()that generatesschema1,schema2, etc., those dangling references remain unpatched, producing Swagger validation warnings.Library version fragility:
schema0is not part offastify-type-provider-zod's public API. A patch release could change the naming convention (e.g., to a content-hash or UUID), silently breaking this fix with no type error or test failure.Overly broad string replacement:
replaceAllon the full JSON string searches the entire serialized document. While#/components/schemas/schema0is fairly specific, it would incorrectly rewrite any occurrence in adescriptionorexamplefield that happens to contain this exact string.🤖 Prompt for AI Agents