Skip to content

Commit 7b56d55

Browse files
ymc9claude
andcommitted
fix(server): align RPC OpenAPI spec with runtime parameter contract
- Add optional 'meta' query parameter to all GET endpoints (model query ops and query procedures) to document the SuperJSON companion parameter consumed by unmarshalQ alongside 'q' - Mark 'args' as required in procedure envelope schema when the procedure declares at least one non-optional parameter, matching mapProcedureArgs which throws 'missing procedure arguments' in that case Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0a4457d commit 7b56d55

2 files changed

Lines changed: 261 additions & 2 deletions

File tree

packages/server/src/api/rpc/openapi.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,9 @@ export class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {
351351

352352
if (inputSchemaRef) {
353353
if (isQueryOp) {
354-
// OAPI 3.1 supports content-typed parameters for structured query values
354+
// OAPI 3.1 supports content-typed parameters for structured query values.
355+
// `meta` is an optional companion to `q` used to carry SuperJSON serialization
356+
// metadata (see unmarshalQ in api/common/utils.ts).
355357
operation['parameters'] = [
356358
{
357359
name: 'q',
@@ -361,6 +363,12 @@ export class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {
361363
[JSON_CT]: { schema: inputSchemaRef },
362364
},
363365
},
366+
{
367+
name: 'meta',
368+
in: 'query',
369+
description: 'JSON-encoded SuperJSON serialization metadata for the "q" parameter',
370+
schema: { type: 'string' },
371+
},
364372
];
365373
} else {
366374
operation['requestBody'] = {
@@ -386,10 +394,14 @@ export class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {
386394
? { $ref: `#/components/schemas/${argsSchemaId}` }
387395
: { type: 'object' };
388396

389-
// The RPC handler accepts { args: { param1: val, ... } } envelope
397+
// The RPC handler accepts { args: { param1: val, ... } } envelope.
398+
// `args` is required when the procedure has at least one non-optional parameter
399+
// (mapProcedureArgs throws 'missing procedure arguments' otherwise).
400+
const hasRequiredParams = Object.values(procDef.params ?? {}).some((p) => !p.optional);
390401
const envelopeSchema: SchemaObject = {
391402
type: 'object',
392403
properties: { args: argsSchemaRef },
404+
...(hasRequiredParams && { required: ['args'] }),
393405
};
394406

395407
const op: Record<string, unknown> = {
@@ -434,6 +446,12 @@ export class RPCApiSpecGenerator<Schema extends SchemaDef = SchemaDef> {
434446
[JSON_CT]: { schema: envelopeSchema },
435447
},
436448
},
449+
{
450+
name: 'meta',
451+
in: 'query',
452+
description: 'JSON-encoded SuperJSON serialization metadata for the "q" parameter',
453+
schema: { type: 'string' },
454+
},
437455
];
438456
} else {
439457
op['requestBody'] = {

0 commit comments

Comments
 (0)