Skip to content

Commit

Permalink
feat: Introduce draft property (#110)
Browse files Browse the repository at this point in the history
* Support marking props, routes and namspaces as draft

* Test new feature

* ci: Format code

* ci: Generate code

* ci: Generate code

---------

Co-authored-by: Seam Bot <devops@getseam.com>
  • Loading branch information
andrii-balitskyi and seambot authored Oct 7, 2024
1 parent aef37eb commit 60b5598
Show file tree
Hide file tree
Showing 12 changed files with 1,954 additions and 677 deletions.
2 changes: 2 additions & 0 deletions src/lib/blueprint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ test('createProperties: uses provided values', (t) => {
deprecated: true,
'x-deprecated': 'This property is deprecated',
'x-undocumented': 'true',
'x-draft': 'true',
},
}

Expand Down Expand Up @@ -77,6 +78,7 @@ test('createProperties: uses provided values', (t) => {
property.isUndocumented,
'isUndocumented should be true when x-undocumented is provided',
)
t.true(property.isDraft, 'isDraft should be true when x-draft is provided')
})

const postEndpoint: OpenapiOperation = {
Expand Down
20 changes: 20 additions & 0 deletions src/lib/blueprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface Route {
subroutes: Route[]
isUndocumented: boolean
isDeprecated: boolean
isDraft: boolean
}

export interface Resource {
Expand All @@ -44,6 +45,7 @@ export interface Namespace {
path: string
isDeprecated: boolean
isUndocumented: boolean
isDraft: boolean
}

export interface Endpoint {
Expand All @@ -53,6 +55,7 @@ export interface Endpoint {
description: string
isUndocumented: boolean
isDeprecated: boolean
isDraft: boolean
deprecationMessage: string
request: Request
response: Response
Expand All @@ -64,6 +67,7 @@ interface BaseParameter {
isRequired: boolean
isUndocumented: boolean
isDeprecated: boolean
isDraft: boolean
deprecationMessage: string
description: string
}
Expand Down Expand Up @@ -161,6 +165,7 @@ interface BaseProperty {
isDeprecated: boolean
deprecationMessage: string
isUndocumented: boolean
isDraft: boolean
}

export type Property =
Expand Down Expand Up @@ -318,6 +323,7 @@ const createRoutes = async (
return routes
.map(addIsDeprecatedToRoute)
.map(addIsUndocumentedToRoute)
.map(addIsDraftToRoute)
.map(addNamespaceStatusToRoute)
}

Expand Down Expand Up @@ -377,12 +383,14 @@ const createRoute = async (
path: namespace,
isDeprecated: false,
isUndocumented: false,
isDraft: false,
}
: null,
endpoints: await createEndpoints(path, pathItem, context),
subroutes: [],
isUndocumented: false,
isDeprecated: false,
isDraft: false,
}
}

Expand All @@ -396,6 +404,11 @@ const addIsUndocumentedToRoute = (route: Route): Route => ({
isUndocumented: route.endpoints.every((endpoint) => endpoint.isUndocumented),
})

const addIsDraftToRoute = (route: Route): Route => ({
...route,
isDraft: route.endpoints.every((endpoint) => endpoint.isDraft),
})

const addNamespaceStatusToRoute = (
route: Route,
_idx: number,
Expand All @@ -408,13 +421,15 @@ const addNamespaceStatusToRoute = (
)
const isNamespaceDeprecated = namespaceRoutes.every((r) => r.isDeprecated)
const isNamespaceUndocumented = namespaceRoutes.every((r) => r.isUndocumented)
const isNamespaceDraft = namespaceRoutes.every((r) => r.isDraft)

return {
...route,
namespace: {
...route.namespace,
isDeprecated: isNamespaceDeprecated,
isUndocumented: isNamespaceUndocumented,
isDraft: isNamespaceDraft,
},
}
}
Expand Down Expand Up @@ -472,6 +487,8 @@ const createEndpoint = async (

const isDeprecated = parsedOperation.deprecated

const isDraft = parsedOperation['x-draft'].length > 0

const deprecationMessage = parsedOperation['x-deprecated']

const request = createRequest(methods, operation, path)
Expand All @@ -483,6 +500,7 @@ const createEndpoint = async (
description,
isUndocumented,
isDeprecated,
isDraft,
deprecationMessage,
response: createResponse(operation, path),
request,
Expand Down Expand Up @@ -600,6 +618,7 @@ const createParameter = (
isDeprecated: parsedProp['x-deprecated'].length > 0,
deprecationMessage: parsedProp['x-deprecated'],
isUndocumented: parsedProp['x-undocumented'].length > 0,
isDraft: parsedProp['x-draft'].length > 0,
}

switch (parsedProp.type) {
Expand Down Expand Up @@ -803,6 +822,7 @@ const createProperty = (
isDeprecated: parsedProp['x-deprecated'].length > 0,
deprecationMessage: parsedProp['x-deprecated'],
isUndocumented: parsedProp['x-undocumented'].length > 0,
isDraft: parsedProp['x-draft'].length > 0,
}

switch (parsedProp.type) {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/openapi-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const ParameterSchema = z.object({
deprecated: z.boolean().default(false),
'x-undocumented': z.string().default(''),
'x-deprecated': z.string().default(''),
'x-draft': z.string().default(''),
})

const ResponseSchema = z.record(
Expand Down Expand Up @@ -63,6 +64,7 @@ export const OpenapiOperationSchema = z.object({
'x-title': z.string().default(''),
'x-undocumented': z.string().default(''),
'x-deprecated': z.string().default(''),
'x-draft': z.string().default(''),
})

export const PropertySchema: z.ZodSchema<any> = z.object({
Expand All @@ -71,6 +73,7 @@ export const PropertySchema: z.ZodSchema<any> = z.object({
deprecated: z.boolean().default(false),
'x-undocumented': z.string().default(''),
'x-deprecated': z.string().default(''),
'x-draft': z.string().default(''),
enum: z.array(z.string().or(z.boolean())).optional(),
$ref: z.string().optional(),
format: z.string().optional(),
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/types/code-sample-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,15 @@ export default [
body: {},
},
},
{
title: 'Draft endpoint',
description: 'This is a draft endpoint',
request: {
path: '/draft/endpoint',
parameters: {},
},
response: {
body: {},
},
},
]
31 changes: 31 additions & 0 deletions test/fixtures/types/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export default {
type: 'string',
'x-undocumented': 'This prop is intentionally left undocumented.',
},
draft_prop: {
description: 'This prop is draft',
type: 'string',
'x-draft': 'This prop is intentionally left draft.',
},
nullable_prop: {
description: 'This prop is nullable',
type: 'string',
Expand Down Expand Up @@ -245,5 +250,31 @@ export default {
'x-title': 'Deprecated and undocumented endpoint',
},
},
'/draft/endpoint': {
get: {
operationId: 'draftEndpointGet',
responses: {
200: {
content: {
'application/json': {
schema: {
properties: {
ok: { type: 'boolean' },
},
required: ['ok'],
type: 'object',
},
},
},
description: 'Draft endpoint',
},
},
security: [],
summary: '/draft/endpoint',
tags: ['/draft'],
'x-draft': 'true',
'x-title': 'Draft endpoint',
},
},
},
}
5 changes: 5 additions & 0 deletions test/fixtures/types/route-specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@ export const routes = {
methods: ['GET'],
jsonResponse: z.object({}),
},
'/draft/endpoint': {
auth: 'none',
methods: ['GET'],
jsonResponse: z.object({}),
},
},
} as const
11 changes: 11 additions & 0 deletions test/fixtures/types/route-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Routes {
name: string
deprecated_prop?: string
undocumented_prop?: string
draft_prop?: string
nullable_prop?: string
number_prop?: number
object_prop?: Record<string, string>
Expand All @@ -32,6 +33,7 @@ export interface Routes {
name: string
deprecated_prop?: string
undocumented_prop?: string
draft_prop?: string
nullable_prop?: string
number_prop?: number
object_prop?: Record<string, string>
Expand Down Expand Up @@ -62,6 +64,15 @@ export interface Routes {
formData: Record<string, unknown>
jsonResponse: Record<string, never>
}
'/draft/endpoint': {
route: '/draft/endpoint'
method: 'GET'
queryParams: Record<string, unknown>
jsonBody: Record<string, unknown>
commonParams: Record<string, unknown>
formData: Record<string, unknown>
jsonResponse: Record<string, never>
}
}

export type RouteResponse<Path extends keyof Routes> =
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/types/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const foo = z.object({
name: z.string(),
deprecated_prop: z.string().optional(),
undocumented_prop: z.string().optional(),
draft_prop: z.string().optional(),
nullable_prop: z.string().optional().nullable(),
number_prop: z.number().optional(),
object_prop: z.record(z.string(), z.any()).optional(),
Expand Down
Loading

0 comments on commit 60b5598

Please sign in to comment.