kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: mark optional Organization fields as nullable in OpenAPI spec (#1090)

Better Auth's OpenAPI generator does not emit nullable: true for fields
with required: false. This causes the Organization (Workspace) schema
to declare logo, metadata, and description as non-nullable strings,
while the API actually returns null for these fields.

Add a markOptionalSchemaFieldsNullable post-processor that walks
component schemas and adds nullable: true to properties not listed in
the required array.

Closes #1087

authored by

Ivan Bobchenkov and committed by
GitHub
a1755d3b 37c85d0a

+33 -3
+6 -3
apps/api/src/index.ts
··· 42 42 import { 43 43 dedupeOperationIds, 44 44 ensureOperationSummaries, 45 + markOptionalSchemaFieldsNullable, 45 46 mergeOpenApiSpecs, 46 47 normalizeApiServerUrl, 47 48 normalizeEmptyRequiredArrays, ··· 304 305 return c.json( 305 306 ensureOperationSummaries( 306 307 dedupeOperationIds( 307 - normalizeNullableSchemasForOpenApi30( 308 - normalizeEmptyRequiredArrays( 309 - mergeOpenApiSpecs(honoSpec, normalizedAuthSpec), 308 + markOptionalSchemaFieldsNullable( 309 + normalizeNullableSchemasForOpenApi30( 310 + normalizeEmptyRequiredArrays( 311 + mergeOpenApiSpecs(honoSpec, normalizedAuthSpec), 312 + ), 310 313 ), 311 314 ), 312 315 ),
+27
apps/api/src/utils/openapi-spec.ts
··· 410 410 return spec; 411 411 }; 412 412 413 + export const markOptionalSchemaFieldsNullable = ( 414 + spec: Record<string, unknown>, 415 + ) => { 416 + const schemas = ((spec as { components?: { schemas?: unknown } }).components 417 + ?.schemas || {}) as Record<string, unknown>; 418 + 419 + for (const schema of Object.values(schemas)) { 420 + if (!isPlainObject(schema)) continue; 421 + 422 + const properties = schema.properties as Record<string, unknown> | undefined; 423 + if (!isPlainObject(properties)) continue; 424 + 425 + const required = Array.isArray(schema.required) ? schema.required : []; 426 + 427 + for (const [name, prop] of Object.entries(properties)) { 428 + if (required.includes(name)) continue; 429 + if (!isPlainObject(prop)) continue; 430 + if (prop.nullable === true) continue; 431 + if (typeof prop.type !== "string") continue; 432 + 433 + prop.nullable = true; 434 + } 435 + } 436 + 437 + return spec; 438 + }; 439 + 413 440 export const ensureOperationSummaries = (spec: Record<string, unknown>) => { 414 441 const paths = ((spec as { paths?: unknown }).paths || {}) as Record< 415 442 string,