Skip to content

Commit

Permalink
fix: callback operation ids (#262)
Browse files Browse the repository at this point in the history
* fix: callback operation ids

* chore: reorder id segments

* chore: empty key
  • Loading branch information
Jakub Jankowski authored Dec 21, 2023
1 parent 1cc34ec commit 3414259
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 13 deletions.
27 changes: 23 additions & 4 deletions src/__tests__/generators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,31 @@ describe('idGenerators', () => {
expect(id1).toEqual(id2);
});
it('httpCallbackOperation ids should be unique', () => {
const operation1 = { parentId: '12345', method: 'post', path: '{$request.body#/returnedPetAdoptedUrl}' };
const operation2 = { parentId: '12345', method: 'post', path: '{$request.body#/newPetAvailableUrl}' };
const operation1 = {
parentId: '12345',
method: 'post',
path: '{$request.body#/returnedPetAdoptedUrl}',
key: 'returnedPetAdopted',
};
const operation2 = {
parentId: '12345',
method: 'post',
path: '{$request.body#/newPetAvailableUrl}',
key: 'newPetAvailable',
};
const operation3 = {
parentId: '12345',
method: 'post',
path: '{$request.body#/newPetAvailableUrl}',
key: 'newPet',
};
const id1 = idGenerators.httpCallbackOperation(operation1);
const id2 = idGenerators.httpCallbackOperation(operation2);
expect(id1).toEqual('http_callback-12345-post-{$request.body#/returnedPetAdoptedUrl}');
expect(id2).toEqual('http_callback-12345-post-{$request.body#/newPetAvailableUrl}');
const id3 = idGenerators.httpCallbackOperation(operation3);
expect(id1).toEqual('http_callback-12345-returnedPetAdopted-post-{$request.body#/returnedPetAdoptedUrl}');
expect(id2).toEqual('http_callback-12345-newPetAvailable-post-{$request.body#/newPetAvailableUrl}');
expect(id3).toEqual('http_callback-12345-newPet-post-{$request.body#/newPetAvailableUrl}');
expect(id1).not.toEqual(id2);
expect(id2).not.toEqual(id3);
});
});
4 changes: 2 additions & 2 deletions src/generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const idGenerators = {
return join(['http_webhook_operation', props.parentId, props.method, sanitizePath(props.name)]);
},

httpCallbackOperation: (props: Context & { method: string; path: string }) => {
return join(['http_callback', props.parentId, props.method, props.path]);
httpCallbackOperation: (props: Context & { method: string; path: string; key: string }) => {
return join(['http_callback', props.parentId, props.key, props.method, props.path]);
},

httpPathParam: (props: Context & { keyOrName: string }) => {
Expand Down
58 changes: 58 additions & 0 deletions src/oas/__tests__/__snapshots__/operation.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,64 @@ Array [
"tags": Array [],
},
Object {
"callbacks": Array [
Object {
"extensions": Object {},
"id": "http_callback-undefined-MyEvent-post-{$request.body#/callbackUrl}",
"key": "MyEvent",
"method": "post",
"path": "{$request.body#/callbackUrl}",
"request": Object {
"body": Object {
"contents": Array [
Object {
"encodings": Array [],
"examples": Array [],
"id": "http_media-http_request_body-http_callback-undefined-MyEvent-post-{$request.body#/callbackUrl}-application/json",
"mediaType": "application/json",
"schema": Object {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": Object {
"message": Object {
"examples": Array [
"Some event happened",
],
"type": "string",
},
},
"required": Array [
"message",
],
"type": "object",
"x-stoplight": Object {
"id": "schema-http_media-http_request_body-http_callback-undefined-MyEvent-post-{$request.body#/callbackUrl}-application/json-",
},
},
},
],
"id": "http_request_body-http_callback-undefined-MyEvent-post-{$request.body#/callbackUrl}",
"required": true,
},
"cookie": Array [],
"headers": Array [],
"path": Array [],
"query": Array [],
},
"responses": Array [
Object {
"code": "200",
"contents": Array [],
"description": "Your server returns this code if it accepts the callback",
"headers": Array [],
"id": "http_response-http_callback-undefined-MyEvent-post-{$request.body#/callbackUrl}-200",
},
],
"security": Array [],
"securityDeclarationType": "inheritedFromService",
"servers": Array [],
"tags": Array [],
},
],
"description": "",
"extensions": Object {},
"id": "http_operation-abc-put-/pet/{}",
Expand Down
32 changes: 32 additions & 0 deletions src/oas/__tests__/fixtures/oas3-kitchen-sink.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,38 @@
],
"requestBody": {
"$ref": "#/components/requestBodies/Pet"
},
"callbacks": {
"MyEvent": {
"{$request.body#/callbackUrl}": {
"post": {
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Some event happened"
}
},
"required": [
"message"
]
}
}
}
},
"responses": {
"200": {
"description": "Your server returns this code if it accepts the callback"
}
}
}
}
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/oas/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ export function transformOasEndpointOperations<

export const transformOasEndpointOperation: TranslateFunction<
DeepPartial<OpenAPIObject> | DeepPartial<Spec>,
[config: EndpointOperationConfig, name: string, method: string],
[config: EndpointOperationConfig, name: string, method: string, key?: string],
Omit<IHttpEndpointOperation, 'responses' | 'request' | 'servers' | 'security' | 'callbacks'>
> = function ({ type, documentProp, nameProp }: EndpointOperationConfig, name: string, method: string) {
> = function ({ type, documentProp, nameProp }: EndpointOperationConfig, name: string, method: string, key?: string) {
const pathObj = this.maybeResolveLocalRef(this.document?.[documentProp]?.[name]) as PathsObject;
if (typeof pathObj !== 'object' || pathObj === null) {
throw new Error(`Could not find ${[documentProp, name].join('/')} in the provided spec.`);
Expand All @@ -89,6 +89,7 @@ export const transformOasEndpointOperation: TranslateFunction<
parentId: serviceId,
method,
path: name,
key: key ?? '',
});
} else if (type === 'operation') {
id = this.ids.operation =
Expand Down
3 changes: 2 additions & 1 deletion src/oas3/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ export const transformOas3Operation: Oas3HttpEndpointOperationTransformer = ({
name,
method,
config,
key,
ctx = createContext(_document),
}) => {
const httpOperation = transformOasEndpointOperation.call(ctx, config, name, method);
const httpOperation = transformOasEndpointOperation.call(ctx, config, name, method, key);
const parentObj = ctx.maybeResolveLocalRef(ctx.document[config.documentProp]![name]) as Fragment;
const operation = ctx.maybeResolveLocalRef(parentObj[method]) as Fragment;

Expand Down
6 changes: 3 additions & 3 deletions src/oas3/transformers/__tests__/callbacks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('translateToCallbacks', () => {
{
key: 'newPetWebhook',
extensions: {},
id: '3245690b6a7fc',
id: '8598295bca7aa',
method: 'post',
path: '{$request.body#/newPetAvailableUrl}',
request: {
Expand Down Expand Up @@ -152,7 +152,7 @@ describe('translateToCallbacks', () => {
{
key: 'newPetWebhook',
extensions: {},
id: '07041d5723f4a',
id: '602f44a0af2a3',
method: 'post',
path: '{$request.body#/returnedPetAvailableUrl}',
request: {
Expand Down Expand Up @@ -204,7 +204,7 @@ describe('translateToCallbacks', () => {
{
key: 'petAdopted',
extensions: {},
id: '2333951a518f9',
id: '54f5719cae277',
method: 'post',
path: '{$request.body#/adoptedUrl}',
request: {
Expand Down
8 changes: 7 additions & 1 deletion src/oas3/transformers/callbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ export const translateToCallbacks: Oas3TranslateFunction<
const ctx = createContext(document);
ctx.context = 'callback';
Object.assign(ctx.ids, this.ids);
ctx.ids.operation = this.generateId.httpCallbackOperation({ parentId: this.ids.service, method, path });
ctx.ids.operation = this.generateId.httpCallbackOperation({
parentId: this.ids.service,
method,
path,
key: callbackName,
});
results.push({
...transformOas3Operation({
document,
method,
name: path,
key: callbackName,
config: OPERATION_CONFIG,
ctx,
}),
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface ITransformEndpointOperationOpts<T extends Fragment> {
document: T;
name: string;
method: string;
key?: string;
config: EndpointOperationConfig;
ctx?: TransformerContext<T>;
}
Expand Down

0 comments on commit 3414259

Please sign in to comment.