Skip to content

feat: Custom param type - #184

Closed
daogrady wants to merge 3 commits into
mainfrom
feat/custom-param-type
Closed

daogrady wants to merge 3 commits into
mainfrom
feat/custom-param-type

Conversation

@daogrady

@daogrady daogrady commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes issues/issues/21005

@daogrady
daogrady force-pushed the feat/custom-param-type branch from 393fdee to 9482e71 Compare September 3, 2026 08:20
@daogrady
daogrady marked this pull request as draft September 3, 2026 08:27
@daogrady

daogrady commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor Author

Converting to draft, as this is a feature that is not covered in the odata standard:

"CustomParameter": {
            "$Kind": "ComplexType",
            "@Core.Description": "A custom parameter is either a header or a query option",
            "@Core.LongDescription": "The type of a custom parameter is always a string. Restrictions on the parameter values can be expressed by annotating the record expression describing the parameter with terms from the Validation vocabulary, e.g. Validation.Pattern or Validation.AllowedValues.",
            "Name": {
                "@Core.Description": "Name of the custom parameter"
            },
            "Description": {
                "$Nullable": true,
                "@Core.Description": "Description of the custom parameter"
            },
            "DocumentationURL": {
                "$Nullable": true,
                "@Core.IsURL": true,
                "@Core.Description": "URL of related documentation"
            },
            "Required": {
                "$Type": "Edm.Boolean",
                "$DefaultValue": false,
                "@Core.Description": "true: parameter is required, false or not specified: parameter is optional"
            },
            "ExampleValues": {
                "$Collection": true,
                "$Type": "Core.PrimitiveExampleValue",
                "@Core.Description": "Example values for the custom parameter"
            }
        },

https://raw.githubusercontent.com/oasis-tcs/odata-vocabularies/main/vocabularies/Org.OData.Capabilities.V1.json

explicitly states that (a) the type is always string and (b) value restrictions can be passed as such. That would mean booleans would be restricted by setting the allowed values to ["true", "false"], which is awkward. So the request to be able to pass a custom type with a matching default value makes sense.

The import already supports this, see:

// foo.cds
service DemoService {
    entity Things {
        key id   : Integer;
            name : String;
    }
}

annotate DemoService.Things with @Capabilities.InsertRestrictions.CustomHeaders: [{
    Name                : 'x-auto-activate',
    Description         : 'Auto-activate the record. Boolean, defaults to true.',
    Required            : false,
    ![@openapi.type]    : 'boolean',
    ![@openapi.default] : true
}];

then (with feat/custom-param-type checked out):

cds compile foo.cds -2 openapi > out.json

inspect the output file to find the custom type. Then

cds import --from openapi out.json

inspect the srv/external/out.csn to find the custom type again.

Still, other tools could trip over this non-standard annotation, so I am hesitant to merge it just yet.

@daogrady

daogrady commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Checked with openapiviewer.com, and at least there it does not break anything:

before:
Screenshot 2026-09-03 at 13 31 04

after:
Screenshot 2026-09-03 at 13 31 09

Comment thread CHANGELOG.md

### Changed
- set `odata` as the service protocol if no protocol is set to match the default behavior of `@sap/cds`. Provide `cds.env.openapi.defaultProtocol = "rest"` to restore old behavior.
### Deprecated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder (cosmetic): mind blank lines b/w headings before release

@tim-sh tim-sh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@tim-sh

tim-sh commented Sep 24, 2026

Copy link
Copy Markdown
Member

Looks good to me

@daogrady To clarify my approval, it referred to the impl and was not a vote on the standard-related question you rightly raised (and I agree with your hesitation).

I'd actually go further: the problem of a boolean only expressible as type: string with enum: ["true", "false"] is a generic OData/OpenAPI gap and not CAP-specific. We shouldn't deviate from the spec for a generic problem without a CAP-specific reason. So I'd imagine this extension rather upstream in the OData vocabulary than in a CAP-proprietary @openapi.* annotation that a standard-conformant consumer wouldn't expect.

@daogrady

Copy link
Copy Markdown
Contributor Author

Thank you for weighing in. I agree with your sentiment. I will close this PR and the issue it referred to as won't fix, and point out the concerns we identified.

@daogrady daogrady closed this Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants