Skip to content

Commit a08e8e7

Browse files
razor-xclaude
andauthored
fix: Leave pagination params out of the at least one parameter guard (#1008)
* fix: Leave pagination params out of the at least one parameter guard The at least one parameter guard counted every parameter, so accessCodes.list({ limit: 10 }) satisfied the guard, and the generated parameter type, while naming no filter at all, and a page cursor alone satisfied it from page two onward. Pagination knobs are not filters. Generate an explicit atLeastOneParameterNames list that excludes limit and page_cursor, use it for the runtime check instead of scanning every value, and constrain the generated RequireAtLeastOne parameter types to the same names so the type level and runtime agree. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2 * docs: Drop the pagination parameter comment Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B8xeJm2Hd923k8uo6eoFd2 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9ac8973 commit a08e8e7

47 files changed

Lines changed: 1326 additions & 828 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎codegen/layouts/partials/route-class-endpoint-export.hbs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type {{parametersTypeName}} = {{#if requiresAtLeastOneParameter}}RequireAtLeastOne<{{/if}}{{> request-object parameters=parameters}}{{#if requiresAtLeastOneParameter}}>{{/if}}
1+
export type {{parametersTypeName}} = {{#if requiresAtLeastOneParameter}}RequireAtLeastOne<{{/if}}{{> request-object parameters=parameters}}{{#if requiresAtLeastOneParameter}}, {{atLeastOneParameterNamesUnion}}>{{/if}}
22

33
/**
44
* @deprecated Use {{requestTypeName}} instead.

‎codegen/layouts/partials/route-class-endpoint.hbs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
parameters,
1010
hasRequiredParameters: {{hasRequiredParameters}},
1111
requiredParameterNames: [{{#each requiredParameterNames}}{{json .}}{{#unless @last}}, {{/unless}}{{/each}}],
12+
atLeastOneParameterNames: [{{#each atLeastOneParameterNames}}{{json .}}{{#unless @last}}, {{/unless}}{{/each}}],
1213
responseKey: {{#if returnsVoid}}undefined{{else}}'{{responseKey}}'{{/if}},
1314
{{#if hasPagination}}hasPagination: true,
1415
{{/if}}options,

‎codegen/lib/layouts/route.ts‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export interface EndpointLayoutContext {
4040
hasRequiredParameters: boolean
4141
requiredParameterNames: string[]
4242
requiresAtLeastOneParameter: boolean
43+
atLeastOneParameterNames: string[]
44+
atLeastOneParameterNamesUnion: string
4345
parameters: Parameter[]
4446
responseIsList: boolean
4547
responseResourceTypeName: string
@@ -72,7 +74,9 @@ export const setRouteLayoutContext = (
7274
file.needsRequireAtLeastOneImport =
7375
node != null &&
7476
'endpoints' in node &&
75-
node.endpoints.some(requiresAtLeastOneParameter)
77+
node.endpoints.some(
78+
(endpoint) => getAtLeastOneParameterNames(endpoint).length > 0,
79+
)
7680
file.resourceTypeImports =
7781
node != null && 'endpoints' in node
7882
? [
@@ -155,7 +159,12 @@ export const getEndpointLayoutContext = (
155159
requiredParameterNames: endpoint.request.parameters
156160
.filter(({ isRequired }) => isRequired)
157161
.map(({ name }) => name),
158-
requiresAtLeastOneParameter: requiresAtLeastOneParameter(endpoint),
162+
requiresAtLeastOneParameter:
163+
getAtLeastOneParameterNames(endpoint).length > 0,
164+
atLeastOneParameterNames: getAtLeastOneParameterNames(endpoint),
165+
atLeastOneParameterNamesUnion: getAtLeastOneParameterNames(endpoint)
166+
.map((name) => `'${name}'`)
167+
.join(' | '),
159168
parameters: endpoint.request.parameters,
160169
responseIsList: endpoint.response.responseType === 'resource_list',
161170
responseResourceTypeName:
@@ -172,6 +181,15 @@ const requiresAtLeastOneParameter = (endpoint: Endpoint): boolean =>
172181
endpoint.request.hasRequiredParameters &&
173182
endpoint.request.parameters.every(({ isRequired }) => !isRequired)
174183

184+
const paginationParameterNames = new Set(['limit', 'page_cursor'])
185+
186+
const getAtLeastOneParameterNames = (endpoint: Endpoint): string[] =>
187+
requiresAtLeastOneParameter(endpoint)
188+
? endpoint.request.parameters
189+
.map(({ name }) => name)
190+
.filter((name) => !paginationParameterNames.has(name))
191+
: []
192+
175193
const isActionAttemptEndpoint = (endpoint: Endpoint): boolean =>
176194
endpoint.response.responseType === 'resource' &&
177195
endpoint.response.resourceType === 'action_attempt'

‎src/lib/request-parameters.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const assertValidRequestParameters = (
1010
path: string,
1111
hasRequiredParameters: boolean,
1212
requiredParameterNames: readonly string[],
13+
atLeastOneParameterNames: readonly string[],
1314
): void => {
1415
if (parameters === undefined) {
1516
if (hasRequiredParameters) {
@@ -37,8 +38,10 @@ export const assertValidRequestParameters = (
3738
}
3839

3940
if (
40-
hasRequiredParameters &&
41-
Object.values(parameterValues).every((value) => value === undefined)
41+
atLeastOneParameterNames.length > 0 &&
42+
atLeastOneParameterNames.every(
43+
(name) => parameterValues[name] === undefined,
44+
)
4245
) {
4346
throw new TypeError(`At least one parameter is required for ${path}`)
4447
}

‎src/lib/routes/access-codes/access-codes.ts‎

Lines changed: 88 additions & 56 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/lib/routes/access-codes/simulate/simulate.ts‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/lib/routes/access-codes/unmanaged/unmanaged.ts‎

Lines changed: 22 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)