diff --git a/src/lib/blueprint.ts b/src/lib/blueprint.ts index 2c47275..83447ae 100644 --- a/src/lib/blueprint.ts +++ b/src/lib/blueprint.ts @@ -286,6 +286,7 @@ const createRoutes = async ( for (const [path, pathItem] of pathEntries) { const namespace = getNamespace(path, paths) + const route = await createRoute(namespace, path, pathItem, context) const existingRoute = routeMap.get(route.path) @@ -318,7 +319,9 @@ const getNamespace = (path: string, paths: OpenapiPaths): string | null => { // An endpoint is a route that ends without further paths. i.e., ends in // a letter (not slash). - const endpoints = pathKeys.filter((key) => !key.endsWith('/')) + const endpoints = pathKeys.filter((key) => { + return new RegExp(`^/${[...namespace, part].join('/')}/\\w+$`).test(key) + }) if (endpoints.length === 0) { namespace.push(part) diff --git a/test/fixtures/types/code-sample-definitions.ts b/test/fixtures/types/code-sample-definitions.ts index 83d2dd1..f79de66 100644 --- a/test/fixtures/types/code-sample-definitions.ts +++ b/test/fixtures/types/code-sample-definitions.ts @@ -37,4 +37,22 @@ export default [ }, }, }, + { + title: 'List planes', + description: 'This is the wya to get all plans', + request: { + path: '/transport/air/planes/list', + parameters: {}, + }, + response: { + body: { + planes: [ + { + plane_id: '9d3163f9-9185-40d3-a0ce-a03d3c7ce402', + name: 'Woosh', + }, + ], + }, + }, + }, ] diff --git a/test/fixtures/types/openapi.ts b/test/fixtures/types/openapi.ts index a48af70..0f79f9c 100644 --- a/test/fixtures/types/openapi.ts +++ b/test/fixtures/types/openapi.ts @@ -36,6 +36,22 @@ export default { }, required: ['foo_id', 'name'], }, + plane: { + type: 'object', + description: 'A plane resource.', + properties: { + plane_id: { + description: 'plane id', + format: 'uuid', + type: 'string', + }, + name: { + description: 'Planej name', + type: 'string', + }, + }, + required: ['plane_id', 'name'], + }, }, }, paths: { @@ -157,5 +173,37 @@ export default { 'x-title': 'List foos', }, }, + '/transport/air/planes/list': { + get: { + operationId: 'planesListGet', + responses: { + 200: { + content: { + 'application/json': { + schema: { + properties: { + ok: { type: 'boolean' }, + planes: { + items: { $ref: '#/components/schemas/plane' }, + type: 'array', + }, + }, + required: ['planes', 'ok'], + type: 'object', + }, + }, + }, + description: 'List all planes.', + }, + 400: { description: 'Bad Request' }, + 401: { description: 'Unauthorized' }, + }, + security: [], + summary: '/transport/air/planes/list', + tags: ['/transport/air/planes'], + 'x-response-key': 'planes', + 'x-title': 'List planes', + }, + }, }, } diff --git a/test/fixtures/types/route-specs.ts b/test/fixtures/types/route-specs.ts index 9901a5b..4bbbaaa 100644 --- a/test/fixtures/types/route-specs.ts +++ b/test/fixtures/types/route-specs.ts @@ -16,5 +16,12 @@ export const routes = { jsonResponse: z.object({ foos: z.array(schemas.foo), }), + '/transport/air/planes/list': { + auth: 'none', + methods: ['GET'], + jsonResponse: z.object({ + planes: z.array(schemas.plane), + }), + }, }, } as const diff --git a/test/fixtures/types/route-types.ts b/test/fixtures/types/route-types.ts index 55d89a7..9f3d55f 100644 --- a/test/fixtures/types/route-types.ts +++ b/test/fixtures/types/route-types.ts @@ -33,6 +33,20 @@ export interface Routes { } } } + '/transport/air/planes/list': { + route: '/transport/air/planes/list' + method: 'GET' + queryParams: Record + jsonBody: Record + commonParams: Record + formData: Record + jsonResponse: { + planes: { + plane_id: string + name: string + } + } + } } export type RouteResponse = diff --git a/test/fixtures/types/schemas.ts b/test/fixtures/types/schemas.ts index eb23fdc..1c1f4c3 100644 --- a/test/fixtures/types/schemas.ts +++ b/test/fixtures/types/schemas.ts @@ -7,3 +7,8 @@ export const foo = z.object({ undocumented_prop: z.string().optional(), nullable_property: z.string().optional().nullable(), }) + +export const plane = z.object({ + plane_id: z.string().uuid(), + name: z.string(), +}) diff --git a/test/snapshots/blueprint.test.ts.md b/test/snapshots/blueprint.test.ts.md index c9c0fc8..1b8f1a7 100644 --- a/test/snapshots/blueprint.test.ts.md +++ b/test/snapshots/blueprint.test.ts.md @@ -61,6 +61,30 @@ Generated by [AVA](https://avajs.dev). ], resourceType: 'foo', }, + plane: { + description: 'A plane resource.', + properties: [ + { + deprecationMessage: '', + description: 'plane id', + format: 'id', + isDeprecated: false, + isUndocumented: false, + jsonType: 'string', + name: 'plane_id', + }, + { + deprecationMessage: '', + description: 'Planej name', + format: 'string', + isDeprecated: false, + isUndocumented: false, + jsonType: 'string', + name: 'name', + }, + ], + resourceType: 'plane', + }, }, routes: [ { @@ -399,6 +423,97 @@ Generated by [AVA](https://avajs.dev). path: '/foos', subroutes: [], }, + { + endpoints: [ + { + codeSamples: [ + { + code: { + javascript: { + request: 'await seam.transport.air.planes.list()', + request_syntax: 'javascript', + response: '[{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]', + response_syntax: 'javascript', + title: 'JavaScript', + }, + php: { + request: `transport->air->planes->list()`, + request_syntax: 'php', + response: '[{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]', + response_syntax: 'json', + title: 'PHP', + }, + python: { + request: 'seam.transport.air.planes.list()', + request_syntax: 'python', + response: '[Plane(plane_id="9d3163f9-9185-40d3-a0ce-a03d3c7ce402", name="Woosh")]', + response_syntax: 'python', + title: 'Python', + }, + ruby: { + request: 'seam.transport.air.planes.list()', + request_syntax: 'ruby', + response: '[{"plane_id" => "9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name" => "Woosh"}]', + response_syntax: 'ruby', + title: 'Ruby', + }, + seam_cli: { + request: 'seam transport air planes list ', + request_syntax: 'bash', + response: '[{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]', + response_syntax: 'json', + title: 'Seam CLI', + }, + }, + description: 'This is the wya to get all plans', + request: { + parameters: {}, + path: '/transport/air/planes/list', + }, + response: { + body: { + planes: [ + { + name: 'Woosh', + plane_id: '9d3163f9-9185-40d3-a0ce-a03d3c7ce402', + }, + ], + }, + }, + title: 'List planes', + }, + ], + deprecationMessage: '', + description: '', + isDeprecated: false, + isUndocumented: false, + name: 'list', + path: '/transport/air/planes/list', + request: { + methods: [ + 'GET', + ], + parameters: [], + preferredMethod: 'GET', + semanticMethod: 'GET', + }, + response: { + description: 'List all planes.', + resourceType: 'plane', + responseKey: 'planes', + responseType: 'resource_list', + }, + title: 'List planes', + }, + ], + name: 'planes', + namespace: { + path: '/transport/air', + }, + path: '/transport/air/planes', + subroutes: [], + }, ], title: 'Foo', } @@ -460,6 +575,30 @@ Generated by [AVA](https://avajs.dev). ], resourceType: 'foo', }, + plane: { + description: 'A plane resource.', + properties: [ + { + deprecationMessage: '', + description: 'plane id', + format: 'id', + isDeprecated: false, + isUndocumented: false, + jsonType: 'string', + name: 'plane_id', + }, + { + deprecationMessage: '', + description: 'Planej name', + format: 'string', + isDeprecated: false, + isUndocumented: false, + jsonType: 'string', + name: 'name', + }, + ], + resourceType: 'plane', + }, }, routes: [ { @@ -838,6 +977,107 @@ Generated by [AVA](https://avajs.dev). path: '/foos', subroutes: [], }, + { + endpoints: [ + { + codeSamples: [ + { + code: { + javascript: { + request: `// javascript␊ + await seam.transport.air.planes.list()`, + request_syntax: 'javascript', + response: `// javascript␊ + [{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]`, + response_syntax: 'javascript', + title: 'JavaScript', + }, + php: { + request: `// php␊ + transport->air->planes->list()`, + request_syntax: 'php', + response: `// json␊ + [{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]`, + response_syntax: 'json', + title: 'PHP', + }, + python: { + request: `// python␊ + seam.transport.air.planes.list()`, + request_syntax: 'python', + response: `// python␊ + [Plane(plane_id="9d3163f9-9185-40d3-a0ce-a03d3c7ce402", name="Woosh")]`, + response_syntax: 'python', + title: 'Python', + }, + ruby: { + request: `// ruby␊ + seam.transport.air.planes.list()`, + request_syntax: 'ruby', + response: `// ruby␊ + [{"plane_id" => "9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name" => "Woosh"}]`, + response_syntax: 'ruby', + title: 'Ruby', + }, + seam_cli: { + request: `// bash␊ + seam transport air planes list `, + request_syntax: 'bash', + response: `// json␊ + [{"plane_id":"9d3163f9-9185-40d3-a0ce-a03d3c7ce402","name":"Woosh"}]`, + response_syntax: 'json', + title: 'Seam CLI', + }, + }, + description: 'This is the wya to get all plans', + request: { + parameters: {}, + path: '/transport/air/planes/list', + }, + response: { + body: { + planes: [ + { + name: 'Woosh', + plane_id: '9d3163f9-9185-40d3-a0ce-a03d3c7ce402', + }, + ], + }, + }, + title: 'List planes', + }, + ], + deprecationMessage: '', + description: '', + isDeprecated: false, + isUndocumented: false, + name: 'list', + path: '/transport/air/planes/list', + request: { + methods: [ + 'GET', + ], + parameters: [], + preferredMethod: 'GET', + semanticMethod: 'GET', + }, + response: { + description: 'List all planes.', + resourceType: 'plane', + responseKey: 'planes', + responseType: 'resource_list', + }, + title: 'List planes', + }, + ], + name: 'planes', + namespace: { + path: '/transport/air', + }, + path: '/transport/air/planes', + subroutes: [], + }, ], title: 'Foo', } diff --git a/test/snapshots/blueprint.test.ts.snap b/test/snapshots/blueprint.test.ts.snap index a7047e8..6c1b44d 100644 Binary files a/test/snapshots/blueprint.test.ts.snap and b/test/snapshots/blueprint.test.ts.snap differ diff --git a/test/snapshots/seam-blueprint.test.ts.md b/test/snapshots/seam-blueprint.test.ts.md index 5fd409a..944c948 100644 --- a/test/snapshots/seam-blueprint.test.ts.md +++ b/test/snapshots/seam-blueprint.test.ts.md @@ -113,15 +113,6 @@ Generated by [AVA](https://avajs.dev). jsonType: 'string', name: 'external_type_display_name', }, - { - deprecationMessage: '', - description: '', - format: 'boolean', - isDeprecated: false, - isUndocumented: false, - jsonType: 'boolean', - name: 'is_managed', - }, { deprecationMessage: '', description: '', @@ -268,9 +259,6 @@ Generated by [AVA](https://avajs.dev). { name: 'visionline_card', }, - { - name: 'salto_ks_credential', - }, ], }, { @@ -291,15 +279,6 @@ Generated by [AVA](https://avajs.dev). jsonType: 'boolean', name: 'is_latest_desired_state_synced_with_provider', }, - { - deprecationMessage: '', - description: '', - format: 'boolean', - isDeprecated: false, - isUndocumented: false, - jsonType: 'boolean', - name: 'is_managed', - }, { deprecationMessage: '', description: '', @@ -362,15 +341,6 @@ Generated by [AVA](https://avajs.dev). }, ], }, - { - deprecationMessage: '', - description: '', - format: 'string', - isDeprecated: false, - isUndocumented: false, - jsonType: 'string', - name: 'card_id', - }, { deprecationMessage: '', description: '', @@ -380,15 +350,6 @@ Generated by [AVA](https://avajs.dev). jsonType: 'array', name: 'common_acs_entrance_ids', }, - { - deprecationMessage: '', - description: '', - format: 'string', - isDeprecated: false, - isUndocumented: false, - jsonType: 'string', - name: 'credential_id', - }, { deprecationMessage: '', description: '', @@ -398,15 +359,6 @@ Generated by [AVA](https://avajs.dev). jsonType: 'array', name: 'guest_acs_entrance_ids', }, - { - deprecationMessage: '', - description: '', - format: 'boolean', - isDeprecated: false, - isUndocumented: false, - jsonType: 'boolean', - name: 'is_valid', - }, { deprecationMessage: '', description: '', @@ -947,10 +899,10 @@ Generated by [AVA](https://avajs.dev). }, { deprecationMessage: '', - description: 'Warnings associated with the `acs_system`.', + description: '', format: 'list', isDeprecated: false, - isUndocumented: false, + isUndocumented: true, jsonType: 'array', name: 'warnings', }, @@ -1114,15 +1066,6 @@ Generated by [AVA](https://avajs.dev). jsonType: 'boolean', name: 'is_latest_desired_state_synced_with_provider', }, - { - deprecationMessage: '', - description: '', - format: 'boolean', - isDeprecated: false, - isUndocumented: false, - jsonType: 'boolean', - name: 'is_managed', - }, { deprecationMessage: '', description: '', @@ -1373,39 +1316,6 @@ Generated by [AVA](https://avajs.dev). }, title: '', }, - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'list_accessible_entrances', - path: '/acs/access_groups/list_accessible_entrances', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: true, - isUndocumented: false, - jsonType: 'string', - name: 'acs_access_group_id', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, { codeSamples: [], deprecationMessage: '', @@ -1490,92 +1400,6 @@ Generated by [AVA](https://avajs.dev). path: '/acs/access_groups', subroutes: [], }, - { - endpoints: [ - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'get', - path: '/acs/access_groups/unmanaged/get', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: true, - isUndocumented: false, - jsonType: 'string', - name: 'acs_access_group_id', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'list', - path: '/acs/access_groups/unmanaged/list', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'acs_system_id', - }, - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'acs_user_id', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - ], - name: 'unmanaged', - namespace: { - path: '/acs', - }, - path: '/acs/access_groups/unmanaged', - subroutes: [], - }, { endpoints: [ { @@ -2313,71 +2137,6 @@ Generated by [AVA](https://avajs.dev). path: '/acs/credentials', subroutes: [], }, - { - endpoints: [ - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'get', - path: '/acs/credentials/unmanaged/get', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: true, - isUndocumented: false, - jsonType: 'string', - name: 'acs_credential_id', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'list', - path: '/acs/credentials/unmanaged/list', - request: { - methods: [ - 'POST', - ], - parameters: [], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - ], - name: 'unmanaged', - namespace: { - path: '/acs', - }, - path: '/acs/credentials/unmanaged', - subroutes: [], - }, { endpoints: [ { @@ -3450,122 +3209,6 @@ Generated by [AVA](https://avajs.dev). path: '/acs/users', subroutes: [], }, - { - endpoints: [ - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'get', - path: '/acs/users/unmanaged/get', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: true, - isUndocumented: false, - jsonType: 'string', - name: 'acs_user_id', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - { - codeSamples: [], - deprecationMessage: '', - description: '', - isDeprecated: false, - isUndocumented: false, - name: 'list', - path: '/acs/users/unmanaged/list', - request: { - methods: [ - 'POST', - ], - parameters: [ - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'acs_system_id', - }, - { - deprecationMessage: '', - description: '', - format: 'number', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'number', - name: 'limit', - }, - { - deprecationMessage: '', - description: '', - format: 'string', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'user_identity_email_address', - }, - { - deprecationMessage: '', - description: '', - format: 'id', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'user_identity_id', - }, - { - deprecationMessage: '', - description: '', - format: 'string', - isDeprecated: false, - isRequired: false, - isUndocumented: false, - jsonType: 'string', - name: 'user_identity_phone_number', - }, - ], - preferredMethod: 'POST', - semanticMethod: 'POST', - }, - response: { - description: 'OK', - responseType: 'void', - }, - title: '', - }, - ], - name: 'unmanaged', - namespace: { - path: '/acs', - }, - path: '/acs/users/unmanaged', - subroutes: [], - }, ], title: 'Seam Connect', } diff --git a/test/snapshots/seam-blueprint.test.ts.snap b/test/snapshots/seam-blueprint.test.ts.snap index bd223fc..e8d3073 100644 Binary files a/test/snapshots/seam-blueprint.test.ts.snap and b/test/snapshots/seam-blueprint.test.ts.snap differ