docs-util: extract feature flags in generated OAS (#12554)
This commit is contained in:
@@ -605,10 +605,12 @@ class DefaultKindGenerator<T extends ts.Node = ts.Node> {
|
|||||||
getInformationFromTags(node: ts.Node): {
|
getInformationFromTags(node: ts.Node): {
|
||||||
deprecatedTag: ts.JSDocTag | undefined
|
deprecatedTag: ts.JSDocTag | undefined
|
||||||
versionTag: ts.JSDocTag | undefined
|
versionTag: ts.JSDocTag | undefined
|
||||||
|
featureFlagTag: ts.JSDocTag | undefined
|
||||||
} {
|
} {
|
||||||
const nodeComments = ts.getJSDocCommentsAndTags(node)
|
const nodeComments = ts.getJSDocCommentsAndTags(node)
|
||||||
let deprecatedTag: ts.JSDocTag | undefined
|
let deprecatedTag: ts.JSDocTag | undefined
|
||||||
let versionTag: ts.JSDocTag | undefined
|
let versionTag: ts.JSDocTag | undefined
|
||||||
|
let featureFlagTag: ts.JSDocTag | undefined
|
||||||
|
|
||||||
nodeComments.forEach((comment) => {
|
nodeComments.forEach((comment) => {
|
||||||
if (!("tags" in comment)) {
|
if (!("tags" in comment)) {
|
||||||
@@ -623,12 +625,17 @@ class DefaultKindGenerator<T extends ts.Node = ts.Node> {
|
|||||||
if (tag.tagName.getText() === "version") {
|
if (tag.tagName.getText() === "version") {
|
||||||
versionTag = tag
|
versionTag = tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tag.tagName.getText() === "featureFlag") {
|
||||||
|
featureFlagTag = tag
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
deprecatedTag,
|
deprecatedTag,
|
||||||
versionTag,
|
versionTag,
|
||||||
|
featureFlagTag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,7 +435,8 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check deprecation and version in tags
|
// check deprecation and version in tags
|
||||||
const { deprecatedTag, versionTag } = this.getInformationFromTags(node)
|
const { deprecatedTag, versionTag, featureFlagTag } =
|
||||||
|
this.getInformationFromTags(node)
|
||||||
|
|
||||||
if (deprecatedTag) {
|
if (deprecatedTag) {
|
||||||
oas.deprecated = true
|
oas.deprecated = true
|
||||||
@@ -450,6 +451,12 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (featureFlagTag) {
|
||||||
|
oas["x-featureFlag"] = featureFlagTag.comment
|
||||||
|
? (featureFlagTag.comment as string)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
return formatOas(oas, oasPrefix)
|
return formatOas(oas, oasPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +791,8 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check deprecation and version in tags
|
// check deprecation and version in tags
|
||||||
const { deprecatedTag, versionTag } = this.getInformationFromTags(node)
|
const { deprecatedTag, versionTag, featureFlagTag } =
|
||||||
|
this.getInformationFromTags(node)
|
||||||
|
|
||||||
if (deprecatedTag) {
|
if (deprecatedTag) {
|
||||||
oas.deprecated = true
|
oas.deprecated = true
|
||||||
@@ -804,6 +812,14 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
delete oas["x-version"]
|
delete oas["x-version"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (featureFlagTag) {
|
||||||
|
oas["x-featureFlag"] = featureFlagTag.comment
|
||||||
|
? (featureFlagTag.comment as string)
|
||||||
|
: undefined
|
||||||
|
} else {
|
||||||
|
delete oas["x-featureFlag"]
|
||||||
|
}
|
||||||
|
|
||||||
return formatOas(oas, oasPrefix)
|
return formatOas(oas, oasPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1562,6 +1578,27 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
})
|
})
|
||||||
}) || undefined // avoid showing it as false in the generated OAS
|
}) || undefined // avoid showing it as false in the generated OAS
|
||||||
|
|
||||||
|
let featureFlag: string | undefined
|
||||||
|
|
||||||
|
commentsAndTags.some((comment) => {
|
||||||
|
if (!("tags" in comment)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
comment.tags?.some((tag) => {
|
||||||
|
if (tag.tagName.getText() !== "featureFlag" || !tag.comment) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
featureFlag =
|
||||||
|
typeof tag.comment === "string" ? tag.comment : tag.comment.join(" ")
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return featureFlag !== undefined
|
||||||
|
})
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case isEnum || isEnumParent:
|
case isEnum || isEnumParent:
|
||||||
const enumMembers: string[] = []
|
const enumMembers: string[] = []
|
||||||
@@ -1584,6 +1621,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
description,
|
description,
|
||||||
enum: enumMembers,
|
enum: enumMembers,
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case itemType.isLiteral() || typeAsString === "RegExp":
|
case itemType.isLiteral() || typeAsString === "RegExp":
|
||||||
const isString =
|
const isString =
|
||||||
@@ -1602,6 +1640,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
name: title,
|
name: title,
|
||||||
}),
|
}),
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case itemType.flags === ts.TypeFlags.String ||
|
case itemType.flags === ts.TypeFlags.String ||
|
||||||
itemType.flags === ts.TypeFlags.Number ||
|
itemType.flags === ts.TypeFlags.Number ||
|
||||||
@@ -1622,6 +1661,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
name: title,
|
name: title,
|
||||||
}),
|
}),
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case ("intrinsicName" in itemType &&
|
case ("intrinsicName" in itemType &&
|
||||||
itemType.intrinsicName === "boolean") ||
|
itemType.intrinsicName === "boolean") ||
|
||||||
@@ -1634,6 +1674,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
? this.getDefaultValue(symbol?.valueDeclaration)
|
? this.getDefaultValue(symbol?.valueDeclaration)
|
||||||
: undefined,
|
: undefined,
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case this.checker.isArrayType(itemType):
|
case this.checker.isArrayType(itemType):
|
||||||
return {
|
return {
|
||||||
@@ -1656,6 +1697,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
saveSchema,
|
saveSchema,
|
||||||
...rest,
|
...rest,
|
||||||
}),
|
}),
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case itemType.isUnion():
|
case itemType.isUnion():
|
||||||
// if it's a union of literal types,
|
// if it's a union of literal types,
|
||||||
@@ -1675,6 +1717,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
enum: cleanedUpTypes.map(
|
enum: cleanedUpTypes.map(
|
||||||
(unionType) => (unionType as ts.LiteralType).value
|
(unionType) => (unionType as ts.LiteralType).value
|
||||||
),
|
),
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1690,12 +1733,17 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (oneOfItems.length === 1) {
|
if (oneOfItems.length === 1) {
|
||||||
return oneOfItems[0]
|
return {
|
||||||
|
...oneOfItems[0],
|
||||||
|
"x-featureFlag": oneOfItems[0]["x-featureFlag"] || featureFlag,
|
||||||
|
deprecated: oneOfItems[0].deprecated || isDeprecated,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
oneOf: oneOfItems,
|
oneOf: oneOfItems,
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case itemType.isIntersection():
|
case itemType.isIntersection():
|
||||||
const allOfItems = this.typesHelper
|
const allOfItems = this.typesHelper
|
||||||
@@ -1712,12 +1760,17 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (allOfItems.length === 1) {
|
if (allOfItems.length === 1) {
|
||||||
return allOfItems[0]
|
return {
|
||||||
|
...allOfItems[0],
|
||||||
|
"x-featureFlag": allOfItems[0]["x-featureFlag"] || featureFlag,
|
||||||
|
deprecated: allOfItems[0].deprecated || isDeprecated,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allOf: allOfItems,
|
allOf: allOfItems,
|
||||||
deprecated: isDeprecated,
|
deprecated: isDeprecated,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
case typeAsString.startsWith("Pick"):
|
case typeAsString.startsWith("Pick"):
|
||||||
const pickTypeArgs =
|
const pickTypeArgs =
|
||||||
@@ -1807,6 +1860,7 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
: undefined,
|
: undefined,
|
||||||
// this is changed later
|
// this is changed later
|
||||||
required: undefined,
|
required: undefined,
|
||||||
|
"x-featureFlag": featureFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties: Record<
|
const properties: Record<
|
||||||
@@ -2472,6 +2526,19 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldSchemaObj?.["x-featureFlag"] !== newSchemaObj?.["x-featureFlag"]) {
|
||||||
|
// avoid many changes to exising OAS
|
||||||
|
if (!newSchemaObj?.["x-featureFlag"]) {
|
||||||
|
if (oldSchemaObj!["x-featureFlag"]) {
|
||||||
|
wasUpdated = true
|
||||||
|
}
|
||||||
|
delete oldSchemaObj!["x-featureFlag"]
|
||||||
|
} else {
|
||||||
|
oldSchemaObj!["x-featureFlag"] = newSchemaObj["x-featureFlag"]
|
||||||
|
wasUpdated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!wasUpdated) {
|
if (!wasUpdated) {
|
||||||
const requiredChanged =
|
const requiredChanged =
|
||||||
oldSchemaObj!.required?.length !== newSchemaObj?.required?.length ||
|
oldSchemaObj!.required?.length !== newSchemaObj?.required?.length ||
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export declare type OpenApiOperation = Partial<OpenAPIV3.OperationObject> & {
|
|||||||
"x-events"?: OasEvent[]
|
"x-events"?: OasEvent[]
|
||||||
"x-deprecated_message"?: string
|
"x-deprecated_message"?: string
|
||||||
"x-version"?: string
|
"x-version"?: string
|
||||||
|
"x-featureFlag"?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare type CommonCliOptions = {
|
export declare type CommonCliOptions = {
|
||||||
@@ -23,6 +24,7 @@ export declare type CommonCliOptions = {
|
|||||||
|
|
||||||
export declare type OpenApiSchema = OpenAPIV3.SchemaObject & {
|
export declare type OpenApiSchema = OpenAPIV3.SchemaObject & {
|
||||||
"x-schemaName"?: string
|
"x-schemaName"?: string
|
||||||
|
"x-featureFlag"?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare interface OpenApiTagObject extends OpenAPIV3.TagObject {
|
export declare interface OpenApiTagObject extends OpenAPIV3.TagObject {
|
||||||
|
|||||||
Reference in New Issue
Block a user