docs: support since, deprecated, and feature flag tags in dml reference (#13741)
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Badge, Tooltip } from "@/components"
|
||||||
|
|
||||||
|
export type DeprecatedNoticeProps = {
|
||||||
|
description?: string
|
||||||
|
tooltipTextClassName?: string
|
||||||
|
badgeClassName?: string
|
||||||
|
badgeContent?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeprecatedNotice = ({
|
||||||
|
description,
|
||||||
|
tooltipTextClassName,
|
||||||
|
badgeClassName,
|
||||||
|
badgeContent = `Deprecated`,
|
||||||
|
}: DeprecatedNoticeProps) => {
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
tooltipChildren={
|
||||||
|
<span className={tooltipTextClassName}>
|
||||||
|
{description ||
|
||||||
|
"This feature is deprecated and may be removed in future releases."}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
clickable
|
||||||
|
>
|
||||||
|
<Badge variant="neutral" className={badgeClassName}>
|
||||||
|
{badgeContent}
|
||||||
|
</Badge>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Badge, Tooltip } from "@/components"
|
||||||
|
|
||||||
|
export type VersionNoticeProps = {
|
||||||
|
version: string
|
||||||
|
tooltipTextClassName?: string
|
||||||
|
badgeClassName?: string
|
||||||
|
badgeContent?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VersionNotice = ({
|
||||||
|
version,
|
||||||
|
tooltipTextClassName,
|
||||||
|
badgeClassName,
|
||||||
|
badgeContent = `v${version}`,
|
||||||
|
}: VersionNoticeProps) => {
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
tooltipChildren={
|
||||||
|
<span className={tooltipTextClassName}>
|
||||||
|
This is available starting from
|
||||||
|
<br />
|
||||||
|
<a
|
||||||
|
href={`https://github.com/medusajs/medusa/releases/tag/${version}`}
|
||||||
|
>
|
||||||
|
Medusa v{version}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
clickable
|
||||||
|
>
|
||||||
|
<Badge variant="blue" className={badgeClassName}>
|
||||||
|
{badgeContent}
|
||||||
|
</Badge>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@ import {
|
|||||||
import { decodeStr, isInView } from "@/utils"
|
import { decodeStr, isInView } from "@/utils"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { useIsBrowser, useSiteConfig } from "../../.."
|
import { useIsBrowser, useSiteConfig } from "../../.."
|
||||||
|
import { VersionNotice } from "../../Notices/VersionNotice"
|
||||||
|
import { DeprecatedNotice } from "../../Notices/DeprecatedNotice"
|
||||||
|
|
||||||
type CommonProps = ParentCommonProps & {
|
type CommonProps = ParentCommonProps & {
|
||||||
level?: number
|
level?: number
|
||||||
@@ -236,6 +238,15 @@ const TypeListItem = ({
|
|||||||
badgeContent={<ArrowsPointingOutMini />}
|
badgeContent={<ArrowsPointingOutMini />}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{item.since && (
|
||||||
|
<VersionNotice
|
||||||
|
version={item.since}
|
||||||
|
badgeClassName="!p-0 leading-none"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{item.deprecated?.is_deprecated && (
|
||||||
|
<DeprecatedNotice description={item.deprecated?.description} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DetailsSummary>
|
</DetailsSummary>
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ export type Type = {
|
|||||||
featureFlag?: string
|
featureFlag?: string
|
||||||
expandable: boolean
|
expandable: boolean
|
||||||
children?: Type[]
|
children?: Type[]
|
||||||
|
deprecated?: {
|
||||||
|
is_deprecated: boolean
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
since?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParameterTypesType = {
|
type ParameterTypesType = {
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ export * from "./Details/Summary"
|
|||||||
export * from "./DetailsList"
|
export * from "./DetailsList"
|
||||||
export * from "./DottedSeparator"
|
export * from "./DottedSeparator"
|
||||||
export * from "./EditButton"
|
export * from "./EditButton"
|
||||||
export * from "./ExpandableNotice"
|
export * from "./Notices/ExpandableNotice"
|
||||||
export * from "./FeatureFlagNotice"
|
export * from "./Notices/FeatureFlagNotice"
|
||||||
|
export * from "./Notices/DeprecatedNotice"
|
||||||
|
export * from "./Notices/VersionNotice"
|
||||||
export * from "./Feedback"
|
export * from "./Feedback"
|
||||||
export * from "./Feedback/Solutions"
|
export * from "./Feedback/Solutions"
|
||||||
export * from "./Footer"
|
export * from "./Footer"
|
||||||
|
|||||||
@@ -606,14 +606,22 @@ class DefaultKindGenerator<T extends ts.Node = ts.Node> {
|
|||||||
deprecatedTag: ts.JSDocTag | undefined
|
deprecatedTag: ts.JSDocTag | undefined
|
||||||
sinceTag: ts.JSDocTag | undefined
|
sinceTag: ts.JSDocTag | undefined
|
||||||
featureFlagTag: ts.JSDocTag | undefined
|
featureFlagTag: ts.JSDocTag | undefined
|
||||||
|
summary: string | undefined
|
||||||
} {
|
} {
|
||||||
const nodeComments = ts.getJSDocCommentsAndTags(node)
|
const nodeComments = ts.getJSDocCommentsAndTags(node)
|
||||||
let deprecatedTag: ts.JSDocTag | undefined
|
let deprecatedTag: ts.JSDocTag | undefined
|
||||||
let sinceTag: ts.JSDocTag | undefined
|
let sinceTag: ts.JSDocTag | undefined
|
||||||
let featureFlagTag: ts.JSDocTag | undefined
|
let featureFlagTag: ts.JSDocTag | undefined
|
||||||
|
let summary: string | undefined
|
||||||
|
|
||||||
nodeComments.forEach((comment) => {
|
nodeComments.forEach((comment) => {
|
||||||
if (!("tags" in comment)) {
|
if (!("tags" in comment)) {
|
||||||
|
if (ts.isJSDoc(comment) && comment.comment) {
|
||||||
|
summary =
|
||||||
|
typeof comment.comment === "string"
|
||||||
|
? comment.comment
|
||||||
|
: comment.comment.map((part) => part.text).join(" ")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,9 +644,22 @@ class DefaultKindGenerator<T extends ts.Node = ts.Node> {
|
|||||||
deprecatedTag,
|
deprecatedTag,
|
||||||
sinceTag,
|
sinceTag,
|
||||||
featureFlagTag,
|
featureFlagTag,
|
||||||
|
summary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatJSDocTag(tag: ts.JSDocTag | undefined): string | undefined {
|
||||||
|
if (!tag) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof tag.comment === "string") {
|
||||||
|
return tag.comment
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag.comment?.map((part) => part.text).join(" ")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a node is ignored.
|
* Check if a node is ignored.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -101,10 +101,24 @@ class DmlKindGenerator extends DefaultKindGenerator<ts.CallExpression> {
|
|||||||
dataModelName,
|
dataModelName,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use parent to get tags like since, deprecated, featureFlag
|
||||||
|
*/
|
||||||
|
const parent = node.parent?.parent?.parent
|
||||||
|
|
||||||
|
const { sinceTag, deprecatedTag, featureFlagTag } =
|
||||||
|
this.getInformationFromTags(parent)
|
||||||
|
|
||||||
const dmlFile: DmlFile = {
|
const dmlFile: DmlFile = {
|
||||||
[dataModelName]: {
|
[dataModelName]: {
|
||||||
filePath: getBasePath(node.getSourceFile().fileName),
|
filePath: getBasePath(node.getSourceFile().fileName),
|
||||||
properties,
|
properties,
|
||||||
|
since: this.formatJSDocTag(sinceTag),
|
||||||
|
deprecated: {
|
||||||
|
is_deprecated: !!deprecatedTag,
|
||||||
|
description: this.formatJSDocTag(deprecatedTag),
|
||||||
|
},
|
||||||
|
featureFlag: this.formatJSDocTag(featureFlagTag),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +243,11 @@ class DmlKindGenerator extends DefaultKindGenerator<ts.CallExpression> {
|
|||||||
)
|
)
|
||||||
const isBoolean = propertyTypeStr.includes("BooleanProperty")
|
const isBoolean = propertyTypeStr.includes("BooleanProperty")
|
||||||
const relationName = isRelation ? camelToWords(propertyName) : undefined
|
const relationName = isRelation ? camelToWords(propertyName) : undefined
|
||||||
|
const { summary, sinceTag, deprecatedTag, featureFlagTag } =
|
||||||
|
this.getInformationFromTags(propertyNode)
|
||||||
|
|
||||||
let propertyDescription =
|
let propertyDescription =
|
||||||
|
summary ||
|
||||||
this.knowledgeBaseFactory.tryToGetObjectPropertySummary({
|
this.knowledgeBaseFactory.tryToGetObjectPropertySummary({
|
||||||
retrieveOptions: {
|
retrieveOptions: {
|
||||||
str: propertyName,
|
str: propertyName,
|
||||||
@@ -251,6 +268,24 @@ class DmlKindGenerator extends DefaultKindGenerator<ts.CallExpression> {
|
|||||||
propertyDescription += `\n\n@expandable`
|
propertyDescription += `\n\n@expandable`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sinceTag) {
|
||||||
|
propertyDescription += `\n\n@since ${
|
||||||
|
this.formatJSDocTag(sinceTag) ?? ""
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlagTag) {
|
||||||
|
propertyDescription += `\n\n@featureFlag ${
|
||||||
|
this.formatJSDocTag(featureFlagTag) ?? ""
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedTag) {
|
||||||
|
propertyDescription += `\n\n@deprecated ${
|
||||||
|
this.formatJSDocTag(deprecatedTag) ?? ""
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
properties[propertyName] = propertyDescription
|
properties[propertyName] = propertyDescription
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import path from "path"
|
|||||||
import {
|
import {
|
||||||
Application,
|
Application,
|
||||||
Comment,
|
Comment,
|
||||||
|
CommentTag,
|
||||||
Context,
|
Context,
|
||||||
Converter,
|
Converter,
|
||||||
DeclarationReflection,
|
DeclarationReflection,
|
||||||
@@ -12,6 +13,9 @@ import { getDirname, getDmlProperties, isDmlEntity } from "utils"
|
|||||||
import { DmlFile } from "types"
|
import { DmlFile } from "types"
|
||||||
|
|
||||||
const FILE_NAME_REGEX = /packages\/modules\/(?<module>[a-z-]+)/
|
const FILE_NAME_REGEX = /packages\/modules\/(?<module>[a-z-]+)/
|
||||||
|
const SINCE_REGEX = /@since\s+([\d.]+)/
|
||||||
|
const DEPRECATED_REGEX = /@deprecated\s+(.+)/
|
||||||
|
const FEATURE_FLAG_REGEX = /@featureFlag\s+(\S+)/
|
||||||
|
|
||||||
export function load(app: Application) {
|
export function load(app: Application) {
|
||||||
app.converter.on(
|
app.converter.on(
|
||||||
@@ -76,6 +80,41 @@ function getDescriptionsFromJson(
|
|||||||
if (!jsonFileContent[reflection.name]) {
|
if (!jsonFileContent[reflection.name]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const comment = reflection.comment || new Comment()
|
||||||
|
|
||||||
|
if (jsonFileContent[reflection.name].since) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@since", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: jsonFileContent[reflection.name].since!,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonFileContent[reflection.name].deprecated?.is_deprecated) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@deprecated", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: jsonFileContent[reflection.name].deprecated!.description || "",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonFileContent[reflection.name].featureFlag) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@featureFlag", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: jsonFileContent[reflection.name].featureFlag!,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
reflection.comment = comment
|
||||||
|
|
||||||
Object.entries(jsonFileContent[reflection.name].properties).forEach(
|
Object.entries(jsonFileContent[reflection.name].properties).forEach(
|
||||||
([propertyName, description]) => {
|
([propertyName, description]) => {
|
||||||
@@ -90,16 +129,57 @@ function getDescriptionsFromJson(
|
|||||||
const comment = propertyReflection.comment || new Comment()
|
const comment = propertyReflection.comment || new Comment()
|
||||||
|
|
||||||
const isExpandable = description.includes("@expandable")
|
const isExpandable = description.includes("@expandable")
|
||||||
|
const sinceMatch = description.match(SINCE_REGEX)
|
||||||
|
const featureFlagMatch = description.match(FEATURE_FLAG_REGEX)
|
||||||
|
const deprecatedMatch = description.match(DEPRECATED_REGEX)
|
||||||
|
|
||||||
comment.summary.push({
|
comment.summary.push({
|
||||||
kind: "text",
|
kind: "text",
|
||||||
text: description.replace("@expandable", "").trim(),
|
text: description
|
||||||
|
.replace("@expandable", "")
|
||||||
|
.replace(SINCE_REGEX, "")
|
||||||
|
.replace(FEATURE_FLAG_REGEX, "")
|
||||||
|
.replace(DEPRECATED_REGEX, "")
|
||||||
|
.trim(),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isExpandable) {
|
if (isExpandable) {
|
||||||
comment.modifierTags.add("@expandable")
|
comment.modifierTags.add("@expandable")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sinceMatch) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@since", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: sinceMatch[1],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureFlagMatch) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@featureFlag", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: featureFlagMatch[1],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedMatch) {
|
||||||
|
comment.blockTags.push(
|
||||||
|
new CommentTag("@deprecated", [
|
||||||
|
{
|
||||||
|
kind: "text",
|
||||||
|
text: deprecatedMatch[1],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
propertyReflection.comment = comment
|
propertyReflection.comment = comment
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ export default function () {
|
|||||||
|
|
||||||
const tagContent = sinceTag.content.map((content) => content.text).join("")
|
const tagContent = sinceTag.content.map((content) => content.text).join("")
|
||||||
|
|
||||||
return `:::note\n\nThis is available starting from Medusa \`v${tagContent}\`.\n\n:::`
|
return `:::note\n\nThis is available starting from [Medusa v${tagContent}](https://github.com/medusajs/medusa/releases/tag/v${tagContent}).\n\n:::`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{{version this}}}
|
||||||
|
|
||||||
{{{sourceCodeLink}}}
|
{{{sourceCodeLink}}}
|
||||||
|
|
||||||
{{{dmlProperties}}}
|
{{{dmlProperties}}}
|
||||||
@@ -34,4 +34,9 @@ export type Parameter = {
|
|||||||
featureFlag?: string
|
featureFlag?: string
|
||||||
expandable: boolean
|
expandable: boolean
|
||||||
children?: Parameter[]
|
children?: Parameter[]
|
||||||
|
since?: string
|
||||||
|
deprecated?: {
|
||||||
|
is_deprecated: boolean
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,10 @@ export function reflectionComponentFormatter({
|
|||||||
reflection.flags.isOptional ||
|
reflection.flags.isOptional ||
|
||||||
reflection.kind === ReflectionKind.EnumMember
|
reflection.kind === ReflectionKind.EnumMember
|
||||||
const comments = getComments(reflection)
|
const comments = getComments(reflection)
|
||||||
|
const deprecatedTag = comments?.blockTags.find(
|
||||||
|
(tag) => tag.tag === "@deprecated"
|
||||||
|
)
|
||||||
|
const sinceTag = comments?.blockTags.find((tag) => tag.tag === "@since")
|
||||||
const componentItem: Parameter = {
|
const componentItem: Parameter = {
|
||||||
name: reflection.name,
|
name: reflection.name,
|
||||||
type: reflection.type
|
type: reflection.type
|
||||||
@@ -160,6 +164,17 @@ export function reflectionComponentFormatter({
|
|||||||
children: [],
|
children: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sinceTag) {
|
||||||
|
componentItem.since = sinceTag.content.map((c) => c.text).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedTag) {
|
||||||
|
componentItem.deprecated = {
|
||||||
|
is_deprecated: true,
|
||||||
|
description: deprecatedTag?.content.map((c) => c.text).join(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (level + 1 > (maxLevel || MarkdownTheme.MAX_LEVEL)) {
|
if (level + 1 > (maxLevel || MarkdownTheme.MAX_LEVEL)) {
|
||||||
return componentItem
|
return componentItem
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -66,7 +66,12 @@ export function getReflectionTypeParameters({
|
|||||||
description = loadComment(typeName, project)
|
description = loadComment(typeName, project)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const deprecatedTag = comment?.blockTags.find(
|
||||||
|
(tag) => tag.tag === "@deprecated"
|
||||||
|
)
|
||||||
|
const sinceTag = comment?.blockTags.find((tag) => tag.tag === "@since")
|
||||||
|
|
||||||
|
const parameter: Parameter = {
|
||||||
name: "name" in reflectionType ? reflectionType.name : typeName,
|
name: "name" in reflectionType ? reflectionType.name : typeName,
|
||||||
type,
|
type,
|
||||||
optional:
|
optional:
|
||||||
@@ -84,6 +89,19 @@ export function getReflectionTypeParameters({
|
|||||||
featureFlag: Handlebars.helpers.featureFlag(comment),
|
featureFlag: Handlebars.helpers.featureFlag(comment),
|
||||||
children: [],
|
children: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sinceTag) {
|
||||||
|
parameter.since = sinceTag.content.map((c) => c.text).join("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedTag) {
|
||||||
|
parameter.deprecated = {
|
||||||
|
is_deprecated: true,
|
||||||
|
description: deprecatedTag?.content.map((c) => c.text).join(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentItem: Parameter[] = []
|
const componentItem: Parameter[] = []
|
||||||
|
|||||||
+6
@@ -307,6 +307,12 @@ export declare type DmlFile = {
|
|||||||
[k: string]: {
|
[k: string]: {
|
||||||
filePath: string
|
filePath: string
|
||||||
properties: DmlObject
|
properties: DmlObject
|
||||||
|
since?: string
|
||||||
|
deprecated?: {
|
||||||
|
is_deprecated: boolean
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
featureFlag?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user