Skip to content

Commit

Permalink
[ENG-1251] SnapTrade API Portal Feedback (part 2 - ordering endpoints (
Browse files Browse the repository at this point in the history
…#263)

* cleanup sidebar spacing

* add more docs for api portal

* normalize line heights/font size for navlinks

* style section label better

* make radius "sm" for object/array forms in reference page

* fix line height of linksgroup.tsx

* reduce padding for api reference operations

* order + orderOpenApiSpecification

* docs(changeset): add "order" property to konfig.yaml for ordering operations in API reference page

* orderOpenApiSpecification in api portal

* add docs for ordering operations in api reference

* add passthrough to KonfigYamlCommon to future compatability
  • Loading branch information
dphuang2 authored Oct 9, 2023
1 parent 05ba7ee commit 99310fc
Show file tree
Hide file tree
Showing 26 changed files with 554 additions and 47 deletions.
2 changes: 1 addition & 1 deletion customers/decentro/decentro-in-collections-sdk
2 changes: 1 addition & 1 deletion customers/decentro/decentro-in-kyc-sdk
2 changes: 1 addition & 1 deletion customers/eyelevel/groundx-sdks
2 changes: 1 addition & 1 deletion customers/newscatcher/newscatcher-sdks
5 changes: 5 additions & 0 deletions generator/konfig-dash/.changeset/unlucky-adults-invite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'konfig-lib': minor
---

add "order" property to konfig.yaml for ordering operations in API reference page
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,63 @@ export const readmeHeader = z
.optional()
.describe('Call to action to be displayed in SDKs README.md')

// Define an operation, which can be either an operationId or a combination of subpath and HTTP method
const Operation = z.union([
z
.string()
.describe(
'This represents the operationId from the OpenAPI specification.'
),
z
.object({
path: z.string().describe("This represents the operation's subpath."),
method: z
.string()
.describe("This represents the operation's HTTP method."),
})
.describe("This represents the operation's subpath and HTTP method."),
])

// Define a schema for a tag along with its associated operations
const TagWithOperations = z
.object({
tag: z
.string()
.describe('This represents the tag name from the OpenAPI specification.'),
operations: z
.array(Operation)
.optional()
.describe(
'An ordered list of operations associated with the tag. Each operation can be an operationId or a combination of subpath and HTTP method.'
),
})
.describe(
'A schema that represents a tag and its associated operations in a user-defined order.'
)

// Define the main schema for the API order configuration
const ApiOrderConfigurationSchema = z
.array(TagWithOperations)
.describe(
'An ordered list of tags, where each tag has its associated operations. This represents the user-defined order for displaying tags and operations in the API documentation.'
)

export type ApiOrderConfiguration = z.infer<typeof ApiOrderConfigurationSchema>

export const KonfigYamlCommon = z
.object({
primaryColor,
portal,
order: ApiOrderConfigurationSchema.optional(),
readmeHeader,
readmeOperation: z
.object({
operationId: z.string(),
})
.optional(),
.optional()
.describe(
`Operation to be displayed in "Getting Started" section of SDKs README.md`
),
portalTitle: z
.string()
.optional()
Expand Down Expand Up @@ -258,6 +305,7 @@ export const KonfigYamlCommon = z
)
.optional(),
})
.passthrough()
.merge(requiredEnvironmentVariablesConfig)

export type KonfigYamlCommonType = z.infer<typeof KonfigYamlCommon>
Expand Down
1 change: 1 addition & 0 deletions generator/konfig-dash/packages/konfig-lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ export * from './forEachReferenceUntyped'
export * from './recurseObject'
export * from './snaptrade-demo'
export * from './util/find-repository'
export * from './util/order-openapi-specification'
export * from './util/konfig-api-key-header'
2 changes: 2 additions & 0 deletions generator/konfig-dash/packages/konfig-lib/src/parseSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { convertSwaggerToOAS3 } from './convertSwaggerToOAS3'

export type SchemaObject = OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject

export type PathsObject = OpenAPIV3.PathsObject | OpenAPIV3_1.PathsObject

export type RequestBodyObject =
| OpenAPIV3.RequestBodyObject
| OpenAPIV3_1.RequestBodyObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import camelcase from './util/camelcase'
import { HttpMethods } from './forEachOperation'
import { transformInnerSchemas } from './util/transform-inner-schemas'
import { convertOneOfSchemasToAny } from './convert-one-of-schemas-to-any'
import { orderOpenApiSpecification } from './util/order-openapi-specification'

export const doNotGenerateVendorExtension = 'x-do-not-generate'

Expand Down Expand Up @@ -60,13 +61,18 @@ export const transformSpec = async ({
infoContactName,
infoContactUrl,
fixConfig,
order,
doNotValidateGloballyRequiredSecurity,
removeRequiredProperties,
}: Options): Promise<string> => {
const spec = await parseSpec(specString)

if (!spec.spec.paths) throw Error('"path" is not an array')

if (order !== undefined) {
orderOpenApiSpecification({ spec: spec.spec, order })
}

// recurse through entire spec and shorten any strings that are grater than
// 65535 bytes by taking out middle sections of the string
recurseObject(spec.spec, ({ value: text, parent, path }) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { Spec } from '../parseSpec'
import { orderOpenApiSpecification } from './order-openapi-specification'

describe('orderOpenApiSpecification', () => {
it('should order tags and operations based on user configuration', () => {
const spec: Spec['spec'] = {
openapi: '3.0.0',
info: {
title: 'Test',
version: '1.0.0',
},
paths: {
'/test4': {
get: {
tags: ['test4'],
operationId: 'test4',
responses: {},
},
},
'/test3': {
get: {
tags: ['test3'],
operationId: 'test3',
responses: {},
},
},
'/test': {
get: {
tags: ['test'],
operationId: 'test',
responses: {},
},
},
'/test-x': {
get: {
tags: ['test'],
operationId: 'test-x',
responses: {},
},
},
'/test2': {
get: {
tags: ['test2'],
operationId: 'test2',
responses: {},
},
},
},
tags: [
{
name: 'test2',
},
{
name: 'test',
},
{
name: 'test4',
},
{
name: 'test3',
},
],
}

const orderedSpec: Spec['spec'] = {
openapi: '3.0.0',
info: {
title: 'Test',
version: '1.0.0',
},
paths: {
'/test-x': {
get: {
tags: ['test'],
operationId: 'test-x',
responses: {},
},
},
'/test': {
get: {
tags: ['test'],
operationId: 'test',
responses: {},
},
},
'/test2': {
get: {
tags: ['test2'],
operationId: 'test2',
responses: {},
},
},
'/test4': {
get: {
tags: ['test4'],
operationId: 'test4',
responses: {},
},
},
'/test3': {
get: {
tags: ['test3'],
operationId: 'test3',
responses: {},
},
},
},
tags: [
{
name: 'test',
},
{
name: 'test2',
},
{
name: 'test4',
},
{
name: 'test3',
},
],
}

orderOpenApiSpecification({
spec,
order: [
{
tag: 'test',
operations: [
'test-x',
{
path: '/test',
method: 'get',
},
],
},
{
tag: 'test2',
},
],
})

expect(spec.tags).toStrictEqual(orderedSpec.tags)
expect(Object.keys(spec.paths)).toStrictEqual(
Object.keys(orderedSpec.paths)
)
})
})
Loading

0 comments on commit 99310fc

Please sign in to comment.