From 0b08943edde8d12d59241e57d462a00772b0b2a5 Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Wed, 10 Dec 2025 11:33:00 +0100 Subject: [PATCH 1/7] chore: Simplify code --- src/components/extractor.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/components/extractor.ts b/src/components/extractor.ts index c3c937a..7e656b1 100644 --- a/src/components/extractor.ts +++ b/src/components/extractor.ts @@ -147,7 +147,7 @@ export function extractExports( const unknownExports: Array = []; for (const exportSymbol of exportSymbols) { if (exportSymbol.name === 'default') { - validateComponentType(componentName, exportSymbol, checker); + validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker); componentSymbol = exportSymbol; } else if (exportSymbol.name === `${componentName}Props`) { propsSymbol = exportSymbol; @@ -167,18 +167,7 @@ export function extractExports( return { componentSymbol, propsSymbol }; } -function validateComponentType(componentName: string, symbol: ts.Symbol, checker: ts.TypeChecker) { - const declaration = extractDeclaration(symbol); - let type: ts.Type; - if (ts.isExportAssignment(declaration)) { - // export default Something; - type = checker.getTypeAtLocation(declaration.expression); - } else if (ts.isFunctionDeclaration(declaration)) { - // export default function Something() {...} - type = checker.getTypeAtLocation(declaration); - } else { - throw new Error(`Unknown default export for ${componentName}`); - } +function validateComponentType(type: ts.Type, checker: ts.TypeChecker) { if ( // React.forwardRef type.getSymbol()?.name !== 'ForwardRefExoticComponent' && From 52e93a9cfefa0081d563ef186163991335e3d7fe Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 13:50:13 +0100 Subject: [PATCH 2/7] allow skipping exports validation --- src/components/extractor.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/extractor.ts b/src/components/extractor.ts index 7e656b1..961e477 100644 --- a/src/components/extractor.ts +++ b/src/components/extractor.ts @@ -151,7 +151,10 @@ export function extractExports( componentSymbol = exportSymbol; } else if (exportSymbol.name === `${componentName}Props`) { propsSymbol = exportSymbol; - } else if (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name)) { + } else if ( + !extraExports[componentName] || + (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*')) + ) { unknownExports.push(exportSymbol.name); } } From 564d69e2ebc2001899d7a818f1e397ef8ac0d986 Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 14:19:13 +0100 Subject: [PATCH 3/7] export built assets --- .gitignore | 1 - lib/LICENSE | 175 ++++++++++++++++++ lib/NOTICE | 1 + lib/README.md | 21 +++ lib/components/component-definition.d.ts | 4 + lib/components/component-definition.js | 119 ++++++++++++ lib/components/component-definition.js.map | 1 + .../extract-value-descriptions.d.ts | 3 + lib/components/extract-value-descriptions.js | 50 +++++ .../extract-value-descriptions.js.map | 1 + lib/components/extractor.d.ts | 23 +++ lib/components/extractor.js | 156 ++++++++++++++++ lib/components/extractor.js.map | 1 + lib/components/index.d.ts | 11 ++ lib/components/index.js | 65 +++++++ lib/components/index.js.map | 1 + lib/components/interfaces.d.ts | 81 ++++++++ lib/components/interfaces.js | 3 + lib/components/interfaces.js.map | 1 + lib/components/object-definition.d.ts | 6 + lib/components/object-definition.js | 115 ++++++++++++ lib/components/object-definition.js.map | 1 + lib/index.d.ts | 3 + lib/index.js | 26 +++ lib/index.js.map | 1 + lib/package.json | 51 +++++ lib/shared/bootstrap.d.ts | 2 + lib/shared/bootstrap.js | 48 +++++ lib/shared/bootstrap.js.map | 1 + lib/shared/type-utils.d.ts | 21 +++ lib/shared/type-utils.js | 90 +++++++++ lib/shared/type-utils.js.map | 1 + lib/test-utils/extractor.d.ts | 3 + lib/test-utils/extractor.js | 127 +++++++++++++ lib/test-utils/extractor.js.map | 1 + lib/test-utils/index.d.ts | 20 ++ lib/test-utils/index.js | 47 +++++ lib/test-utils/index.js.map | 1 + lib/test-utils/interfaces.d.ts | 33 ++++ lib/test-utils/interfaces.js | 3 + lib/test-utils/interfaces.js.map | 1 + package.json | 4 +- 42 files changed, 1321 insertions(+), 3 deletions(-) create mode 100644 lib/LICENSE create mode 100644 lib/NOTICE create mode 100644 lib/README.md create mode 100644 lib/components/component-definition.d.ts create mode 100644 lib/components/component-definition.js create mode 100644 lib/components/component-definition.js.map create mode 100644 lib/components/extract-value-descriptions.d.ts create mode 100644 lib/components/extract-value-descriptions.js create mode 100644 lib/components/extract-value-descriptions.js.map create mode 100644 lib/components/extractor.d.ts create mode 100644 lib/components/extractor.js create mode 100644 lib/components/extractor.js.map create mode 100644 lib/components/index.d.ts create mode 100644 lib/components/index.js create mode 100644 lib/components/index.js.map create mode 100644 lib/components/interfaces.d.ts create mode 100644 lib/components/interfaces.js create mode 100644 lib/components/interfaces.js.map create mode 100644 lib/components/object-definition.d.ts create mode 100644 lib/components/object-definition.js create mode 100644 lib/components/object-definition.js.map create mode 100644 lib/index.d.ts create mode 100644 lib/index.js create mode 100644 lib/index.js.map create mode 100644 lib/package.json create mode 100644 lib/shared/bootstrap.d.ts create mode 100644 lib/shared/bootstrap.js create mode 100644 lib/shared/bootstrap.js.map create mode 100644 lib/shared/type-utils.d.ts create mode 100644 lib/shared/type-utils.js create mode 100644 lib/shared/type-utils.js.map create mode 100644 lib/test-utils/extractor.d.ts create mode 100644 lib/test-utils/extractor.js create mode 100644 lib/test-utils/extractor.js.map create mode 100644 lib/test-utils/index.d.ts create mode 100644 lib/test-utils/index.js create mode 100644 lib/test-utils/index.js.map create mode 100644 lib/test-utils/interfaces.d.ts create mode 100644 lib/test-utils/interfaces.js create mode 100644 lib/test-utils/interfaces.js.map diff --git a/.gitignore b/.gitignore index bec6a4c..c63018e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ build -lib /node_modules coverage diff --git a/lib/LICENSE b/lib/LICENSE new file mode 100644 index 0000000..67db858 --- /dev/null +++ b/lib/LICENSE @@ -0,0 +1,175 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/lib/NOTICE b/lib/NOTICE new file mode 100644 index 0000000..616fc58 --- /dev/null +++ b/lib/NOTICE @@ -0,0 +1 @@ +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..98a2709 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,21 @@ +## Documentation tools for Cloudscape Design System + +This package contains the source code for API documentation tools used as a build dependency of the React components for the [Cloudscape Design System](https://cloudscape.design/). + +Cloudscape is an open source design system for building intuitive, engaging, and inclusive web cloud experiences at scale. It consists of an extensive set of guidelines to create user experiences, along with the design resources and front-end components to streamline implementation. + +Cloudscape was built for and is used by [Amazon Web Services (AWS)](https://aws.amazon.com/) products and services. We created it in 2016 to improve the user experience across AWS web applications, and also to help teams implement those applications faster. Since then, we have continued enhancing the system based on customer feedback and research. + +Browse the [components repository](https://github.com/cloudscape-design/components) of Cloudscape Design System. + +## Getting help + +You can [create bug reports or feature requests](https://github.com/cloudscape-design/components/issues/new/choose), or [start a discussion](https://github.com/cloudscape-design/components/discussions) to ask a question. To minimize duplicates, we recommend that you search for existing bug reports, feature requests, or discussions before initiating a new thread. + +## Contributing + +The [contribution guidelines](https://github.com/cloudscape-design/documenter/blob/main/CONTRIBUTING.md) contains information on how to contribute, as well as our support model and versioning strategy. + +## License + +This project is licensed under the [Apache 2.0 License](/LICENSE). diff --git a/lib/components/component-definition.d.ts b/lib/components/component-definition.d.ts new file mode 100644 index 0000000..95bab16 --- /dev/null +++ b/lib/components/component-definition.d.ts @@ -0,0 +1,4 @@ +import ts from 'typescript'; +import type { ComponentDefinition } from './interfaces'; +import type { ExpandedProp, ExtractedDescription } from './extractor'; +export declare function buildComponentDefinition(name: string, dashCaseName: string, props: Array, functions: Array, defaultValues: Record, componentDescription: ExtractedDescription, checker: ts.TypeChecker): ComponentDefinition; diff --git a/lib/components/component-definition.js b/lib/components/component-definition.js new file mode 100644 index 0000000..0de8220 --- /dev/null +++ b/lib/components/component-definition.js @@ -0,0 +1,119 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.buildComponentDefinition = buildComponentDefinition; +const type_utils_1 = require("../shared/type-utils"); +const object_definition_1 = require("./object-definition"); +function getCommentTag(description, name) { + var _a; + const tag = description.tags.find(tag => tag.name === name); + return tag ? (_a = tag.text) !== null && _a !== void 0 ? _a : '' : undefined; +} +function getCommentTags(description, name) { + const tags = description.tags + .filter(tag => tag.name === name) + .map(tag => { + if (!tag.text) { + throw new Error(`Tag ${name} is missing text`); + } + return tag.text; + }); + return tags.length > 0 ? tags : undefined; +} +function castI18nTag(tag) { + return tag === undefined ? undefined : true; +} +function buildComponentDefinition(name, dashCaseName, props, functions, defaultValues, componentDescription, checker) { + const regions = props.filter(prop => prop.type === 'React.ReactNode'); + const events = props.filter(prop => { + // The onError event handler of the error boundary component does not follow the + // event handlers convention and is categorized to properties instead. + if (name === 'ErrorBoundary' && prop.name === 'onError') { + return false; + } + else { + return prop.name.match(/^on[A-Z]/); + } + }); + const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop)); + return { + name, + dashCaseName, + releaseStatus: 'stable', + description: componentDescription.text, + systemTags: getCommentTags(componentDescription, 'awsuiSystem'), + regions: regions.map((region) => ({ + name: region.name, + displayName: getCommentTag(region.description, 'displayname'), + description: region.description.text, + isDefault: region.name === 'children', + systemTags: getCommentTags(region.description, 'awsuiSystem'), + visualRefreshTag: getCommentTag(region.description, 'visualrefresh'), + deprecatedTag: getCommentTag(region.description, 'deprecated'), + i18nTag: castI18nTag(getCommentTag(region.description, 'i18n')), + })), + functions: functions.map((func) => ({ + name: func.name, + description: func.description.text, + returnType: (0, type_utils_1.stringifyType)(func.rawType.getNonNullableType().getCallSignatures()[0].getReturnType(), checker), + parameters: func.rawType + .getNonNullableType() + .getCallSignatures()[0] + .getParameters() + .map((param) => { + const paramType = checker.getTypeAtLocation((0, type_utils_1.extractDeclaration)(param)); + return { + name: param.name, + type: (0, type_utils_1.stringifyType)(paramType, checker), + }; + }), + })), + properties: onlyProps.map((property) => { + const { type, inlineType } = (0, object_definition_1.getObjectDefinition)(property.type, property.rawType, property.rawTypeNode, checker); + return { + name: property.name, + type: type, + inlineType: inlineType, + optional: property.isOptional, + description: property.description.text, + defaultValue: defaultValues[property.name], + systemTags: getCommentTags(property.description, 'awsuiSystem'), + visualRefreshTag: getCommentTag(property.description, 'visualrefresh'), + deprecatedTag: getCommentTag(property.description, 'deprecated'), + analyticsTag: getCommentTag(property.description, 'analytics'), + i18nTag: castI18nTag(getCommentTag(property.description, 'i18n')), + }; + }), + events: events.map((event) => { + const { detailType, detailInlineType, cancelable } = extractEventDetails(event.rawType, event.rawTypeNode, checker); + return { + name: event.name, + description: event.description.text, + cancelable, + detailType, + detailInlineType, + systemTags: getCommentTags(event.description, 'awsuiSystem'), + deprecatedTag: getCommentTag(event.description, 'deprecated'), + }; + }), + }; +} +function extractEventDetails(type, typeNode, checker) { + var _a, _b; + const realType = type.getNonNullableType(); + const handlerName = (_a = realType.aliasSymbol) === null || _a === void 0 ? void 0 : _a.getName(); + if (handlerName !== 'CancelableEventHandler' && handlerName !== 'NonCancelableEventHandler') { + throw new Error(`Unknown event handler type: ${checker.typeToString(realType)}`); + } + const cancelable = handlerName === 'CancelableEventHandler'; + const detailType = (_b = realType.aliasTypeArguments) === null || _b === void 0 ? void 0 : _b[0]; + if (detailType && detailType.getProperties().length > 0) { + const { type, inlineType } = (0, object_definition_1.getObjectDefinition)((0, type_utils_1.stringifyType)(detailType, checker), detailType, typeNode, checker); + return { + detailType: type, + detailInlineType: inlineType, + cancelable, + }; + } + return { cancelable }; +} +//# sourceMappingURL=component-definition.js.map \ No newline at end of file diff --git a/lib/components/component-definition.js.map b/lib/components/component-definition.js.map new file mode 100644 index 0000000..c242e0e --- /dev/null +++ b/lib/components/component-definition.js.map @@ -0,0 +1 @@ +{"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../src/components/component-definition.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport { extractDeclaration, stringifyType } from '../shared/type-utils';\nimport type {\n ComponentDefinition,\n ComponentFunction,\n ComponentProperty,\n ComponentRegion,\n EventHandler,\n} from './interfaces';\nimport type { ExpandedProp, ExtractedDescription } from './extractor';\nimport { getObjectDefinition } from './object-definition';\n\nfunction getCommentTag(description: ExtractedDescription, name: string) {\n const tag = description.tags.find(tag => tag.name === name);\n return tag ? tag.text ?? '' : undefined;\n}\n\nfunction getCommentTags(description: ExtractedDescription, name: string) {\n const tags = description.tags\n .filter(tag => tag.name === name)\n .map(tag => {\n if (!tag.text) {\n throw new Error(`Tag ${name} is missing text`);\n }\n return tag.text;\n });\n return tags.length > 0 ? tags : undefined;\n}\n\nfunction castI18nTag(tag: string | undefined) {\n return tag === undefined ? undefined : true;\n}\n\nexport function buildComponentDefinition(\n name: string,\n dashCaseName: string,\n props: Array,\n functions: Array,\n defaultValues: Record,\n componentDescription: ExtractedDescription,\n checker: ts.TypeChecker\n): ComponentDefinition {\n const regions = props.filter(prop => prop.type === 'React.ReactNode');\n const events = props.filter(prop => {\n // The onError event handler of the error boundary component does not follow the\n // event handlers convention and is categorized to properties instead.\n if (name === 'ErrorBoundary' && prop.name === 'onError') {\n return false;\n } else {\n return prop.name.match(/^on[A-Z]/);\n }\n });\n const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop));\n return {\n name,\n dashCaseName,\n releaseStatus: 'stable',\n description: componentDescription.text,\n systemTags: getCommentTags(componentDescription, 'awsuiSystem'),\n regions: regions.map(\n (region): ComponentRegion => ({\n name: region.name,\n displayName: getCommentTag(region.description, 'displayname'),\n description: region.description.text,\n isDefault: region.name === 'children',\n systemTags: getCommentTags(region.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(region.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(region.description, 'deprecated'),\n i18nTag: castI18nTag(getCommentTag(region.description, 'i18n')),\n })\n ),\n functions: functions.map(\n (func): ComponentFunction => ({\n name: func.name,\n description: func.description.text,\n returnType: stringifyType(func.rawType.getNonNullableType().getCallSignatures()[0].getReturnType(), checker),\n parameters: func.rawType\n .getNonNullableType()\n .getCallSignatures()[0]\n .getParameters()\n .map((param): ComponentFunction['parameters'][0] => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.name,\n type: stringifyType(paramType, checker),\n };\n }),\n })\n ),\n properties: onlyProps.map((property): ComponentProperty => {\n const { type, inlineType } = getObjectDefinition(property.type, property.rawType, property.rawTypeNode, checker);\n return {\n name: property.name,\n type: type,\n inlineType: inlineType,\n optional: property.isOptional,\n description: property.description.text,\n defaultValue: defaultValues[property.name],\n systemTags: getCommentTags(property.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(property.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(property.description, 'deprecated'),\n analyticsTag: getCommentTag(property.description, 'analytics'),\n i18nTag: castI18nTag(getCommentTag(property.description, 'i18n')),\n };\n }),\n events: events.map((event): EventHandler => {\n const { detailType, detailInlineType, cancelable } = extractEventDetails(\n event.rawType,\n event.rawTypeNode,\n checker\n );\n return {\n name: event.name,\n description: event.description.text,\n cancelable,\n detailType,\n detailInlineType,\n systemTags: getCommentTags(event.description, 'awsuiSystem'),\n deprecatedTag: getCommentTag(event.description, 'deprecated'),\n };\n }),\n };\n}\n\nfunction extractEventDetails(type: ts.Type, typeNode: ts.TypeNode | undefined, checker: ts.TypeChecker) {\n const realType = type.getNonNullableType();\n const handlerName = realType.aliasSymbol?.getName();\n if (handlerName !== 'CancelableEventHandler' && handlerName !== 'NonCancelableEventHandler') {\n throw new Error(`Unknown event handler type: ${checker.typeToString(realType)}`);\n }\n const cancelable = handlerName === 'CancelableEventHandler';\n const detailType = realType.aliasTypeArguments?.[0];\n if (detailType && detailType.getProperties().length > 0) {\n const { type, inlineType } = getObjectDefinition(stringifyType(detailType, checker), detailType, typeNode, checker);\n return {\n detailType: type,\n detailInlineType: inlineType,\n cancelable,\n };\n }\n return { cancelable };\n}\n"]} \ No newline at end of file diff --git a/lib/components/extract-value-descriptions.d.ts b/lib/components/extract-value-descriptions.d.ts new file mode 100644 index 0000000..a9d631f --- /dev/null +++ b/lib/components/extract-value-descriptions.d.ts @@ -0,0 +1,3 @@ +import ts from 'typescript'; +import { ValueDescription } from './interfaces'; +export declare function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined): (ValueDescription | undefined)[]; diff --git a/lib/components/extract-value-descriptions.js b/lib/components/extract-value-descriptions.js new file mode 100644 index 0000000..b1a9fae --- /dev/null +++ b/lib/components/extract-value-descriptions.js @@ -0,0 +1,50 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.extractValueDescriptions = extractValueDescriptions; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +const type_utils_1 = require("../shared/type-utils"); +function extractValueDescriptions(type, typeNode) { + var _a; + if (type.aliasSymbol) { + // Traverse from "variant: ButtonProps.Variant" to "type Variant = ..." + const aliasDeclaration = (0, type_utils_1.extractDeclaration)(type.aliasSymbol); + if (typescript_1.default.isTypeAliasDeclaration(aliasDeclaration)) { + typeNode = aliasDeclaration.type; + } + } + if (!typeNode) { + return []; + } + const maybeList = typeNode.getChildren()[0]; + // based on similar code in typedoc + // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438 + if (maybeList.kind !== typescript_1.default.SyntaxKind.SyntaxList) { + return []; + } + const rawComments = []; + let memberIndex = 0; + for (const child of maybeList.getChildren()) { + const text = child.getFullText(); + if (text.includes('/**')) { + rawComments[memberIndex] = ((_a = rawComments[memberIndex]) !== null && _a !== void 0 ? _a : '') + child.getFullText(); + } + if (child.kind !== typescript_1.default.SyntaxKind.BarToken) { + memberIndex++; + } + } + // Array.from to fix sparse array + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots + return Array.from(rawComments).map((comment) => { + if (!comment) { + return undefined; + } + const systemTags = Array.from(comment.matchAll(/@awsuiSystem\s+(\w+)/g), ([_, system]) => system); + return systemTags.length > 0 ? { systemTags } : undefined; + }); +} +//# sourceMappingURL=extract-value-descriptions.js.map \ No newline at end of file diff --git a/lib/components/extract-value-descriptions.js.map b/lib/components/extract-value-descriptions.js.map new file mode 100644 index 0000000..a430c9d --- /dev/null +++ b/lib/components/extract-value-descriptions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extract-value-descriptions.js","sourceRoot":"","sources":["../../src/components/extract-value-descriptions.ts"],"names":[],"mappings":";;;;;AAMA,4DAwCC;AA9CD,qEAAqE;AACrE,sCAAsC;AACtC,4DAA4B;AAC5B,qDAA0D;AAG1D,SAAgB,wBAAwB,CAAC,IAAgC,EAAE,QAAiC;;IAC1G,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,uEAAuE;QACvE,MAAM,gBAAgB,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,oBAAE,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChD,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,mCAAmC;IACnC,6HAA6H;IAC7H,IAAI,SAAS,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,WAAW,GAA8B,EAAE,CAAC;IAClD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,MAAA,WAAW,CAAC,WAAW,CAAC,mCAAI,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACpF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC1C,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,iCAAiC;IACjC,uHAAuH;IACvH,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAgC,EAAE;QAC3E,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAClG,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport { extractDeclaration } from '../shared/type-utils';\nimport { ValueDescription } from './interfaces';\n\nexport function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined) {\n if (type.aliasSymbol) {\n // Traverse from \"variant: ButtonProps.Variant\" to \"type Variant = ...\"\n const aliasDeclaration = extractDeclaration(type.aliasSymbol);\n if (ts.isTypeAliasDeclaration(aliasDeclaration)) {\n typeNode = aliasDeclaration.type;\n }\n }\n\n if (!typeNode) {\n return [];\n }\n\n const maybeList = typeNode.getChildren()[0];\n // based on similar code in typedoc\n // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438\n if (maybeList.kind !== ts.SyntaxKind.SyntaxList) {\n return [];\n }\n const rawComments: Array = [];\n let memberIndex = 0;\n for (const child of maybeList.getChildren()) {\n const text = child.getFullText();\n if (text.includes('/**')) {\n rawComments[memberIndex] = (rawComments[memberIndex] ?? '') + child.getFullText();\n }\n\n if (child.kind !== ts.SyntaxKind.BarToken) {\n memberIndex++;\n }\n }\n // Array.from to fix sparse array\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots\n return Array.from(rawComments).map((comment): ValueDescription | undefined => {\n if (!comment) {\n return undefined;\n }\n const systemTags = Array.from(comment.matchAll(/@awsuiSystem\\s+(\\w+)/g), ([_, system]) => system);\n return systemTags.length > 0 ? { systemTags } : undefined;\n });\n}\n"]} \ No newline at end of file diff --git a/lib/components/extractor.d.ts b/lib/components/extractor.d.ts new file mode 100644 index 0000000..2757624 --- /dev/null +++ b/lib/components/extractor.d.ts @@ -0,0 +1,23 @@ +import ts from 'typescript'; +export interface ExtractedDescription { + text: string | undefined; + tags: Array<{ + name: string; + text: string | undefined; + }>; +} +export interface ExpandedProp { + name: string; + type: string; + isOptional: boolean; + rawType: ts.Type; + rawTypeNode: ts.TypeNode | undefined; + description: ExtractedDescription; +} +export declare function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker): Record; +export declare function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker): ExpandedProp[]; +export declare function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker): ExpandedProp[]; +export declare function extractExports(componentName: string, exportSymbols: ts.Symbol[], checker: ts.TypeChecker, extraExports: Record>): { + componentSymbol: ts.Symbol; + propsSymbol: ts.Symbol; +}; diff --git a/lib/components/extractor.js b/lib/components/extractor.js new file mode 100644 index 0000000..fd33de4 --- /dev/null +++ b/lib/components/extractor.js @@ -0,0 +1,156 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.extractDefaultValues = extractDefaultValues; +exports.extractProps = extractProps; +exports.extractFunctions = extractFunctions; +exports.extractExports = extractExports; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +const type_utils_1 = require("../shared/type-utils"); +function extractDefaultValues(exportSymbol, checker) { + let declaration = (0, type_utils_1.extractDeclaration)(exportSymbol); + if (typescript_1.default.isExportAssignment(declaration)) { + // Traverse from "export default Something;" to the actual "Something" + const symbol = checker.getSymbolAtLocation(declaration.expression); + if (!symbol) { + throw new Error('Cannot resolve symbol'); + } + declaration = (0, type_utils_1.extractDeclaration)(symbol); + } + // Extract "Something" from "const Component = Something" + if (typescript_1.default.isVariableDeclaration(declaration) && declaration.initializer) { + declaration = declaration.initializer; + } + // Extract "Something" from "Something as MyComponentType" + if (typescript_1.default.isAsExpression(declaration)) { + declaration = declaration.expression; + } + // Extract "Something from React.forwardRef(Something)" + if (typescript_1.default.isCallExpression(declaration) && + (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')) { + declaration = declaration.arguments[0]; + } + // In the component function, find arguments destructuring + let argument; + if (typescript_1.default.isFunctionDeclaration(declaration) || + typescript_1.default.isFunctionExpression(declaration) || + typescript_1.default.isArrowFunction(declaration)) { + if (declaration.parameters.length === 0) { + return {}; + } + argument = declaration.parameters[0].name; + } + if (!argument) { + throw new Error(`Unsupported component declaration type ${typescript_1.default.SyntaxKind[declaration.kind]}`); + } + if (!typescript_1.default.isObjectBindingPattern(argument)) { + // if a component does not use props de-structuring, we do not detect default values + return {}; + } + const values = {}; + for (const element of argument.elements) { + if (typescript_1.default.isIdentifier(element.name) && element.initializer) { + values[element.name.escapedText] = element.initializer.getText(); + } + } + return values; +} +function extractProps(propsSymbol, checker) { + const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol); + return exportType + .getProperties() + .map((value) => { + const declaration = (0, type_utils_1.extractDeclaration)(value); + const type = checker.getTypeAtLocation(declaration); + return { + name: value.name, + type: (0, type_utils_1.stringifyType)(type, checker), + rawType: type, + rawTypeNode: declaration.type, + isOptional: (0, type_utils_1.isOptional)(type), + description: (0, type_utils_1.getDescription)(value.getDocumentationComment(checker), declaration), + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)); +} +function extractFunctions(propsSymbol, checker) { + var _a, _b, _c; + const propsName = propsSymbol.getName(); + const namespaceDeclaration = [ + // if we got the namespace directly + ...((_a = propsSymbol.getDeclarations()) !== null && _a !== void 0 ? _a : []), + // find namespace declaration from the interface with the same name + ...((_c = (_b = checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()) === null || _b === void 0 ? void 0 : _b.getDeclarations()) !== null && _c !== void 0 ? _c : []), + ].find(decl => decl.kind === typescript_1.default.SyntaxKind.ModuleDeclaration); + const refType = (0, type_utils_1.unwrapNamespaceDeclaration)(namespaceDeclaration) + .map(child => checker.getTypeAtLocation(child)) + .find(type => { var _a, _b; return ((_b = ((_a = type.getSymbol()) !== null && _a !== void 0 ? _a : type.aliasSymbol)) === null || _b === void 0 ? void 0 : _b.getName()) === 'Ref'; }); + if (!refType) { + return []; + } + return refType + .getProperties() + .map((value) => { + const declaration = (0, type_utils_1.extractDeclaration)(value); + const type = checker.getTypeAtLocation(declaration); + const realType = type.getNonNullableType(); + if (realType.getCallSignatures().length === 0) { + throw new Error(`${propsName}.Ref should contain only methods, "${value.name}" has a "${(0, type_utils_1.stringifyType)(type, checker)}" type`); + } + return { + name: value.name, + type: (0, type_utils_1.stringifyType)(realType, checker), + rawType: realType, + rawTypeNode: declaration.type, + isOptional: (0, type_utils_1.isOptional)(type), + description: (0, type_utils_1.getDescription)(value.getDocumentationComment(checker), declaration), + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)); +} +function extractExports(componentName, exportSymbols, checker, extraExports) { + let componentSymbol; + let propsSymbol; + const unknownExports = []; + for (const exportSymbol of exportSymbols) { + if (exportSymbol.name === 'default') { + validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker); + componentSymbol = exportSymbol; + } + else if (exportSymbol.name === `${componentName}Props`) { + propsSymbol = exportSymbol; + } + else if (!extraExports[componentName] || + (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*'))) { + unknownExports.push(exportSymbol.name); + } + } + if (unknownExports.length > 0) { + throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`); + } + if (!componentSymbol) { + throw new Error(`Missing default export for ${componentName}`); + } + if (!propsSymbol) { + throw new Error(`Missing ${componentName}Props export`); + } + return { componentSymbol, propsSymbol }; +} +function validateComponentType(type, checker) { + var _a; + if ( + // React.forwardRef + ((_a = type.getSymbol()) === null || _a === void 0 ? void 0 : _a.name) !== 'ForwardRefExoticComponent' && + // Plain function returning JSX + type.getCallSignatures().some(signature => { + const returnTypeName = checker.typeToString(signature.getReturnType()); + return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal'; + })) { + throw new Error(`Unknown default export type ${checker.typeToString(type)}`); + } +} +//# sourceMappingURL=extractor.js.map \ No newline at end of file diff --git a/lib/components/extractor.js.map b/lib/components/extractor.js.map new file mode 100644 index 0000000..eeafcf8 --- /dev/null +++ b/lib/components/extractor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/components/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport {\n extractDeclaration,\n getDescription,\n isOptional,\n stringifyType,\n unwrapNamespaceDeclaration,\n} from '../shared/type-utils';\n\nexport interface ExtractedDescription {\n text: string | undefined;\n tags: Array<{ name: string; text: string | undefined }>;\n}\n\nexport interface ExpandedProp {\n name: string;\n type: string;\n isOptional: boolean;\n rawType: ts.Type;\n rawTypeNode: ts.TypeNode | undefined;\n description: ExtractedDescription;\n}\n\nexport function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker) {\n let declaration: ts.Node = extractDeclaration(exportSymbol);\n if (ts.isExportAssignment(declaration)) {\n // Traverse from \"export default Something;\" to the actual \"Something\"\n const symbol = checker.getSymbolAtLocation(declaration.expression);\n if (!symbol) {\n throw new Error('Cannot resolve symbol');\n }\n declaration = extractDeclaration(symbol);\n }\n // Extract \"Something\" from \"const Component = Something\"\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n declaration = declaration.initializer;\n }\n // Extract \"Something\" from \"Something as MyComponentType\"\n if (ts.isAsExpression(declaration)) {\n declaration = declaration.expression;\n }\n // Extract \"Something from React.forwardRef(Something)\"\n if (\n ts.isCallExpression(declaration) &&\n (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')\n ) {\n declaration = declaration.arguments[0];\n }\n\n // In the component function, find arguments destructuring\n let argument: ts.Node | undefined;\n if (\n ts.isFunctionDeclaration(declaration) ||\n ts.isFunctionExpression(declaration) ||\n ts.isArrowFunction(declaration)\n ) {\n if (declaration.parameters.length === 0) {\n return {};\n }\n argument = declaration.parameters[0].name;\n }\n if (!argument) {\n throw new Error(`Unsupported component declaration type ${ts.SyntaxKind[declaration.kind]}`);\n }\n if (!ts.isObjectBindingPattern(argument)) {\n // if a component does not use props de-structuring, we do not detect default values\n return {};\n }\n const values: Record = {};\n for (const element of argument.elements) {\n if (ts.isIdentifier(element.name) && element.initializer) {\n values[element.name.escapedText as string] = element.initializer.getText();\n }\n }\n return values;\n}\n\nexport function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol);\n\n return exportType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n return {\n name: value.name,\n type: stringifyType(type, checker),\n rawType: type,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const propsName = propsSymbol.getName();\n const namespaceDeclaration = [\n // if we got the namespace directly\n ...(propsSymbol.getDeclarations() ?? []),\n // find namespace declaration from the interface with the same name\n ...(checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()?.getDeclarations() ?? []),\n ].find(decl => decl.kind === ts.SyntaxKind.ModuleDeclaration);\n const refType = unwrapNamespaceDeclaration(namespaceDeclaration)\n .map(child => checker.getTypeAtLocation(child))\n .find(type => (type.getSymbol() ?? type.aliasSymbol)?.getName() === 'Ref');\n\n if (!refType) {\n return [];\n }\n return refType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n const realType = type.getNonNullableType();\n if (realType.getCallSignatures().length === 0) {\n throw new Error(\n `${propsName}.Ref should contain only methods, \"${value.name}\" has a \"${stringifyType(type, checker)}\" type`\n );\n }\n return {\n name: value.name,\n type: stringifyType(realType, checker),\n rawType: realType,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractExports(\n componentName: string,\n exportSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n extraExports: Record>\n) {\n let componentSymbol;\n let propsSymbol;\n const unknownExports: Array = [];\n for (const exportSymbol of exportSymbols) {\n if (exportSymbol.name === 'default') {\n validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker);\n componentSymbol = exportSymbol;\n } else if (exportSymbol.name === `${componentName}Props`) {\n propsSymbol = exportSymbol;\n } else if (\n !extraExports[componentName] ||\n (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*'))\n ) {\n unknownExports.push(exportSymbol.name);\n }\n }\n if (unknownExports.length > 0) {\n throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`);\n }\n if (!componentSymbol) {\n throw new Error(`Missing default export for ${componentName}`);\n }\n if (!propsSymbol) {\n throw new Error(`Missing ${componentName}Props export`);\n }\n return { componentSymbol, propsSymbol };\n}\n\nfunction validateComponentType(type: ts.Type, checker: ts.TypeChecker) {\n if (\n // React.forwardRef\n type.getSymbol()?.name !== 'ForwardRefExoticComponent' &&\n // Plain function returning JSX\n type.getCallSignatures().some(signature => {\n const returnTypeName = checker.typeToString(signature.getReturnType());\n return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal';\n })\n ) {\n throw new Error(`Unknown default export type ${checker.typeToString(type)}`);\n }\n}\n"]} \ No newline at end of file diff --git a/lib/components/index.d.ts b/lib/components/index.d.ts new file mode 100644 index 0000000..5f3e28c --- /dev/null +++ b/lib/components/index.d.ts @@ -0,0 +1,11 @@ +import type { ComponentDefinition } from './interfaces'; +export interface DocumenterOptions { + tsconfigPath: string; + publicFilesGlob: string; + extraExports?: Record>; +} +export interface WriteOptions { + outDir: string; +} +export declare function writeComponentsDocumentation({ outDir, ...options }: WriteOptions & DocumenterOptions): void; +export declare function documentComponents(options: DocumenterOptions): Array; diff --git a/lib/components/index.js b/lib/components/index.js new file mode 100644 index 0000000..b4be0ba --- /dev/null +++ b/lib/components/index.js @@ -0,0 +1,65 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.writeComponentsDocumentation = writeComponentsDocumentation; +exports.documentComponents = documentComponents; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const node_fs_1 = __importDefault(require("node:fs")); +const change_case_1 = require("change-case"); +const pathe_1 = __importDefault(require("pathe")); +const micromatch_1 = require("micromatch"); +const component_definition_1 = require("./component-definition"); +const extractor_1 = require("./extractor"); +const bootstrap_1 = require("../shared/bootstrap"); +const type_utils_1 = require("../shared/type-utils"); +function componentNameFromPath(componentPath) { + const dashCaseName = pathe_1.default.basename(pathe_1.default.dirname(componentPath)); + return { dashCaseName, name: (0, change_case_1.pascalCase)(dashCaseName) }; +} +function writeComponentsDocumentation({ outDir, ...options }) { + const definitions = documentComponents(options); + node_fs_1.default.mkdirSync(outDir, { recursive: true }); + for (const definition of definitions) { + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, definition.dashCaseName + '.js'), `module.exports = ${JSON.stringify(definition, null, 2)};`); + } + const indexContent = `module.exports = { + ${definitions + .map(definition => `${JSON.stringify(definition.dashCaseName)}:require('./${definition.dashCaseName}')`) + .join(',\n')} + }`; + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'index.js'), indexContent); + node_fs_1.default.copyFileSync(require.resolve('./interfaces.d.ts'), pathe_1.default.join(outDir, 'interfaces.d.ts')); + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'index.d.ts'), `import { ComponentDefinition } from './interfaces'; +declare const definitions: Record; +export = definitions; +`); +} +function documentComponents(options) { + const program = (0, bootstrap_1.bootstrapTypescriptProject)(options.tsconfigPath); + const checker = program.getTypeChecker(); + const isMatch = (0, micromatch_1.matcher)(pathe_1.default.resolve(options.publicFilesGlob)); + const sourceFiles = program.getSourceFiles().filter(file => isMatch(file.fileName)); + if (sourceFiles.length === 0) { + throw new Error(`No files found matching ${options.publicFilesGlob}`); + } + return sourceFiles.map(sourceFile => { + var _a; + const moduleSymbol = checker.getSymbolAtLocation(sourceFile); + const { name, dashCaseName } = componentNameFromPath(sourceFile.fileName); + // istanbul ignore next + if (!moduleSymbol) { + throw new Error(`Unable to resolve module: ${sourceFile.fileName}`); + } + const exportSymbols = checker.getExportsOfModule(moduleSymbol); + const { propsSymbol, componentSymbol } = (0, extractor_1.extractExports)(name, exportSymbols, checker, (_a = options === null || options === void 0 ? void 0 : options.extraExports) !== null && _a !== void 0 ? _a : {}); + const props = (0, extractor_1.extractProps)(propsSymbol, checker); + const functions = (0, extractor_1.extractFunctions)(propsSymbol, checker); + const defaultValues = (0, extractor_1.extractDefaultValues)(componentSymbol, checker); + const componentDescription = (0, type_utils_1.getDescription)(componentSymbol.getDocumentationComment(checker), (0, type_utils_1.extractDeclaration)(componentSymbol)); + return (0, component_definition_1.buildComponentDefinition)(name, dashCaseName, props, functions, defaultValues, componentDescription, checker); + }); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/components/index.js.map b/lib/components/index.js.map new file mode 100644 index 0000000..602dac7 --- /dev/null +++ b/lib/components/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":";;;;;AA4BA,oEAuBC;AAED,gDAgCC;AArFD,qEAAqE;AACrE,sCAAsC;AACtC,sDAAyB;AACzB,6CAAyC;AACzC,kDAA0B;AAC1B,2CAAqC;AAErC,iEAAkE;AAClE,2CAAmG;AAEnG,mDAAiE;AACjE,qDAA0E;AAE1E,SAAS,qBAAqB,CAAC,aAAqB;IAClD,MAAM,YAAY,GAAG,eAAK,CAAC,QAAQ,CAAC,eAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAClE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAA,wBAAU,EAAC,YAAY,CAAC,EAAE,CAAC;AAC1D,CAAC;AAYD,SAAgB,4BAA4B,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,EAAoC;IACnG,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAChD,iBAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,YAAY,GAAG,KAAK,CAAC,EACnD,oBAAoB,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAC3D,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG;MACjB,WAAW;SACV,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC,eAAe,UAAU,CAAC,YAAY,IAAI,CAAC;SACvG,IAAI,CAAC,KAAK,CAAC;IACd,CAAC;IACH,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IAC/D,iBAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7F,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAChC;;;CAGH,CACE,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAA0B;IAC3D,MAAM,OAAO,GAAG,IAAA,sCAA0B,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,MAAM,OAAO,GAAG,IAAA,oBAAO,EAAC,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAEhE,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEpF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;;QAClC,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAC7D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAE1E,uBAAuB;QACvB,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAC/D,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,IAAA,0BAAc,EAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,EAAE,CAAC,CAAC;QACnH,MAAM,KAAK,GAAG,IAAA,wBAAY,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAA,4BAAgB,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,IAAA,gCAAoB,EAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,oBAAoB,GAAG,IAAA,2BAAc,EACzC,eAAe,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAChD,IAAA,+BAAkB,EAAC,eAAe,CAAC,CACpC,CAAC;QAEF,OAAO,IAAA,+CAAwB,EAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAC;IACtH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport { pascalCase } from 'change-case';\nimport pathe from 'pathe';\nimport { matcher } from 'micromatch';\n\nimport { buildComponentDefinition } from './component-definition';\nimport { extractDefaultValues, extractExports, extractFunctions, extractProps } from './extractor';\nimport type { ComponentDefinition } from './interfaces';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport { extractDeclaration, getDescription } from '../shared/type-utils';\n\nfunction componentNameFromPath(componentPath: string) {\n const dashCaseName = pathe.basename(pathe.dirname(componentPath));\n return { dashCaseName, name: pascalCase(dashCaseName) };\n}\n\nexport interface DocumenterOptions {\n tsconfigPath: string;\n publicFilesGlob: string;\n extraExports?: Record>;\n}\n\nexport interface WriteOptions {\n outDir: string;\n}\n\nexport function writeComponentsDocumentation({ outDir, ...options }: WriteOptions & DocumenterOptions): void {\n const definitions = documentComponents(options);\n fs.mkdirSync(outDir, { recursive: true });\n for (const definition of definitions) {\n fs.writeFileSync(\n pathe.join(outDir, definition.dashCaseName + '.js'),\n `module.exports = ${JSON.stringify(definition, null, 2)};`\n );\n }\n const indexContent = `module.exports = {\n ${definitions\n .map(definition => `${JSON.stringify(definition.dashCaseName)}:require('./${definition.dashCaseName}')`)\n .join(',\\n')}\n }`;\n fs.writeFileSync(pathe.join(outDir, 'index.js'), indexContent);\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n fs.writeFileSync(\n pathe.join(outDir, 'index.d.ts'),\n `import { ComponentDefinition } from './interfaces';\ndeclare const definitions: Record;\nexport = definitions;\n`\n );\n}\n\nexport function documentComponents(options: DocumenterOptions): Array {\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const isMatch = matcher(pathe.resolve(options.publicFilesGlob));\n\n const sourceFiles = program.getSourceFiles().filter(file => isMatch(file.fileName));\n\n if (sourceFiles.length === 0) {\n throw new Error(`No files found matching ${options.publicFilesGlob}`);\n }\n\n return sourceFiles.map(sourceFile => {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n const { name, dashCaseName } = componentNameFromPath(sourceFile.fileName);\n\n // istanbul ignore next\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const { propsSymbol, componentSymbol } = extractExports(name, exportSymbols, checker, options?.extraExports ?? {});\n const props = extractProps(propsSymbol, checker);\n const functions = extractFunctions(propsSymbol, checker);\n const defaultValues = extractDefaultValues(componentSymbol, checker);\n const componentDescription = getDescription(\n componentSymbol.getDocumentationComment(checker),\n extractDeclaration(componentSymbol)\n );\n\n return buildComponentDefinition(name, dashCaseName, props, functions, defaultValues, componentDescription, checker);\n });\n}\n"]} \ No newline at end of file diff --git a/lib/components/interfaces.d.ts b/lib/components/interfaces.d.ts new file mode 100644 index 0000000..50efdf7 --- /dev/null +++ b/lib/components/interfaces.d.ts @@ -0,0 +1,81 @@ +export interface ComponentDefinition { + name: string; + dashCaseName: string; + /** @deprecated */ + releaseStatus: string; + /** @deprecated */ + version?: string; + /** @deprecated */ + description?: string; + systemTags?: Array; + properties: ComponentProperty[]; + regions: ComponentRegion[]; + functions: ComponentFunction[]; + events: EventHandler[]; +} +interface Taggable { + deprecatedTag?: string; + visualRefreshTag?: string; + i18nTag?: true | undefined; + systemTags?: Array; +} +export interface ValueDescription { + systemTags: Array; +} +export interface ComponentProperty extends Taggable { + name: string; + description?: string; + optional: boolean; + type: string; + inlineType?: TypeDefinition; + defaultValue?: string; + analyticsTag?: string; +} +export interface ComponentRegion extends Taggable { + name: string; + description?: string; + displayName?: string; + isDefault: boolean; +} +export interface ComponentFunction { + name: string; + description?: string; + parameters: FunctionParameter[]; + returnType: string; +} +export type TypeDefinition = ObjectDefinition | FunctionDefinition | UnionTypeDefinition; +export interface ObjectDefinition { + name: string; + type: 'object'; + properties: ObjectDefinitionProperty[]; +} +export interface ObjectDefinitionProperty { + name: string; + optional: boolean; + type: string; + inlineType?: TypeDefinition; +} +export interface FunctionDefinition { + name: string; + type: 'function'; + returnType: string; + parameters: FunctionParameter[]; +} +export interface FunctionParameter { + name: string; + type: string; +} +export interface UnionTypeDefinition { + name: string; + type: 'union'; + valueDescriptions?: Record; + values: string[]; +} +export interface EventHandler extends Taggable { + name: string; + description?: string; + detailType?: string; + detailInlineType?: TypeDefinition; + cancelable: boolean; +} +export {}; diff --git a/lib/components/interfaces.js b/lib/components/interfaces.js new file mode 100644 index 0000000..db91911 --- /dev/null +++ b/lib/components/interfaces.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=interfaces.js.map \ No newline at end of file diff --git a/lib/components/interfaces.js.map b/lib/components/interfaces.js.map new file mode 100644 index 0000000..d68690f --- /dev/null +++ b/lib/components/interfaces.js.map @@ -0,0 +1 @@ +{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/components/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nexport interface ComponentDefinition {\n name: string;\n dashCaseName: string;\n /** @deprecated */\n releaseStatus: string;\n /** @deprecated */\n version?: string;\n /** @deprecated */\n description?: string;\n systemTags?: Array;\n properties: ComponentProperty[];\n regions: ComponentRegion[];\n functions: ComponentFunction[];\n events: EventHandler[];\n}\n\ninterface Taggable {\n deprecatedTag?: string;\n visualRefreshTag?: string;\n i18nTag?: true | undefined;\n systemTags?: Array;\n}\n\nexport interface ValueDescription {\n systemTags: Array;\n}\n\nexport interface ComponentProperty extends Taggable {\n name: string;\n description?: string;\n optional: boolean;\n type: string;\n inlineType?: TypeDefinition;\n defaultValue?: string;\n analyticsTag?: string;\n}\n\nexport interface ComponentRegion extends Taggable {\n name: string;\n description?: string;\n displayName?: string;\n isDefault: boolean;\n}\n\nexport interface ComponentFunction {\n name: string;\n description?: string;\n parameters: FunctionParameter[];\n returnType: string;\n}\n\nexport type TypeDefinition = ObjectDefinition | FunctionDefinition | UnionTypeDefinition;\n\nexport interface ObjectDefinition {\n name: string;\n type: 'object';\n properties: ObjectDefinitionProperty[];\n}\n\nexport interface ObjectDefinitionProperty {\n name: string;\n optional: boolean;\n type: string;\n inlineType?: TypeDefinition;\n}\n\nexport interface FunctionDefinition {\n name: string;\n type: 'function';\n returnType: string;\n parameters: FunctionParameter[];\n}\n\nexport interface FunctionParameter {\n name: string;\n type: string;\n}\n\nexport interface UnionTypeDefinition {\n name: string;\n type: 'union';\n valueDescriptions?: Record;\n values: string[];\n}\n\nexport interface EventHandler extends Taggable {\n name: string;\n description?: string;\n detailType?: string;\n detailInlineType?: TypeDefinition;\n cancelable: boolean;\n}\n"]} \ No newline at end of file diff --git a/lib/components/object-definition.d.ts b/lib/components/object-definition.d.ts new file mode 100644 index 0000000..bcb88e2 --- /dev/null +++ b/lib/components/object-definition.d.ts @@ -0,0 +1,6 @@ +import ts from 'typescript'; +import type { TypeDefinition } from './interfaces'; +export declare function getObjectDefinition(type: string, rawType: ts.Type, rawTypeNode: ts.TypeNode | undefined, checker: ts.TypeChecker): { + type: string; + inlineType?: TypeDefinition; +}; diff --git a/lib/components/object-definition.js b/lib/components/object-definition.js new file mode 100644 index 0000000..d504cb2 --- /dev/null +++ b/lib/components/object-definition.js @@ -0,0 +1,115 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getObjectDefinition = getObjectDefinition; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +const type_utils_1 = require("../shared/type-utils"); +const extract_value_descriptions_1 = require("./extract-value-descriptions"); +function isArrayType(type) { + const symbol = type.getSymbol(); + if (!symbol) { + return false; + } + return symbol.getName() === 'Array' || symbol.getName() === 'ReadonlyArray'; +} +function getObjectDefinition(type, rawType, rawTypeNode, checker) { + const realType = rawType.getNonNullableType(); + const realTypeName = (0, type_utils_1.stringifyType)(realType, checker); + if (realType.flags & typescript_1.default.TypeFlags.String || + realType.flags & typescript_1.default.TypeFlags.Literal || + realType.flags & typescript_1.default.TypeFlags.Boolean || + realType.flags & typescript_1.default.TypeFlags.Number || + isArrayType(realType) || + realTypeName === 'HTMLElement' || + realTypeName.split('.')[0] === 'Highcharts' || + type === 'React.ReactNode') { + // do not expand built-in Javascript methods or primitive values + return { type }; + } + if (realType.isUnionOrIntersection()) { + return getUnionTypeDefinition(realTypeName, realType, rawTypeNode, checker); + } + if (realType.getProperties().length > 0) { + const properties = realType + .getProperties() + .map(prop => { + const propNode = (0, type_utils_1.extractDeclaration)(prop); + const propType = checker.getTypeAtLocation(propNode); + const typeString = (0, type_utils_1.stringifyType)(propType, checker); + return { + name: prop.getName(), + optional: (0, type_utils_1.isOptional)(propType), + ...getObjectDefinition(typeString, propType, propNode.type, checker), + }; + }) + .sort((a, b) => a.name.localeCompare(b.name)); + return { + type: type, + inlineType: { + name: realTypeName.length < 100 ? realTypeName : 'object', + type: 'object', + properties: properties, + }, + }; + } + if (realType.getCallSignatures().length > 0) { + if (realType.getCallSignatures().length > 1) { + throw new Error('Multiple call signatures are not supported'); + } + const signature = realType.getCallSignatures()[0]; + return { + type, + inlineType: { + name: realTypeName, + type: 'function', + returnType: (0, type_utils_1.stringifyType)(signature.getReturnType(), checker), + parameters: signature.getParameters().map(param => { + const paramType = checker.getTypeAtLocation((0, type_utils_1.extractDeclaration)(param)); + return { + name: param.getName(), + type: (0, type_utils_1.stringifyType)(paramType, checker), + }; + }), + }, + }; + } + return { type }; +} +function getPrimitiveType(type) { + if (type.types.every(subtype => subtype.isStringLiteral())) { + return 'string'; + } + if (type.types.every(subtype => subtype.isNumberLiteral())) { + return 'number'; + } + return undefined; +} +function getUnionTypeDefinition(realTypeName, realType, typeNode, checker) { + const valueDescriptions = (0, extract_value_descriptions_1.extractValueDescriptions)(realType, typeNode); + const primitiveType = getPrimitiveType(realType); + const values = realType.types.map(subtype => primitiveType ? subtype.value.toString() : (0, type_utils_1.stringifyType)(subtype, checker)); + return { + type: primitiveType !== null && primitiveType !== void 0 ? primitiveType : realTypeName, + inlineType: { + name: realTypeName, + type: 'union', + valueDescriptions: valueDescriptions.length > 0 ? zipValueDescriptions(values, valueDescriptions) : undefined, + values: values, + }, + }; +} +function zipValueDescriptions(values, descriptions) { + const descriptionsMap = {}; + values.forEach((value, index) => { + const description = descriptions[index]; + if (description) { + descriptionsMap[value] = description; + } + }); + return descriptionsMap; +} +//# sourceMappingURL=object-definition.js.map \ No newline at end of file diff --git a/lib/components/object-definition.js.map b/lib/components/object-definition.js.map new file mode 100644 index 0000000..210ce67 --- /dev/null +++ b/lib/components/object-definition.js.map @@ -0,0 +1 @@ +{"version":3,"file":"object-definition.js","sourceRoot":"","sources":["../../src/components/object-definition.ts"],"names":[],"mappings":";;;;;AAeA,kDAuEC;AAtFD,qEAAqE;AACrE,sCAAsC;AACtC,4DAA4B;AAE5B,qDAAqF;AACrF,6EAAwE;AAExE,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,EAAE,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,KAAK,eAAe,CAAC;AAC9E,CAAC;AAED,SAAgB,mBAAmB,CACjC,IAAY,EACZ,OAAgB,EAChB,WAAoC,EACpC,OAAuB;IAEvB,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACtD,IACE,QAAQ,CAAC,KAAK,GAAG,oBAAE,CAAC,SAAS,CAAC,MAAM;QACpC,QAAQ,CAAC,KAAK,GAAG,oBAAE,CAAC,SAAS,CAAC,OAAO;QACrC,QAAQ,CAAC,KAAK,GAAG,oBAAE,CAAC,SAAS,CAAC,OAAO;QACrC,QAAQ,CAAC,KAAK,GAAG,oBAAE,CAAC,SAAS,CAAC,MAAM;QACpC,WAAW,CAAC,QAAQ,CAAC;QACrB,YAAY,KAAK,aAAa;QAC9B,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY;QAC3C,IAAI,KAAK,iBAAiB,EAC1B,CAAC;QACD,gEAAgE;QAChE,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC;IACD,IAAI,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC;QACrC,OAAO,sBAAsB,CAAC,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,QAAQ;aACxB,aAAa,EAAE;aACf,GAAG,CAAC,IAAI,CAAC,EAAE;YACV,MAAM,QAAQ,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAA2B,CAAC;YACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YACrD,MAAM,UAAU,GAAG,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAEpD,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE;gBACpB,QAAQ,EAAE,IAAA,uBAAU,EAAC,QAAQ,CAAC;gBAC9B,GAAG,mBAAmB,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;aACrE,CAAC;QACJ,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,IAAI;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,YAAY,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ;gBACzD,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,UAAU;aACvB;SACF,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,IAAI,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC;QAElD,OAAO;YACL,IAAI;YACJ,UAAU,EAAE;gBACV,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,IAAA,0BAAa,EAAC,SAAS,CAAC,aAAa,EAAE,EAAE,OAAO,CAAC;gBAC7D,UAAU,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;oBAChD,MAAM,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAA,+BAAkB,EAAC,KAAK,CAAC,CAAC,CAAC;oBACvE,OAAO;wBACL,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE;wBACrB,IAAI,EAAE,IAAA,0BAAa,EAAC,SAAS,EAAE,OAAO,CAAC;qBACxC,CAAC;gBACJ,CAAC,CAAC;aACH;SACF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAgC;IACxD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC;QAC3D,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC;QAC3D,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,sBAAsB,CAC7B,YAAoB,EACpB,QAAoC,EACpC,QAAiC,EACjC,OAAuB;IAEvB,MAAM,iBAAiB,GAAG,IAAA,qDAAwB,EAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACvE,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAC1C,aAAa,CAAC,CAAC,CAAE,OAA0B,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAA,0BAAa,EAAC,OAAO,EAAE,OAAO,CAAC,CAC/F,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,YAAY;QACnC,UAAU,EAAE;YACV,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,OAAO;YACb,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7G,MAAM,EAAE,MAAM;SACf;KACF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAqB,EAAE,YAAiD;IACpG,MAAM,eAAe,GAAqC,EAAE,CAAC;IAC7D,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9B,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,WAAW,EAAE,CAAC;YAChB,eAAe,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport type { TypeDefinition, UnionTypeDefinition, ValueDescription } from './interfaces';\nimport { extractDeclaration, isOptional, stringifyType } from '../shared/type-utils';\nimport { extractValueDescriptions } from './extract-value-descriptions';\n\nfunction isArrayType(type: ts.Type) {\n const symbol = type.getSymbol();\n if (!symbol) {\n return false;\n }\n return symbol.getName() === 'Array' || symbol.getName() === 'ReadonlyArray';\n}\n\nexport function getObjectDefinition(\n type: string,\n rawType: ts.Type,\n rawTypeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker\n): { type: string; inlineType?: TypeDefinition } {\n const realType = rawType.getNonNullableType();\n const realTypeName = stringifyType(realType, checker);\n if (\n realType.flags & ts.TypeFlags.String ||\n realType.flags & ts.TypeFlags.Literal ||\n realType.flags & ts.TypeFlags.Boolean ||\n realType.flags & ts.TypeFlags.Number ||\n isArrayType(realType) ||\n realTypeName === 'HTMLElement' ||\n realTypeName.split('.')[0] === 'Highcharts' ||\n type === 'React.ReactNode'\n ) {\n // do not expand built-in Javascript methods or primitive values\n return { type };\n }\n if (realType.isUnionOrIntersection()) {\n return getUnionTypeDefinition(realTypeName, realType, rawTypeNode, checker);\n }\n if (realType.getProperties().length > 0) {\n const properties = realType\n .getProperties()\n .map(prop => {\n const propNode = extractDeclaration(prop) as ts.PropertyDeclaration;\n const propType = checker.getTypeAtLocation(propNode);\n const typeString = stringifyType(propType, checker);\n\n return {\n name: prop.getName(),\n optional: isOptional(propType),\n ...getObjectDefinition(typeString, propType, propNode.type, checker),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n return {\n type: type,\n inlineType: {\n name: realTypeName.length < 100 ? realTypeName : 'object',\n type: 'object',\n properties: properties,\n },\n };\n }\n if (realType.getCallSignatures().length > 0) {\n if (realType.getCallSignatures().length > 1) {\n throw new Error('Multiple call signatures are not supported');\n }\n const signature = realType.getCallSignatures()[0];\n\n return {\n type,\n inlineType: {\n name: realTypeName,\n type: 'function',\n returnType: stringifyType(signature.getReturnType(), checker),\n parameters: signature.getParameters().map(param => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.getName(),\n type: stringifyType(paramType, checker),\n };\n }),\n },\n };\n }\n return { type };\n}\n\nfunction getPrimitiveType(type: ts.UnionOrIntersectionType) {\n if (type.types.every(subtype => subtype.isStringLiteral())) {\n return 'string';\n }\n if (type.types.every(subtype => subtype.isNumberLiteral())) {\n return 'number';\n }\n return undefined;\n}\n\nfunction getUnionTypeDefinition(\n realTypeName: string,\n realType: ts.UnionOrIntersectionType,\n typeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker\n): { type: string; inlineType: UnionTypeDefinition } {\n const valueDescriptions = extractValueDescriptions(realType, typeNode);\n const primitiveType = getPrimitiveType(realType);\n const values = realType.types.map(subtype =>\n primitiveType ? (subtype as ts.LiteralType).value.toString() : stringifyType(subtype, checker)\n );\n\n return {\n type: primitiveType ?? realTypeName,\n inlineType: {\n name: realTypeName,\n type: 'union',\n valueDescriptions: valueDescriptions.length > 0 ? zipValueDescriptions(values, valueDescriptions) : undefined,\n values: values,\n },\n };\n}\n\nfunction zipValueDescriptions(values: Array, descriptions: Array) {\n const descriptionsMap: Record = {};\n values.forEach((value, index) => {\n const description = descriptions[index];\n if (description) {\n descriptionsMap[value] = description;\n }\n });\n return descriptionsMap;\n}\n"]} \ No newline at end of file diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100644 index 0000000..98434a0 --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,3 @@ +export * from './components/interfaces'; +export { documentComponents, writeComponentsDocumentation } from './components'; +export { writeTestUtilsDocumentation } from './test-utils'; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..01b79f4 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,26 @@ +"use strict"; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.writeTestUtilsDocumentation = exports.writeComponentsDocumentation = exports.documentComponents = void 0; +__exportStar(require("./components/interfaces"), exports); +var components_1 = require("./components"); +Object.defineProperty(exports, "documentComponents", { enumerable: true, get: function () { return components_1.documentComponents; } }); +Object.defineProperty(exports, "writeComponentsDocumentation", { enumerable: true, get: function () { return components_1.writeComponentsDocumentation; } }); +var test_utils_1 = require("./test-utils"); +Object.defineProperty(exports, "writeTestUtilsDocumentation", { enumerable: true, get: function () { return test_utils_1.writeTestUtilsDocumentation; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/index.js.map b/lib/index.js.map new file mode 100644 index 0000000..ed05f25 --- /dev/null +++ b/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC;;;;;;;;;;;;;;;;;AAEtC,0DAAwC;AACxC,2CAAgF;AAAvE,gHAAA,kBAAkB,OAAA;AAAE,0HAAA,4BAA4B,OAAA;AACzD,2CAA2D;AAAlD,yHAAA,2BAA2B,OAAA","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport * from './components/interfaces';\nexport { documentComponents, writeComponentsDocumentation } from './components';\nexport { writeTestUtilsDocumentation } from './test-utils';\n"]} \ No newline at end of file diff --git a/lib/package.json b/lib/package.json new file mode 100644 index 0000000..0e9eeb5 --- /dev/null +++ b/lib/package.json @@ -0,0 +1,51 @@ +{ + "name": "@cloudscape-design/documenter", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "https://github.com/cloudscape-design/documenter.git" + }, + "homepage": "https://cloudscape.design", + "main": "./lib/index.js", + "exports": { + ".": "./lib/index.js" + }, + "scripts": { + "lint": "eslint --ignore-path .gitignore --ignore-path .eslintignore --ext js,ts,tsx .", + "prebuild": "rimraf lib", + "build": "tsc -p tsconfig.json && tsc -p tsconfig.test.json", + "postbuild": "cp package.json README.md NOTICE LICENSE lib", + "test": "vitest run", + "prepare": "husky" + }, + "devDependencies": { + "@types/micromatch": "^4.0.1", + "@types/node": "^20.0.0", + "@types/react": "^16.14.8", + "@types/react-dom": "^16.9.8", + "@typescript-eslint/eslint-plugin": "^4.28.5", + "@typescript-eslint/parser": "^4.28.5", + "@vitest/coverage-v8": "^3.1.3", + "eslint": "^7.31.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-unicorn": "^34.0.1", + "husky": "^9.0.11", + "lint-staged": "^13.2.1", + "prettier": "^2.3.2", + "rimraf": "^5.0.5", + "typescript": "^5.9.2", + "vitest": "^3.1.3" + }, + "dependencies": { + "change-case": "^4.1.1", + "micromatch": "^4.0.8", + "pathe": "^1.1.2" + }, + "lint-staged": { + "*.{ts,tsx,js}": [ + "eslint --fix" + ] + } +} diff --git a/lib/shared/bootstrap.d.ts b/lib/shared/bootstrap.d.ts new file mode 100644 index 0000000..0b7a995 --- /dev/null +++ b/lib/shared/bootstrap.d.ts @@ -0,0 +1,2 @@ +import ts from 'typescript'; +export declare function bootstrapTypescriptProject(tsconfigPath: string): ts.Program; diff --git a/lib/shared/bootstrap.js b/lib/shared/bootstrap.js new file mode 100644 index 0000000..b5eea48 --- /dev/null +++ b/lib/shared/bootstrap.js @@ -0,0 +1,48 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.bootstrapTypescriptProject = bootstrapTypescriptProject; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +const pathe_1 = __importDefault(require("pathe")); +function printDiagnostics(diagnostics) { + for (const diagnostic of diagnostics) { + const message = typescript_1.default.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + if (diagnostic.file) { + const { line, character } = typescript_1.default.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + console.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); + } + else { + console.error(message); + } + } +} +function loadTSConfig(tsconfigPath) { + const configFile = typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile); + if (configFile.error) { + throw new Error('Failed to read tsconfig.json'); + } + const config = typescript_1.default.parseJsonConfigFileContent(configFile.config, typescript_1.default.sys, pathe_1.default.dirname(tsconfigPath)); + if (config.errors.length > 0) { + console.error(...config.errors); + throw new Error('Failed to parse tsconfig.json'); + } + // this prints a warning that incremental mode is not supported in programmatic API + config.options.incremental = false; + delete config.options.tsBuildInfoFile; + return config; +} +function bootstrapTypescriptProject(tsconfigPath) { + const tsconfig = loadTSConfig(tsconfigPath); + const program = typescript_1.default.createProgram(tsconfig.fileNames, tsconfig.options); + const diagnostics = typescript_1.default.getPreEmitDiagnostics(program); + if (diagnostics.length > 0) { + printDiagnostics(diagnostics); + throw new Error('Compilation failed'); + } + return program; +} +//# sourceMappingURL=bootstrap.js.map \ No newline at end of file diff --git a/lib/shared/bootstrap.js.map b/lib/shared/bootstrap.js.map new file mode 100644 index 0000000..8138657 --- /dev/null +++ b/lib/shared/bootstrap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/shared/bootstrap.ts"],"names":[],"mappings":";;;;;AAiCA,gEAWC;AA5CD,qEAAqE;AACrE,sCAAsC;AACtC,4DAA4B;AAC5B,kDAA0B;AAE1B,SAAS,gBAAgB,CAAC,WAAqC;IAC7D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,oBAAE,CAAC,4BAA4B,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC9E,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,oBAAE,CAAC,6BAA6B,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,KAAM,CAAC,CAAC;YACjG,OAAO,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,MAAM,UAAU,GAAG,oBAAE,CAAC,cAAc,CAAC,YAAY,EAAE,oBAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpE,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,MAAM,GAAG,oBAAE,CAAC,0BAA0B,CAAC,UAAU,CAAC,MAAM,EAAE,oBAAE,CAAC,GAAG,EAAE,eAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IACrG,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,mFAAmF;IACnF,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC;IACnC,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;IACtC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,0BAA0B,CAAC,YAAoB;IAC7D,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,oBAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEvE,MAAM,WAAW,GAAG,oBAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport pathe from 'pathe';\n\nfunction printDiagnostics(diagnostics: readonly ts.Diagnostic[]): void {\n for (const diagnostic of diagnostics) {\n const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n');\n if (diagnostic.file) {\n const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!);\n console.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);\n } else {\n console.error(message);\n }\n }\n}\n\nfunction loadTSConfig(tsconfigPath: string): ts.ParsedCommandLine {\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n if (configFile.error) {\n throw new Error('Failed to read tsconfig.json');\n }\n const config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, pathe.dirname(tsconfigPath));\n if (config.errors.length > 0) {\n console.error(...config.errors);\n throw new Error('Failed to parse tsconfig.json');\n }\n // this prints a warning that incremental mode is not supported in programmatic API\n config.options.incremental = false;\n delete config.options.tsBuildInfoFile;\n return config;\n}\n\nexport function bootstrapTypescriptProject(tsconfigPath: string) {\n const tsconfig = loadTSConfig(tsconfigPath);\n const program = ts.createProgram(tsconfig.fileNames, tsconfig.options);\n\n const diagnostics = ts.getPreEmitDiagnostics(program);\n if (diagnostics.length > 0) {\n printDiagnostics(diagnostics);\n throw new Error('Compilation failed');\n }\n\n return program;\n}\n"]} \ No newline at end of file diff --git a/lib/shared/type-utils.d.ts b/lib/shared/type-utils.d.ts new file mode 100644 index 0000000..8802bdc --- /dev/null +++ b/lib/shared/type-utils.d.ts @@ -0,0 +1,21 @@ +import ts from 'typescript'; +export declare function isOptional(type: ts.Type): boolean; +export declare function isNullable(type: ts.Type): boolean; +export declare function unwrapNamespaceDeclaration(declaration: ts.Declaration | undefined): readonly ts.Node[]; +export declare function stringifyType(type: ts.Type, checker: ts.TypeChecker): string; +export declare function getDescription(docComment: Array, declaration: ts.Node): { + text: string | undefined; + tags: { + name: string; + text: string | undefined; + }[]; +}; +export declare function extractDeclaration(symbol: ts.Symbol): ts.Declaration; +export declare function printFlags(flags: number, mapping: Record): string[]; +export declare function extractTypeArguments(type: ts.Type, checker: ts.TypeChecker): { + typeName: string; + typeParameters?: undefined; +} | { + typeParameters: readonly ts.Type[]; + typeName: string; +}; diff --git a/lib/shared/type-utils.js b/lib/shared/type-utils.js new file mode 100644 index 0000000..a6ce286 --- /dev/null +++ b/lib/shared/type-utils.js @@ -0,0 +1,90 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isOptional = isOptional; +exports.isNullable = isNullable; +exports.unwrapNamespaceDeclaration = unwrapNamespaceDeclaration; +exports.stringifyType = stringifyType; +exports.getDescription = getDescription; +exports.extractDeclaration = extractDeclaration; +exports.printFlags = printFlags; +exports.extractTypeArguments = extractTypeArguments; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +function isOptional(type) { + if (!type.isUnionOrIntersection()) { + return false; + } + return !!type.types.find(t => t.flags & typescript_1.default.TypeFlags.Undefined); +} +function isNullable(type) { + if (!type.isUnionOrIntersection()) { + return false; + } + return !!type.types.find(t => t.flags & typescript_1.default.TypeFlags.Null); +} +function unwrapNamespaceDeclaration(declaration) { + if (!declaration) { + return []; + } + const namespaceBlock = declaration.getChildren().find(node => node.kind === typescript_1.default.SyntaxKind.ModuleBlock); + if (!namespaceBlock) { + return []; + } + const moduleContent = namespaceBlock.getChildren().find(node => node.kind === typescript_1.default.SyntaxKind.SyntaxList); + if (!moduleContent) { + return []; + } + return moduleContent.getChildren(); +} +function stripUndefined(typeString) { + return typeString.replace(/\| undefined$/, '').trim(); +} +function stringifyType(type, checker) { + return stripUndefined(checker.typeToString(type, undefined, typescript_1.default.TypeFormatFlags.WriteArrayAsGenericType | + typescript_1.default.TypeFormatFlags.UseFullyQualifiedType | + typescript_1.default.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope)); +} +function expandTags(extraTags) { + return extraTags.map(tag => ({ + name: tag.tagName.text, + text: typescript_1.default.getTextOfJSDocComment(tag.comment), + })); +} +function getDescription(docComment, declaration) { + return { + text: docComment.length > 0 ? typescript_1.default.displayPartsToString(docComment) : undefined, + tags: expandTags(typescript_1.default.getJSDocTags(declaration)), + }; +} +function extractDeclaration(symbol) { + const declarations = symbol.getDeclarations(); + if (!declarations || declarations.length === 0) { + throw new Error(`No declaration found for symbol: ${symbol.getName()}`); + } + if (declarations.length > 1) { + throw new Error(`Multiple declarations found for symbol: ${symbol.getName()}`); + } + return declarations[0]; +} +function printFlags(flags, mapping) { + return Object.entries(mapping) + .filter(([key, value]) => typeof value === 'number') + .filter(([key, value]) => value & flags) + .map(([key, value]) => key); +} +function extractTypeArguments(type, checker) { + const typeParameters = checker.getTypeArguments(type); + if (typeParameters.length <= 0) { + return { typeName: stringifyType(type, checker) }; + } + const symbol = type.getSymbol(); + if (!symbol) { + throw new Error(`Unknown generic type without symbol: ${stringifyType(type, checker)}`); + } + return { typeParameters, typeName: checker.symbolToString(symbol) }; +} +//# sourceMappingURL=type-utils.js.map \ No newline at end of file diff --git a/lib/shared/type-utils.js.map b/lib/shared/type-utils.js.map new file mode 100644 index 0000000..acd45ed --- /dev/null +++ b/lib/shared/type-utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/shared/type-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nexport function isOptional(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Undefined);\n}\n\nexport function isNullable(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Null);\n}\n\nexport function unwrapNamespaceDeclaration(declaration: ts.Declaration | undefined) {\n if (!declaration) {\n return [];\n }\n const namespaceBlock = declaration.getChildren().find(node => node.kind === ts.SyntaxKind.ModuleBlock);\n if (!namespaceBlock) {\n return [];\n }\n const moduleContent = namespaceBlock.getChildren().find(node => node.kind === ts.SyntaxKind.SyntaxList);\n if (!moduleContent) {\n return [];\n }\n return moduleContent.getChildren();\n}\n\nfunction stripUndefined(typeString: string) {\n return typeString.replace(/\\| undefined$/, '').trim();\n}\n\nexport function stringifyType(type: ts.Type, checker: ts.TypeChecker) {\n return stripUndefined(\n checker.typeToString(\n type,\n undefined,\n ts.TypeFormatFlags.WriteArrayAsGenericType |\n ts.TypeFormatFlags.UseFullyQualifiedType |\n ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope\n )\n );\n}\n\nfunction expandTags(extraTags: ReadonlyArray) {\n return extraTags.map(tag => ({\n name: tag.tagName.text,\n text: ts.getTextOfJSDocComment(tag.comment),\n }));\n}\n\nexport function getDescription(docComment: Array, declaration: ts.Node) {\n return {\n text: docComment.length > 0 ? ts.displayPartsToString(docComment) : undefined,\n tags: expandTags(ts.getJSDocTags(declaration)),\n };\n}\n\nexport function extractDeclaration(symbol: ts.Symbol) {\n const declarations = symbol.getDeclarations();\n if (!declarations || declarations.length === 0) {\n throw new Error(`No declaration found for symbol: ${symbol.getName()}`);\n }\n if (declarations.length > 1) {\n throw new Error(`Multiple declarations found for symbol: ${symbol.getName()}`);\n }\n return declarations[0];\n}\n\nexport function printFlags(flags: number, mapping: Record) {\n return Object.entries(mapping)\n .filter(([key, value]) => typeof value === 'number')\n .filter(([key, value]) => (value as number) & flags)\n .map(([key, value]) => key);\n}\n\nexport function extractTypeArguments(type: ts.Type, checker: ts.TypeChecker) {\n const typeParameters = checker.getTypeArguments(type as ts.TypeReference);\n\n if (typeParameters.length <= 0) {\n return { typeName: stringifyType(type, checker) };\n }\n const symbol = type.getSymbol();\n if (!symbol) {\n throw new Error(`Unknown generic type without symbol: ${stringifyType(type, checker)}`);\n }\n return { typeParameters, typeName: checker.symbolToString(symbol) };\n}\n"]} \ No newline at end of file diff --git a/lib/test-utils/extractor.d.ts b/lib/test-utils/extractor.d.ts new file mode 100644 index 0000000..bc1d027 --- /dev/null +++ b/lib/test-utils/extractor.d.ts @@ -0,0 +1,3 @@ +import ts from 'typescript'; +import { TestUtilsDoc } from './interfaces'; +export default function extractDocumentation(sourceFile: ts.SourceFile, checker: ts.TypeChecker, extraExports: Array, includeCoreMethods: boolean): Array; diff --git a/lib/test-utils/extractor.js b/lib/test-utils/extractor.js new file mode 100644 index 0000000..3a21dc7 --- /dev/null +++ b/lib/test-utils/extractor.js @@ -0,0 +1,127 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = extractDocumentation; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const typescript_1 = __importDefault(require("typescript")); +const type_utils_1 = require("../shared/type-utils"); +function getInheritedFrom(declaration, currentClassName) { + if (!typescript_1.default.isMethodDeclaration(declaration) || !typescript_1.default.isClassDeclaration(declaration.parent) || !declaration.parent.name) { + throw new Error(`Unexpected declaration parent: ${declaration.getText()}`); + } + const parentName = declaration.parent.name.getText(); + if (parentName === currentClassName) { + return undefined; + } + return { className: parentName, methodName: declaration.name.getText() }; +} +function getDefaultValue(declaration) { + if (!typescript_1.default.isParameter(declaration)) { + throw new Error(`Unexpected declaration: ${declaration.getText()}`); + } + if (!declaration.initializer) { + return undefined; + } + return declaration.initializer.getText(); +} +function extractDocumentation(sourceFile, checker, extraExports, includeCoreMethods) { + const moduleSymbol = checker.getSymbolAtLocation(sourceFile); + if (!moduleSymbol) { + throw new Error(`Unable to resolve module: ${sourceFile.fileName}`); + } + const exportSymbols = checker.getExportsOfModule(moduleSymbol); + const definitions = new Map(); + for (const symbol of exportSymbols) { + const className = symbol.getName(); + if (extraExports.includes(className)) { + continue; + } + const classType = checker.getDeclaredTypeOfSymbol(symbol); + documentClass(definitions, symbol, classType, checker, includeCoreMethods); + } + return Array.from(definitions.values()); +} +function documentClass(definitions, symbol, classType, checker, includeCoreMethods) { + if (!classType.isClass()) { + throw new Error(`Exported symbol is not a class, got ${checker.symbolToString(symbol)}`); + } + const className = checker.symbolToString(symbol); + const definition = { name: className, methods: [] }; + definitions.set(className, definition); + for (const property of classType.getProperties()) { + const declaration = property.valueDeclaration; + if (!declaration) { + throw new Error(`Unexpected member on ${className} – ${property.getName()}`); + } + const modifiers = (typescript_1.default.canHaveModifiers(declaration) && typescript_1.default.getModifiers(declaration)) || []; + if (modifiers.find(modifier => modifier.kind === typescript_1.default.SyntaxKind.ProtectedKeyword || modifier.kind === typescript_1.default.SyntaxKind.PrivateKeyword)) { + continue; + } + const type = checker.getTypeAtLocation(declaration); + // report each function signature as a separate method + for (const signature of type.getCallSignatures()) { + const maybeReturnType = signature.getReturnType(); + // non-nullable type of `void` is `never` + const returnType = maybeReturnType.flags & typescript_1.default.TypeFlags.Void ? maybeReturnType : maybeReturnType.getNonNullableType(); + const dependency = findDependencyType(returnType, checker); + if (dependency && !definitions.has(dependency.typeName)) { + documentClass(definitions, dependency.symbol, dependency.type, checker, includeCoreMethods); + } + const { typeName, typeParameters } = (0, type_utils_1.extractTypeArguments)(returnType, checker); + const inheritedFrom = getInheritedFrom(declaration, className); + if (inheritedFrom && + !includeCoreMethods && + ['AbstractWrapper', 'ElementWrapper'].includes(inheritedFrom === null || inheritedFrom === void 0 ? void 0 : inheritedFrom.className)) { + continue; + } + definition.methods.push({ + name: property.getName(), + description: (0, type_utils_1.getDescription)(property.getDocumentationComment(checker), declaration).text, + returnType: { + name: typeName, + isNullable: (0, type_utils_1.isNullable)(maybeReturnType), + typeArguments: typeParameters === null || typeParameters === void 0 ? void 0 : typeParameters.map(typeArgument => ({ + name: (0, type_utils_1.stringifyType)(typeArgument, checker), + })), + }, + parameters: signature.parameters.map(parameter => { + const paramType = checker.getTypeAtLocation((0, type_utils_1.extractDeclaration)(parameter)); + return { + name: parameter.name, + typeName: (0, type_utils_1.stringifyType)(paramType, checker), + description: (0, type_utils_1.getDescription)(parameter.getDocumentationComment(checker), declaration).text, + flags: { isOptional: (0, type_utils_1.isOptional)(paramType) }, + defaultValue: getDefaultValue((0, type_utils_1.extractDeclaration)(parameter)), + }; + }), + inheritedFrom: inheritedFrom ? { name: `${inheritedFrom.className}.${inheritedFrom.methodName}` } : undefined, + }); + } + } + definition.methods.sort((a, b) => a.name.localeCompare(b.name)); +} +function findDependencyType(type, checker) { + const symbol = type.getSymbol(); + if (!symbol) { + return; + } + const typeName = checker.symbolToString(symbol); + if (typeName === 'Array' || typeName === 'MultiElementWrapper') { + const itemType = checker.getTypeArguments(type)[0]; + return findDependencyType(itemType, checker); + } + if (!typeName.endsWith('Wrapper') || + ['ElementWrapper', 'ComponentWrapper'].includes(typeName) || + !type.isClassOrInterface()) { + return; + } + return { + typeName, + type, + symbol, + }; +} +//# sourceMappingURL=extractor.js.map \ No newline at end of file diff --git a/lib/test-utils/extractor.js.map b/lib/test-utils/extractor.js.map new file mode 100644 index 0000000..d7cd2ec --- /dev/null +++ b/lib/test-utils/extractor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/test-utils/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport {\n extractDeclaration,\n extractTypeArguments,\n getDescription,\n isNullable,\n isOptional,\n stringifyType,\n} from '../shared/type-utils';\nimport { TestUtilsDoc } from './interfaces';\n\nfunction getInheritedFrom(declaration: ts.Declaration, currentClassName: string) {\n if (!ts.isMethodDeclaration(declaration) || !ts.isClassDeclaration(declaration.parent) || !declaration.parent.name) {\n throw new Error(`Unexpected declaration parent: ${declaration.getText()}`);\n }\n const parentName = declaration.parent.name.getText();\n if (parentName === currentClassName) {\n return undefined;\n }\n return { className: parentName, methodName: declaration.name.getText() };\n}\n\nfunction getDefaultValue(declaration: ts.Declaration) {\n if (!ts.isParameter(declaration)) {\n throw new Error(`Unexpected declaration: ${declaration.getText()}`);\n }\n if (!declaration.initializer) {\n return undefined;\n }\n return declaration.initializer.getText();\n}\n\nexport default function extractDocumentation(\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n extraExports: Array,\n includeCoreMethods: boolean\n): Array {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const definitions = new Map();\n\n for (const symbol of exportSymbols) {\n const className = symbol.getName();\n if (extraExports.includes(className)) {\n continue;\n }\n const classType = checker.getDeclaredTypeOfSymbol(symbol);\n documentClass(definitions, symbol, classType, checker, includeCoreMethods);\n }\n\n return Array.from(definitions.values());\n}\n\nfunction documentClass(\n definitions: Map,\n symbol: ts.Symbol,\n classType: ts.Type,\n checker: ts.TypeChecker,\n includeCoreMethods: boolean\n) {\n if (!classType.isClass()) {\n throw new Error(`Exported symbol is not a class, got ${checker.symbolToString(symbol)}`);\n }\n const className = checker.symbolToString(symbol);\n const definition: TestUtilsDoc = { name: className, methods: [] };\n definitions.set(className, definition);\n\n for (const property of classType.getProperties()) {\n const declaration = property.valueDeclaration;\n if (!declaration) {\n throw new Error(`Unexpected member on ${className} – ${property.getName()}`);\n }\n const modifiers = (ts.canHaveModifiers(declaration) && ts.getModifiers(declaration)) || [];\n if (\n modifiers.find(\n modifier => modifier.kind === ts.SyntaxKind.ProtectedKeyword || modifier.kind === ts.SyntaxKind.PrivateKeyword\n )\n ) {\n continue;\n }\n const type = checker.getTypeAtLocation(declaration);\n // report each function signature as a separate method\n for (const signature of type.getCallSignatures()) {\n const maybeReturnType = signature.getReturnType();\n // non-nullable type of `void` is `never`\n const returnType =\n maybeReturnType.flags & ts.TypeFlags.Void ? maybeReturnType : maybeReturnType.getNonNullableType();\n const dependency = findDependencyType(returnType, checker);\n if (dependency && !definitions.has(dependency.typeName)) {\n documentClass(definitions, dependency.symbol, dependency.type, checker, includeCoreMethods);\n }\n\n const { typeName, typeParameters } = extractTypeArguments(returnType, checker);\n\n const inheritedFrom = getInheritedFrom(declaration, className);\n if (\n inheritedFrom &&\n !includeCoreMethods &&\n ['AbstractWrapper', 'ElementWrapper'].includes(inheritedFrom?.className)\n ) {\n continue;\n }\n\n definition.methods.push({\n name: property.getName(),\n description: getDescription(property.getDocumentationComment(checker), declaration).text,\n returnType: {\n name: typeName,\n isNullable: isNullable(maybeReturnType),\n typeArguments: typeParameters?.map(typeArgument => ({\n name: stringifyType(typeArgument, checker),\n })),\n },\n parameters: signature.parameters.map(parameter => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(parameter));\n return {\n name: parameter.name,\n typeName: stringifyType(paramType, checker),\n description: getDescription(parameter.getDocumentationComment(checker), declaration).text,\n flags: { isOptional: isOptional(paramType) },\n defaultValue: getDefaultValue(extractDeclaration(parameter)),\n };\n }),\n inheritedFrom: inheritedFrom ? { name: `${inheritedFrom.className}.${inheritedFrom.methodName}` } : undefined,\n });\n }\n }\n definition.methods.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction findDependencyType(\n type: ts.Type,\n checker: ts.TypeChecker\n): { typeName: string; type: ts.Type; symbol: ts.Symbol } | undefined {\n const symbol = type.getSymbol();\n if (!symbol) {\n return;\n }\n\n const typeName = checker.symbolToString(symbol);\n if (typeName === 'Array' || typeName === 'MultiElementWrapper') {\n const itemType = checker.getTypeArguments(type as ts.TypeReference)[0];\n return findDependencyType(itemType, checker);\n }\n if (\n !typeName.endsWith('Wrapper') ||\n ['ElementWrapper', 'ComponentWrapper'].includes(typeName) ||\n !type.isClassOrInterface()\n ) {\n return;\n }\n\n return {\n typeName,\n type,\n symbol,\n };\n}\n"]} \ No newline at end of file diff --git a/lib/test-utils/index.d.ts b/lib/test-utils/index.d.ts new file mode 100644 index 0000000..fe21db2 --- /dev/null +++ b/lib/test-utils/index.d.ts @@ -0,0 +1,20 @@ +import { TestUtilsDoc } from './interfaces'; +export interface TestUtilsVariantOptions { + root: string; + extraExports?: Array; +} +export interface TestUtilsDocumenterOptions { + tsconfigPath: string; + includeCoreMethods?: boolean; + domUtils: TestUtilsVariantOptions; + selectorsUtils: TestUtilsVariantOptions; +} +interface TestUtilsDefinitions { + domDefinitions: Array; + selectorsDefinitions: Array; +} +export declare function documentTestUtils(options: TestUtilsDocumenterOptions): TestUtilsDefinitions; +export declare function writeTestUtilsDocumentation({ outDir, ...rest }: TestUtilsDocumenterOptions & { + outDir: string; +}): void; +export {}; diff --git a/lib/test-utils/index.js b/lib/test-utils/index.js new file mode 100644 index 0000000..08b76e7 --- /dev/null +++ b/lib/test-utils/index.js @@ -0,0 +1,47 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.documentTestUtils = documentTestUtils; +exports.writeTestUtilsDocumentation = writeTestUtilsDocumentation; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +const node_fs_1 = __importDefault(require("node:fs")); +const pathe_1 = __importDefault(require("pathe")); +const bootstrap_1 = require("../shared/bootstrap"); +const extractor_1 = __importDefault(require("./extractor")); +function documentTestUtils(options) { + var _a, _b, _c; + const domUtilsRoot = pathe_1.default.resolve(options.domUtils.root); + const selectorsUtilsRoot = pathe_1.default.resolve(options.selectorsUtils.root); + const program = (0, bootstrap_1.bootstrapTypescriptProject)(options.tsconfigPath); + const checker = program.getTypeChecker(); + const domUtilsFile = program.getSourceFiles().find(file => file.fileName === domUtilsRoot); + if (!domUtilsFile) { + throw new Error(`File '${domUtilsRoot}' not found`); + } + const selectorsUtilsFile = program.getSourceFiles().find(file => file.fileName === selectorsUtilsRoot); + if (!selectorsUtilsFile) { + throw new Error(`File '${selectorsUtilsFile}' not found`); + } + const includeCoreMethods = (_a = options.includeCoreMethods) !== null && _a !== void 0 ? _a : false; + return { + domDefinitions: (0, extractor_1.default)(domUtilsFile, checker, (_b = options.domUtils.extraExports) !== null && _b !== void 0 ? _b : [], includeCoreMethods), + selectorsDefinitions: (0, extractor_1.default)(selectorsUtilsFile, checker, (_c = options.selectorsUtils.extraExports) !== null && _c !== void 0 ? _c : [], includeCoreMethods), + }; +} +function writeTestUtilsDocumentation({ outDir, ...rest }) { + const { domDefinitions, selectorsDefinitions } = documentTestUtils(rest); + node_fs_1.default.mkdirSync(outDir, { recursive: true }); + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'dom.js'), `module.exports = { classes: ${JSON.stringify(domDefinitions, null, 2)} };`); + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'selectors.js'), `module.exports = { classes: ${JSON.stringify(selectorsDefinitions, null, 2)} };`); + node_fs_1.default.copyFileSync(require.resolve('./interfaces.d.ts'), pathe_1.default.join(outDir, 'interfaces.d.ts')); + const dtsTemplate = `import { TestUtilsDefinition } from './interfaces'; + declare const definitions: TestUtilsDefinition; + export = definitions; + `; + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'dom.d.ts'), dtsTemplate); + node_fs_1.default.writeFileSync(pathe_1.default.join(outDir, 'selectors.d.ts'), dtsTemplate); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/test-utils/index.js.map b/lib/test-utils/index.js.map new file mode 100644 index 0000000..35284f0 --- /dev/null +++ b/lib/test-utils/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test-utils/index.ts"],"names":[],"mappings":";;;;;AAyBA,8CA8BC;AAED,kEAqBC;AA9ED,qEAAqE;AACrE,sCAAsC;AACtC,sDAAyB;AACzB,kDAA0B;AAC1B,mDAAiE;AACjE,4DAA+C;AAoB/C,SAAgB,iBAAiB,CAAC,OAAmC;;IACnE,MAAM,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,IAAA,sCAA0B,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;IAC3F,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,SAAS,YAAY,aAAa,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,kBAAkB,CAAC,CAAC;IACvG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,SAAS,kBAAkB,aAAa,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,kBAAkB,GAAG,MAAA,OAAO,CAAC,kBAAkB,mCAAI,KAAK,CAAC;IAC/D,OAAO;QACL,cAAc,EAAE,IAAA,mBAAoB,EAClC,YAAY,EACZ,OAAO,EACP,MAAA,OAAO,CAAC,QAAQ,CAAC,YAAY,mCAAI,EAAE,EACnC,kBAAkB,CACnB;QACD,oBAAoB,EAAE,IAAA,mBAAoB,EACxC,kBAAkB,EAClB,OAAO,EACP,MAAA,OAAO,CAAC,cAAc,CAAC,YAAY,mCAAI,EAAE,EACzC,kBAAkB,CACnB;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,GAAG,IAAI,EACyC;IAChD,MAAM,EAAE,cAAc,EAAE,oBAAoB,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzE,iBAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,+BAA+B,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAC5E,CAAC;IACF,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,+BAA+B,IAAI,CAAC,SAAS,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAClF,CAAC;IACF,iBAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7F,MAAM,WAAW,GAAG;;;GAGnB,CAAC;IACF,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9D,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAAC;AACtE,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport pathe from 'pathe';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport extractDocumentation from './extractor';\nimport { TestUtilsDoc } from './interfaces';\n\nexport interface TestUtilsVariantOptions {\n root: string;\n extraExports?: Array;\n}\n\nexport interface TestUtilsDocumenterOptions {\n tsconfigPath: string;\n includeCoreMethods?: boolean;\n domUtils: TestUtilsVariantOptions;\n selectorsUtils: TestUtilsVariantOptions;\n}\n\ninterface TestUtilsDefinitions {\n domDefinitions: Array;\n selectorsDefinitions: Array;\n}\n\nexport function documentTestUtils(options: TestUtilsDocumenterOptions): TestUtilsDefinitions {\n const domUtilsRoot = pathe.resolve(options.domUtils.root);\n const selectorsUtilsRoot = pathe.resolve(options.selectorsUtils.root);\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const domUtilsFile = program.getSourceFiles().find(file => file.fileName === domUtilsRoot);\n if (!domUtilsFile) {\n throw new Error(`File '${domUtilsRoot}' not found`);\n }\n\n const selectorsUtilsFile = program.getSourceFiles().find(file => file.fileName === selectorsUtilsRoot);\n if (!selectorsUtilsFile) {\n throw new Error(`File '${selectorsUtilsFile}' not found`);\n }\n const includeCoreMethods = options.includeCoreMethods ?? false;\n return {\n domDefinitions: extractDocumentation(\n domUtilsFile,\n checker,\n options.domUtils.extraExports ?? [],\n includeCoreMethods\n ),\n selectorsDefinitions: extractDocumentation(\n selectorsUtilsFile,\n checker,\n options.selectorsUtils.extraExports ?? [],\n includeCoreMethods\n ),\n };\n}\n\nexport function writeTestUtilsDocumentation({\n outDir,\n ...rest\n}: TestUtilsDocumenterOptions & { outDir: string }): void {\n const { domDefinitions, selectorsDefinitions } = documentTestUtils(rest);\n fs.mkdirSync(outDir, { recursive: true });\n fs.writeFileSync(\n pathe.join(outDir, 'dom.js'),\n `module.exports = { classes: ${JSON.stringify(domDefinitions, null, 2)} };`\n );\n fs.writeFileSync(\n pathe.join(outDir, 'selectors.js'),\n `module.exports = { classes: ${JSON.stringify(selectorsDefinitions, null, 2)} };`\n );\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n const dtsTemplate = `import { TestUtilsDefinition } from './interfaces';\n declare const definitions: TestUtilsDefinition;\n export = definitions;\n `;\n fs.writeFileSync(pathe.join(outDir, 'dom.d.ts'), dtsTemplate);\n fs.writeFileSync(pathe.join(outDir, 'selectors.d.ts'), dtsTemplate);\n}\n"]} \ No newline at end of file diff --git a/lib/test-utils/interfaces.d.ts b/lib/test-utils/interfaces.d.ts new file mode 100644 index 0000000..91644e7 --- /dev/null +++ b/lib/test-utils/interfaces.d.ts @@ -0,0 +1,33 @@ +export interface Parameter { + name: string; + typeName: string; + description?: string; + flags: { + isOptional?: boolean; + }; + defaultValue?: string; +} +interface TypeArgument { + name: string; +} +export interface TestUtilMethod { + name: string; + description?: string; + returnType: { + name: string; + isNullable: boolean; + typeArguments?: Array; + }; + parameters: Array; + inheritedFrom?: { + name: string; + }; +} +export interface TestUtilsDoc { + name: string; + methods: Array; +} +export interface TestUtilsDefinition { + classes: Array; +} +export {}; diff --git a/lib/test-utils/interfaces.js b/lib/test-utils/interfaces.js new file mode 100644 index 0000000..db91911 --- /dev/null +++ b/lib/test-utils/interfaces.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=interfaces.js.map \ No newline at end of file diff --git a/lib/test-utils/interfaces.js.map b/lib/test-utils/interfaces.js.map new file mode 100644 index 0000000..1656742 --- /dev/null +++ b/lib/test-utils/interfaces.js.map @@ -0,0 +1 @@ +{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/test-utils/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nexport interface Parameter {\n name: string;\n typeName: string;\n description?: string;\n flags: { isOptional?: boolean };\n defaultValue?: string;\n}\n\ninterface TypeArgument {\n name: string;\n}\n\nexport interface TestUtilMethod {\n name: string;\n description?: string;\n returnType: {\n name: string;\n isNullable: boolean;\n typeArguments?: Array;\n };\n parameters: Array;\n /* @deprecated All inherited methods should be filtered automatically */\n inheritedFrom?: {\n name: string;\n };\n}\n\nexport interface TestUtilsDoc {\n name: string;\n methods: Array;\n}\n\nexport interface TestUtilsDefinition {\n classes: Array;\n}\n"]} \ No newline at end of file diff --git a/package.json b/package.json index ce12b22..6644474 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,9 @@ "url": "https://github.com/cloudscape-design/documenter.git" }, "homepage": "https://cloudscape.design", - "main": "./index.js", + "main": "./lib/index.js", "exports": { - ".": "./index.js" + ".": "./lib/index.js" }, "scripts": { "lint": "eslint .", From b70c2910b5ff3302a9370c46335f58cf569ddcea Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 15:05:23 +0100 Subject: [PATCH 4/7] compatibility fixes --- src/components/component-definition.ts | 20 +++++++++++--------- src/components/extractor.ts | 6 +++--- src/components/index.ts | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/components/component-definition.ts b/src/components/component-definition.ts index b35244d..921cbff 100644 --- a/src/components/component-definition.ts +++ b/src/components/component-definition.ts @@ -44,15 +44,17 @@ export function buildComponentDefinition( checker: ts.TypeChecker, ): ComponentDefinition { const regions = props.filter(prop => prop.type === 'React.ReactNode'); - const events = props.filter(prop => { - // The onError event handler of the error boundary component does not follow the - // event handlers convention and is categorized to properties instead. - if (name === 'ErrorBoundary' && prop.name === 'onError') { - return false; - } else { - return prop.name.match(/^on[A-Z]/); - } - }); + const events: Array = []; + // treat all events as properties + // const events = props.filter(prop => { + // // The onError event handler of the error boundary component does not follow the + // // event handlers convention and is categorized to properties instead. + // if (name === 'ErrorBoundary' && prop.name === 'onError') { + // return false; + // } else { + // return prop.name.match(/^on[A-Z]/); + // } + // }); const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop)); return { name, diff --git a/src/components/extractor.ts b/src/components/extractor.ts index 961e477..45671c2 100644 --- a/src/components/extractor.ts +++ b/src/components/extractor.ts @@ -140,7 +140,7 @@ export function extractExports( componentName: string, exportSymbols: ts.Symbol[], checker: ts.TypeChecker, - extraExports: Record>, + extraExports: Record> | false, ) { let componentSymbol; let propsSymbol; @@ -152,8 +152,8 @@ export function extractExports( } else if (exportSymbol.name === `${componentName}Props`) { propsSymbol = exportSymbol; } else if ( - !extraExports[componentName] || - (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*')) + extraExports !== false && + (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name)) ) { unknownExports.push(exportSymbol.name); } diff --git a/src/components/index.ts b/src/components/index.ts index 4a548d9..9932b93 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -19,7 +19,7 @@ function componentNameFromPath(componentPath: string) { export interface DocumenterOptions { tsconfigPath: string; publicFilesGlob: string; - extraExports?: Record>; + extraExports?: Record> | false; } export interface WriteOptions { From 50b4ed1bd9f4186aaf2dc087df7248b9df2502d5 Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 15:05:44 +0100 Subject: [PATCH 5/7] update assets --- lib/components/component-definition.js | 23 +-- lib/components/component-definition.js.map | 2 +- lib/components/extract-value-descriptions.js | 2 +- .../extract-value-descriptions.js.map | 2 +- lib/components/extractor.d.ts | 2 +- lib/components/extractor.js | 4 +- lib/components/extractor.js.map | 2 +- lib/components/index.d.ts | 2 +- lib/components/index.js.map | 2 +- lib/components/object-definition.js.map | 2 +- lib/package.json | 17 +-- lib/shared/type-utils.js | 6 +- lib/shared/type-utils.js.map | 2 +- lib/test-utils/extractor.js.map | 2 +- lib/test-utils/index.js.map | 2 +- package-lock.json | 134 ++++++++++++++---- 16 files changed, 141 insertions(+), 65 deletions(-) diff --git a/lib/components/component-definition.js b/lib/components/component-definition.js index 0de8220..7dd8e80 100644 --- a/lib/components/component-definition.js +++ b/lib/components/component-definition.js @@ -6,7 +6,7 @@ const object_definition_1 = require("./object-definition"); function getCommentTag(description, name) { var _a; const tag = description.tags.find(tag => tag.name === name); - return tag ? (_a = tag.text) !== null && _a !== void 0 ? _a : '' : undefined; + return tag ? ((_a = tag.text) !== null && _a !== void 0 ? _a : '') : undefined; } function getCommentTags(description, name) { const tags = description.tags @@ -24,16 +24,17 @@ function castI18nTag(tag) { } function buildComponentDefinition(name, dashCaseName, props, functions, defaultValues, componentDescription, checker) { const regions = props.filter(prop => prop.type === 'React.ReactNode'); - const events = props.filter(prop => { - // The onError event handler of the error boundary component does not follow the - // event handlers convention and is categorized to properties instead. - if (name === 'ErrorBoundary' && prop.name === 'onError') { - return false; - } - else { - return prop.name.match(/^on[A-Z]/); - } - }); + const events = []; + // treat all events as properties + // const events = props.filter(prop => { + // // The onError event handler of the error boundary component does not follow the + // // event handlers convention and is categorized to properties instead. + // if (name === 'ErrorBoundary' && prop.name === 'onError') { + // return false; + // } else { + // return prop.name.match(/^on[A-Z]/); + // } + // }); const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop)); return { name, diff --git a/lib/components/component-definition.js.map b/lib/components/component-definition.js.map index c242e0e..53833dd 100644 --- a/lib/components/component-definition.js.map +++ b/lib/components/component-definition.js.map @@ -1 +1 @@ -{"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../src/components/component-definition.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport { extractDeclaration, stringifyType } from '../shared/type-utils';\nimport type {\n ComponentDefinition,\n ComponentFunction,\n ComponentProperty,\n ComponentRegion,\n EventHandler,\n} from './interfaces';\nimport type { ExpandedProp, ExtractedDescription } from './extractor';\nimport { getObjectDefinition } from './object-definition';\n\nfunction getCommentTag(description: ExtractedDescription, name: string) {\n const tag = description.tags.find(tag => tag.name === name);\n return tag ? tag.text ?? '' : undefined;\n}\n\nfunction getCommentTags(description: ExtractedDescription, name: string) {\n const tags = description.tags\n .filter(tag => tag.name === name)\n .map(tag => {\n if (!tag.text) {\n throw new Error(`Tag ${name} is missing text`);\n }\n return tag.text;\n });\n return tags.length > 0 ? tags : undefined;\n}\n\nfunction castI18nTag(tag: string | undefined) {\n return tag === undefined ? undefined : true;\n}\n\nexport function buildComponentDefinition(\n name: string,\n dashCaseName: string,\n props: Array,\n functions: Array,\n defaultValues: Record,\n componentDescription: ExtractedDescription,\n checker: ts.TypeChecker\n): ComponentDefinition {\n const regions = props.filter(prop => prop.type === 'React.ReactNode');\n const events = props.filter(prop => {\n // The onError event handler of the error boundary component does not follow the\n // event handlers convention and is categorized to properties instead.\n if (name === 'ErrorBoundary' && prop.name === 'onError') {\n return false;\n } else {\n return prop.name.match(/^on[A-Z]/);\n }\n });\n const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop));\n return {\n name,\n dashCaseName,\n releaseStatus: 'stable',\n description: componentDescription.text,\n systemTags: getCommentTags(componentDescription, 'awsuiSystem'),\n regions: regions.map(\n (region): ComponentRegion => ({\n name: region.name,\n displayName: getCommentTag(region.description, 'displayname'),\n description: region.description.text,\n isDefault: region.name === 'children',\n systemTags: getCommentTags(region.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(region.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(region.description, 'deprecated'),\n i18nTag: castI18nTag(getCommentTag(region.description, 'i18n')),\n })\n ),\n functions: functions.map(\n (func): ComponentFunction => ({\n name: func.name,\n description: func.description.text,\n returnType: stringifyType(func.rawType.getNonNullableType().getCallSignatures()[0].getReturnType(), checker),\n parameters: func.rawType\n .getNonNullableType()\n .getCallSignatures()[0]\n .getParameters()\n .map((param): ComponentFunction['parameters'][0] => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.name,\n type: stringifyType(paramType, checker),\n };\n }),\n })\n ),\n properties: onlyProps.map((property): ComponentProperty => {\n const { type, inlineType } = getObjectDefinition(property.type, property.rawType, property.rawTypeNode, checker);\n return {\n name: property.name,\n type: type,\n inlineType: inlineType,\n optional: property.isOptional,\n description: property.description.text,\n defaultValue: defaultValues[property.name],\n systemTags: getCommentTags(property.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(property.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(property.description, 'deprecated'),\n analyticsTag: getCommentTag(property.description, 'analytics'),\n i18nTag: castI18nTag(getCommentTag(property.description, 'i18n')),\n };\n }),\n events: events.map((event): EventHandler => {\n const { detailType, detailInlineType, cancelable } = extractEventDetails(\n event.rawType,\n event.rawTypeNode,\n checker\n );\n return {\n name: event.name,\n description: event.description.text,\n cancelable,\n detailType,\n detailInlineType,\n systemTags: getCommentTags(event.description, 'awsuiSystem'),\n deprecatedTag: getCommentTag(event.description, 'deprecated'),\n };\n }),\n };\n}\n\nfunction extractEventDetails(type: ts.Type, typeNode: ts.TypeNode | undefined, checker: ts.TypeChecker) {\n const realType = type.getNonNullableType();\n const handlerName = realType.aliasSymbol?.getName();\n if (handlerName !== 'CancelableEventHandler' && handlerName !== 'NonCancelableEventHandler') {\n throw new Error(`Unknown event handler type: ${checker.typeToString(realType)}`);\n }\n const cancelable = handlerName === 'CancelableEventHandler';\n const detailType = realType.aliasTypeArguments?.[0];\n if (detailType && detailType.getProperties().length > 0) {\n const { type, inlineType } = getObjectDefinition(stringifyType(detailType, checker), detailType, typeNode, checker);\n return {\n detailType: type,\n detailInlineType: inlineType,\n cancelable,\n };\n }\n return { cancelable };\n}\n"]} \ No newline at end of file +{"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../src/components/component-definition.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport { extractDeclaration, stringifyType } from '../shared/type-utils';\nimport type {\n ComponentDefinition,\n ComponentFunction,\n ComponentProperty,\n ComponentRegion,\n EventHandler,\n} from './interfaces';\nimport type { ExpandedProp, ExtractedDescription } from './extractor';\nimport { getObjectDefinition } from './object-definition';\n\nfunction getCommentTag(description: ExtractedDescription, name: string) {\n const tag = description.tags.find(tag => tag.name === name);\n return tag ? (tag.text ?? '') : undefined;\n}\n\nfunction getCommentTags(description: ExtractedDescription, name: string) {\n const tags = description.tags\n .filter(tag => tag.name === name)\n .map(tag => {\n if (!tag.text) {\n throw new Error(`Tag ${name} is missing text`);\n }\n return tag.text;\n });\n return tags.length > 0 ? tags : undefined;\n}\n\nfunction castI18nTag(tag: string | undefined) {\n return tag === undefined ? undefined : true;\n}\n\nexport function buildComponentDefinition(\n name: string,\n dashCaseName: string,\n props: Array,\n functions: Array,\n defaultValues: Record,\n componentDescription: ExtractedDescription,\n checker: ts.TypeChecker,\n): ComponentDefinition {\n const regions = props.filter(prop => prop.type === 'React.ReactNode');\n const events: Array = [];\n // treat all events as properties\n // const events = props.filter(prop => {\n // // The onError event handler of the error boundary component does not follow the\n // // event handlers convention and is categorized to properties instead.\n // if (name === 'ErrorBoundary' && prop.name === 'onError') {\n // return false;\n // } else {\n // return prop.name.match(/^on[A-Z]/);\n // }\n // });\n const onlyProps = props.filter(prop => !events.includes(prop) && !regions.includes(prop));\n return {\n name,\n dashCaseName,\n releaseStatus: 'stable',\n description: componentDescription.text,\n systemTags: getCommentTags(componentDescription, 'awsuiSystem'),\n regions: regions.map(\n (region): ComponentRegion => ({\n name: region.name,\n displayName: getCommentTag(region.description, 'displayname'),\n description: region.description.text,\n isDefault: region.name === 'children',\n systemTags: getCommentTags(region.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(region.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(region.description, 'deprecated'),\n i18nTag: castI18nTag(getCommentTag(region.description, 'i18n')),\n }),\n ),\n functions: functions.map(\n (func): ComponentFunction => ({\n name: func.name,\n description: func.description.text,\n returnType: stringifyType(func.rawType.getNonNullableType().getCallSignatures()[0].getReturnType(), checker),\n parameters: func.rawType\n .getNonNullableType()\n .getCallSignatures()[0]\n .getParameters()\n .map((param): ComponentFunction['parameters'][0] => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.name,\n type: stringifyType(paramType, checker),\n };\n }),\n }),\n ),\n properties: onlyProps.map((property): ComponentProperty => {\n const { type, inlineType } = getObjectDefinition(property.type, property.rawType, property.rawTypeNode, checker);\n return {\n name: property.name,\n type: type,\n inlineType: inlineType,\n optional: property.isOptional,\n description: property.description.text,\n defaultValue: defaultValues[property.name],\n systemTags: getCommentTags(property.description, 'awsuiSystem'),\n visualRefreshTag: getCommentTag(property.description, 'visualrefresh'),\n deprecatedTag: getCommentTag(property.description, 'deprecated'),\n analyticsTag: getCommentTag(property.description, 'analytics'),\n i18nTag: castI18nTag(getCommentTag(property.description, 'i18n')),\n };\n }),\n events: events.map((event): EventHandler => {\n const { detailType, detailInlineType, cancelable } = extractEventDetails(\n event.rawType,\n event.rawTypeNode,\n checker,\n );\n return {\n name: event.name,\n description: event.description.text,\n cancelable,\n detailType,\n detailInlineType,\n systemTags: getCommentTags(event.description, 'awsuiSystem'),\n deprecatedTag: getCommentTag(event.description, 'deprecated'),\n };\n }),\n };\n}\n\nfunction extractEventDetails(type: ts.Type, typeNode: ts.TypeNode | undefined, checker: ts.TypeChecker) {\n const realType = type.getNonNullableType();\n const handlerName = realType.aliasSymbol?.getName();\n if (handlerName !== 'CancelableEventHandler' && handlerName !== 'NonCancelableEventHandler') {\n throw new Error(`Unknown event handler type: ${checker.typeToString(realType)}`);\n }\n const cancelable = handlerName === 'CancelableEventHandler';\n const detailType = realType.aliasTypeArguments?.[0];\n if (detailType && detailType.getProperties().length > 0) {\n const { type, inlineType } = getObjectDefinition(stringifyType(detailType, checker), detailType, typeNode, checker);\n return {\n detailType: type,\n detailInlineType: inlineType,\n cancelable,\n };\n }\n return { cancelable };\n}\n"]} \ No newline at end of file diff --git a/lib/components/extract-value-descriptions.js b/lib/components/extract-value-descriptions.js index b1a9fae..c60b061 100644 --- a/lib/components/extract-value-descriptions.js +++ b/lib/components/extract-value-descriptions.js @@ -43,7 +43,7 @@ function extractValueDescriptions(type, typeNode) { if (!comment) { return undefined; } - const systemTags = Array.from(comment.matchAll(/@awsuiSystem\s+(\w+)/g), ([_, system]) => system); + const systemTags = Array.from(comment.matchAll(/@awsuiSystem\s+(\w+)/g), ([, system]) => system); return systemTags.length > 0 ? { systemTags } : undefined; }); } diff --git a/lib/components/extract-value-descriptions.js.map b/lib/components/extract-value-descriptions.js.map index a430c9d..a241688 100644 --- a/lib/components/extract-value-descriptions.js.map +++ b/lib/components/extract-value-descriptions.js.map @@ -1 +1 @@ -{"version":3,"file":"extract-value-descriptions.js","sourceRoot":"","sources":["../../src/components/extract-value-descriptions.ts"],"names":[],"mappings":";;;;;AAMA,4DAwCC;AA9CD,qEAAqE;AACrE,sCAAsC;AACtC,4DAA4B;AAC5B,qDAA0D;AAG1D,SAAgB,wBAAwB,CAAC,IAAgC,EAAE,QAAiC;;IAC1G,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,uEAAuE;QACvE,MAAM,gBAAgB,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,oBAAE,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChD,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,mCAAmC;IACnC,6HAA6H;IAC7H,IAAI,SAAS,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,WAAW,GAA8B,EAAE,CAAC;IAClD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,MAAA,WAAW,CAAC,WAAW,CAAC,mCAAI,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACpF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC1C,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,iCAAiC;IACjC,uHAAuH;IACvH,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAgC,EAAE;QAC3E,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAClG,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport { extractDeclaration } from '../shared/type-utils';\nimport { ValueDescription } from './interfaces';\n\nexport function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined) {\n if (type.aliasSymbol) {\n // Traverse from \"variant: ButtonProps.Variant\" to \"type Variant = ...\"\n const aliasDeclaration = extractDeclaration(type.aliasSymbol);\n if (ts.isTypeAliasDeclaration(aliasDeclaration)) {\n typeNode = aliasDeclaration.type;\n }\n }\n\n if (!typeNode) {\n return [];\n }\n\n const maybeList = typeNode.getChildren()[0];\n // based on similar code in typedoc\n // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438\n if (maybeList.kind !== ts.SyntaxKind.SyntaxList) {\n return [];\n }\n const rawComments: Array = [];\n let memberIndex = 0;\n for (const child of maybeList.getChildren()) {\n const text = child.getFullText();\n if (text.includes('/**')) {\n rawComments[memberIndex] = (rawComments[memberIndex] ?? '') + child.getFullText();\n }\n\n if (child.kind !== ts.SyntaxKind.BarToken) {\n memberIndex++;\n }\n }\n // Array.from to fix sparse array\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots\n return Array.from(rawComments).map((comment): ValueDescription | undefined => {\n if (!comment) {\n return undefined;\n }\n const systemTags = Array.from(comment.matchAll(/@awsuiSystem\\s+(\\w+)/g), ([_, system]) => system);\n return systemTags.length > 0 ? { systemTags } : undefined;\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"extract-value-descriptions.js","sourceRoot":"","sources":["../../src/components/extract-value-descriptions.ts"],"names":[],"mappings":";;;;;AAMA,4DAwCC;AA9CD,qEAAqE;AACrE,sCAAsC;AACtC,4DAA4B;AAC5B,qDAA0D;AAG1D,SAAgB,wBAAwB,CAAC,IAAgC,EAAE,QAAiC;;IAC1G,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,uEAAuE;QACvE,MAAM,gBAAgB,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9D,IAAI,oBAAE,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChD,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,mCAAmC;IACnC,6HAA6H;IAC7H,IAAI,SAAS,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,WAAW,GAA8B,EAAE,CAAC;IAClD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,MAAA,WAAW,CAAC,WAAW,CAAC,mCAAI,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACpF,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC1C,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,iCAAiC;IACjC,uHAAuH;IACvH,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAgC,EAAE;QAC3E,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QACjG,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport { extractDeclaration } from '../shared/type-utils';\nimport { ValueDescription } from './interfaces';\n\nexport function extractValueDescriptions(type: ts.UnionOrIntersectionType, typeNode: ts.TypeNode | undefined) {\n if (type.aliasSymbol) {\n // Traverse from \"variant: ButtonProps.Variant\" to \"type Variant = ...\"\n const aliasDeclaration = extractDeclaration(type.aliasSymbol);\n if (ts.isTypeAliasDeclaration(aliasDeclaration)) {\n typeNode = aliasDeclaration.type;\n }\n }\n\n if (!typeNode) {\n return [];\n }\n\n const maybeList = typeNode.getChildren()[0];\n // based on similar code in typedoc\n // https://github.com/TypeStrong/typedoc/blob/6090b3e31471cea3728db1b03888bca5703b437e/src/lib/converter/symbols.ts#L406-L438\n if (maybeList.kind !== ts.SyntaxKind.SyntaxList) {\n return [];\n }\n const rawComments: Array = [];\n let memberIndex = 0;\n for (const child of maybeList.getChildren()) {\n const text = child.getFullText();\n if (text.includes('/**')) {\n rawComments[memberIndex] = (rawComments[memberIndex] ?? '') + child.getFullText();\n }\n\n if (child.kind !== ts.SyntaxKind.BarToken) {\n memberIndex++;\n }\n }\n // Array.from to fix sparse array\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#array_methods_and_empty_slots\n return Array.from(rawComments).map((comment): ValueDescription | undefined => {\n if (!comment) {\n return undefined;\n }\n const systemTags = Array.from(comment.matchAll(/@awsuiSystem\\s+(\\w+)/g), ([, system]) => system);\n return systemTags.length > 0 ? { systemTags } : undefined;\n });\n}\n"]} \ No newline at end of file diff --git a/lib/components/extractor.d.ts b/lib/components/extractor.d.ts index 2757624..138fdd2 100644 --- a/lib/components/extractor.d.ts +++ b/lib/components/extractor.d.ts @@ -17,7 +17,7 @@ export interface ExpandedProp { export declare function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker): Record; export declare function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker): ExpandedProp[]; export declare function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker): ExpandedProp[]; -export declare function extractExports(componentName: string, exportSymbols: ts.Symbol[], checker: ts.TypeChecker, extraExports: Record>): { +export declare function extractExports(componentName: string, exportSymbols: ts.Symbol[], checker: ts.TypeChecker, extraExports: Record> | false): { componentSymbol: ts.Symbol; propsSymbol: ts.Symbol; }; diff --git a/lib/components/extractor.js b/lib/components/extractor.js index fd33de4..eb81ab7 100644 --- a/lib/components/extractor.js +++ b/lib/components/extractor.js @@ -124,8 +124,8 @@ function extractExports(componentName, exportSymbols, checker, extraExports) { else if (exportSymbol.name === `${componentName}Props`) { propsSymbol = exportSymbol; } - else if (!extraExports[componentName] || - (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*'))) { + else if (extraExports !== false && + (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name))) { unknownExports.push(exportSymbol.name); } } diff --git a/lib/components/extractor.js.map b/lib/components/extractor.js.map index eeafcf8..c81f649 100644 --- a/lib/components/extractor.js.map +++ b/lib/components/extractor.js.map @@ -1 +1 @@ -{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/components/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport {\n extractDeclaration,\n getDescription,\n isOptional,\n stringifyType,\n unwrapNamespaceDeclaration,\n} from '../shared/type-utils';\n\nexport interface ExtractedDescription {\n text: string | undefined;\n tags: Array<{ name: string; text: string | undefined }>;\n}\n\nexport interface ExpandedProp {\n name: string;\n type: string;\n isOptional: boolean;\n rawType: ts.Type;\n rawTypeNode: ts.TypeNode | undefined;\n description: ExtractedDescription;\n}\n\nexport function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker) {\n let declaration: ts.Node = extractDeclaration(exportSymbol);\n if (ts.isExportAssignment(declaration)) {\n // Traverse from \"export default Something;\" to the actual \"Something\"\n const symbol = checker.getSymbolAtLocation(declaration.expression);\n if (!symbol) {\n throw new Error('Cannot resolve symbol');\n }\n declaration = extractDeclaration(symbol);\n }\n // Extract \"Something\" from \"const Component = Something\"\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n declaration = declaration.initializer;\n }\n // Extract \"Something\" from \"Something as MyComponentType\"\n if (ts.isAsExpression(declaration)) {\n declaration = declaration.expression;\n }\n // Extract \"Something from React.forwardRef(Something)\"\n if (\n ts.isCallExpression(declaration) &&\n (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')\n ) {\n declaration = declaration.arguments[0];\n }\n\n // In the component function, find arguments destructuring\n let argument: ts.Node | undefined;\n if (\n ts.isFunctionDeclaration(declaration) ||\n ts.isFunctionExpression(declaration) ||\n ts.isArrowFunction(declaration)\n ) {\n if (declaration.parameters.length === 0) {\n return {};\n }\n argument = declaration.parameters[0].name;\n }\n if (!argument) {\n throw new Error(`Unsupported component declaration type ${ts.SyntaxKind[declaration.kind]}`);\n }\n if (!ts.isObjectBindingPattern(argument)) {\n // if a component does not use props de-structuring, we do not detect default values\n return {};\n }\n const values: Record = {};\n for (const element of argument.elements) {\n if (ts.isIdentifier(element.name) && element.initializer) {\n values[element.name.escapedText as string] = element.initializer.getText();\n }\n }\n return values;\n}\n\nexport function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol);\n\n return exportType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n return {\n name: value.name,\n type: stringifyType(type, checker),\n rawType: type,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const propsName = propsSymbol.getName();\n const namespaceDeclaration = [\n // if we got the namespace directly\n ...(propsSymbol.getDeclarations() ?? []),\n // find namespace declaration from the interface with the same name\n ...(checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()?.getDeclarations() ?? []),\n ].find(decl => decl.kind === ts.SyntaxKind.ModuleDeclaration);\n const refType = unwrapNamespaceDeclaration(namespaceDeclaration)\n .map(child => checker.getTypeAtLocation(child))\n .find(type => (type.getSymbol() ?? type.aliasSymbol)?.getName() === 'Ref');\n\n if (!refType) {\n return [];\n }\n return refType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n const realType = type.getNonNullableType();\n if (realType.getCallSignatures().length === 0) {\n throw new Error(\n `${propsName}.Ref should contain only methods, \"${value.name}\" has a \"${stringifyType(type, checker)}\" type`\n );\n }\n return {\n name: value.name,\n type: stringifyType(realType, checker),\n rawType: realType,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractExports(\n componentName: string,\n exportSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n extraExports: Record>\n) {\n let componentSymbol;\n let propsSymbol;\n const unknownExports: Array = [];\n for (const exportSymbol of exportSymbols) {\n if (exportSymbol.name === 'default') {\n validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker);\n componentSymbol = exportSymbol;\n } else if (exportSymbol.name === `${componentName}Props`) {\n propsSymbol = exportSymbol;\n } else if (\n !extraExports[componentName] ||\n (!extraExports[componentName].includes(exportSymbol.name) && !extraExports[componentName].includes('*'))\n ) {\n unknownExports.push(exportSymbol.name);\n }\n }\n if (unknownExports.length > 0) {\n throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`);\n }\n if (!componentSymbol) {\n throw new Error(`Missing default export for ${componentName}`);\n }\n if (!propsSymbol) {\n throw new Error(`Missing ${componentName}Props export`);\n }\n return { componentSymbol, propsSymbol };\n}\n\nfunction validateComponentType(type: ts.Type, checker: ts.TypeChecker) {\n if (\n // React.forwardRef\n type.getSymbol()?.name !== 'ForwardRefExoticComponent' &&\n // Plain function returning JSX\n type.getCallSignatures().some(signature => {\n const returnTypeName = checker.typeToString(signature.getReturnType());\n return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal';\n })\n ) {\n throw new Error(`Unknown default export type ${checker.typeToString(type)}`);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/components/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport {\n extractDeclaration,\n getDescription,\n isOptional,\n stringifyType,\n unwrapNamespaceDeclaration,\n} from '../shared/type-utils';\n\nexport interface ExtractedDescription {\n text: string | undefined;\n tags: Array<{ name: string; text: string | undefined }>;\n}\n\nexport interface ExpandedProp {\n name: string;\n type: string;\n isOptional: boolean;\n rawType: ts.Type;\n rawTypeNode: ts.TypeNode | undefined;\n description: ExtractedDescription;\n}\n\nexport function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker) {\n let declaration: ts.Node = extractDeclaration(exportSymbol);\n if (ts.isExportAssignment(declaration)) {\n // Traverse from \"export default Something;\" to the actual \"Something\"\n const symbol = checker.getSymbolAtLocation(declaration.expression);\n if (!symbol) {\n throw new Error('Cannot resolve symbol');\n }\n declaration = extractDeclaration(symbol);\n }\n // Extract \"Something\" from \"const Component = Something\"\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n declaration = declaration.initializer;\n }\n // Extract \"Something\" from \"Something as MyComponentType\"\n if (ts.isAsExpression(declaration)) {\n declaration = declaration.expression;\n }\n // Extract \"Something from React.forwardRef(Something)\"\n if (\n ts.isCallExpression(declaration) &&\n (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')\n ) {\n declaration = declaration.arguments[0];\n }\n\n // In the component function, find arguments destructuring\n let argument: ts.Node | undefined;\n if (\n ts.isFunctionDeclaration(declaration) ||\n ts.isFunctionExpression(declaration) ||\n ts.isArrowFunction(declaration)\n ) {\n if (declaration.parameters.length === 0) {\n return {};\n }\n argument = declaration.parameters[0].name;\n }\n if (!argument) {\n throw new Error(`Unsupported component declaration type ${ts.SyntaxKind[declaration.kind]}`);\n }\n if (!ts.isObjectBindingPattern(argument)) {\n // if a component does not use props de-structuring, we do not detect default values\n return {};\n }\n const values: Record = {};\n for (const element of argument.elements) {\n if (ts.isIdentifier(element.name) && element.initializer) {\n values[element.name.escapedText as string] = element.initializer.getText();\n }\n }\n return values;\n}\n\nexport function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol);\n\n return exportType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n return {\n name: value.name,\n type: stringifyType(type, checker),\n rawType: type,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const propsName = propsSymbol.getName();\n const namespaceDeclaration = [\n // if we got the namespace directly\n ...(propsSymbol.getDeclarations() ?? []),\n // find namespace declaration from the interface with the same name\n ...(checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()?.getDeclarations() ?? []),\n ].find(decl => decl.kind === ts.SyntaxKind.ModuleDeclaration);\n const refType = unwrapNamespaceDeclaration(namespaceDeclaration)\n .map(child => checker.getTypeAtLocation(child))\n .find(type => (type.getSymbol() ?? type.aliasSymbol)?.getName() === 'Ref');\n\n if (!refType) {\n return [];\n }\n return refType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n const realType = type.getNonNullableType();\n if (realType.getCallSignatures().length === 0) {\n throw new Error(\n `${propsName}.Ref should contain only methods, \"${value.name}\" has a \"${stringifyType(type, checker)}\" type`,\n );\n }\n return {\n name: value.name,\n type: stringifyType(realType, checker),\n rawType: realType,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractExports(\n componentName: string,\n exportSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n extraExports: Record> | false,\n) {\n let componentSymbol;\n let propsSymbol;\n const unknownExports: Array = [];\n for (const exportSymbol of exportSymbols) {\n if (exportSymbol.name === 'default') {\n validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker);\n componentSymbol = exportSymbol;\n } else if (exportSymbol.name === `${componentName}Props`) {\n propsSymbol = exportSymbol;\n } else if (\n extraExports !== false &&\n (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name))\n ) {\n unknownExports.push(exportSymbol.name);\n }\n }\n if (unknownExports.length > 0) {\n throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`);\n }\n if (!componentSymbol) {\n throw new Error(`Missing default export for ${componentName}`);\n }\n if (!propsSymbol) {\n throw new Error(`Missing ${componentName}Props export`);\n }\n return { componentSymbol, propsSymbol };\n}\n\nfunction validateComponentType(type: ts.Type, checker: ts.TypeChecker) {\n if (\n // React.forwardRef\n type.getSymbol()?.name !== 'ForwardRefExoticComponent' &&\n // Plain function returning JSX\n type.getCallSignatures().some(signature => {\n const returnTypeName = checker.typeToString(signature.getReturnType());\n return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal';\n })\n ) {\n throw new Error(`Unknown default export type ${checker.typeToString(type)}`);\n }\n}\n"]} \ No newline at end of file diff --git a/lib/components/index.d.ts b/lib/components/index.d.ts index 5f3e28c..0e39742 100644 --- a/lib/components/index.d.ts +++ b/lib/components/index.d.ts @@ -2,7 +2,7 @@ import type { ComponentDefinition } from './interfaces'; export interface DocumenterOptions { tsconfigPath: string; publicFilesGlob: string; - extraExports?: Record>; + extraExports?: Record> | false; } export interface WriteOptions { outDir: string; diff --git a/lib/components/index.js.map b/lib/components/index.js.map index 602dac7..634f095 100644 --- a/lib/components/index.js.map +++ b/lib/components/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport { pascalCase } from 'change-case';\nimport pathe from 'pathe';\nimport { matcher } from 'micromatch';\n\nimport { buildComponentDefinition } from './component-definition';\nimport { extractDefaultValues, extractExports, extractFunctions, extractProps } from './extractor';\nimport type { ComponentDefinition } from './interfaces';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport { extractDeclaration, getDescription } from '../shared/type-utils';\n\nfunction componentNameFromPath(componentPath: string) {\n const dashCaseName = pathe.basename(pathe.dirname(componentPath));\n return { dashCaseName, name: pascalCase(dashCaseName) };\n}\n\nexport interface DocumenterOptions {\n tsconfigPath: string;\n publicFilesGlob: string;\n extraExports?: Record>;\n}\n\nexport interface WriteOptions {\n outDir: string;\n}\n\nexport function writeComponentsDocumentation({ outDir, ...options }: WriteOptions & DocumenterOptions): void {\n const definitions = documentComponents(options);\n fs.mkdirSync(outDir, { recursive: true });\n for (const definition of definitions) {\n fs.writeFileSync(\n pathe.join(outDir, definition.dashCaseName + '.js'),\n `module.exports = ${JSON.stringify(definition, null, 2)};`\n );\n }\n const indexContent = `module.exports = {\n ${definitions\n .map(definition => `${JSON.stringify(definition.dashCaseName)}:require('./${definition.dashCaseName}')`)\n .join(',\\n')}\n }`;\n fs.writeFileSync(pathe.join(outDir, 'index.js'), indexContent);\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n fs.writeFileSync(\n pathe.join(outDir, 'index.d.ts'),\n `import { ComponentDefinition } from './interfaces';\ndeclare const definitions: Record;\nexport = definitions;\n`\n );\n}\n\nexport function documentComponents(options: DocumenterOptions): Array {\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const isMatch = matcher(pathe.resolve(options.publicFilesGlob));\n\n const sourceFiles = program.getSourceFiles().filter(file => isMatch(file.fileName));\n\n if (sourceFiles.length === 0) {\n throw new Error(`No files found matching ${options.publicFilesGlob}`);\n }\n\n return sourceFiles.map(sourceFile => {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n const { name, dashCaseName } = componentNameFromPath(sourceFile.fileName);\n\n // istanbul ignore next\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const { propsSymbol, componentSymbol } = extractExports(name, exportSymbols, checker, options?.extraExports ?? {});\n const props = extractProps(propsSymbol, checker);\n const functions = extractFunctions(propsSymbol, checker);\n const defaultValues = extractDefaultValues(componentSymbol, checker);\n const componentDescription = getDescription(\n componentSymbol.getDocumentationComment(checker),\n extractDeclaration(componentSymbol)\n );\n\n return buildComponentDefinition(name, dashCaseName, props, functions, defaultValues, componentDescription, checker);\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport { pascalCase } from 'change-case';\nimport pathe from 'pathe';\nimport { matcher } from 'micromatch';\n\nimport { buildComponentDefinition } from './component-definition';\nimport { extractDefaultValues, extractExports, extractFunctions, extractProps } from './extractor';\nimport type { ComponentDefinition } from './interfaces';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport { extractDeclaration, getDescription } from '../shared/type-utils';\n\nfunction componentNameFromPath(componentPath: string) {\n const dashCaseName = pathe.basename(pathe.dirname(componentPath));\n return { dashCaseName, name: pascalCase(dashCaseName) };\n}\n\nexport interface DocumenterOptions {\n tsconfigPath: string;\n publicFilesGlob: string;\n extraExports?: Record> | false;\n}\n\nexport interface WriteOptions {\n outDir: string;\n}\n\nexport function writeComponentsDocumentation({ outDir, ...options }: WriteOptions & DocumenterOptions): void {\n const definitions = documentComponents(options);\n fs.mkdirSync(outDir, { recursive: true });\n for (const definition of definitions) {\n fs.writeFileSync(\n pathe.join(outDir, definition.dashCaseName + '.js'),\n `module.exports = ${JSON.stringify(definition, null, 2)};`,\n );\n }\n const indexContent = `module.exports = {\n ${definitions\n .map(definition => `${JSON.stringify(definition.dashCaseName)}:require('./${definition.dashCaseName}')`)\n .join(',\\n')}\n }`;\n fs.writeFileSync(pathe.join(outDir, 'index.js'), indexContent);\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n fs.writeFileSync(\n pathe.join(outDir, 'index.d.ts'),\n `import { ComponentDefinition } from './interfaces';\ndeclare const definitions: Record;\nexport = definitions;\n`,\n );\n}\n\nexport function documentComponents(options: DocumenterOptions): Array {\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const isMatch = matcher(pathe.resolve(options.publicFilesGlob));\n\n const sourceFiles = program.getSourceFiles().filter(file => isMatch(file.fileName));\n\n if (sourceFiles.length === 0) {\n throw new Error(`No files found matching ${options.publicFilesGlob}`);\n }\n\n return sourceFiles.map(sourceFile => {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n const { name, dashCaseName } = componentNameFromPath(sourceFile.fileName);\n\n // istanbul ignore next\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const { propsSymbol, componentSymbol } = extractExports(name, exportSymbols, checker, options?.extraExports ?? {});\n const props = extractProps(propsSymbol, checker);\n const functions = extractFunctions(propsSymbol, checker);\n const defaultValues = extractDefaultValues(componentSymbol, checker);\n const componentDescription = getDescription(\n componentSymbol.getDocumentationComment(checker),\n extractDeclaration(componentSymbol),\n );\n\n return buildComponentDefinition(name, dashCaseName, props, functions, defaultValues, componentDescription, checker);\n });\n}\n"]} \ No newline at end of file diff --git a/lib/components/object-definition.js.map b/lib/components/object-definition.js.map index 210ce67..3921e7c 100644 --- a/lib/components/object-definition.js.map +++ b/lib/components/object-definition.js.map @@ -1 +1 @@ -{"version":3,"file":"object-definition.js","sourceRoot":"","sources":["../../src/components/object-definition.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport type { TypeDefinition, UnionTypeDefinition, ValueDescription } from './interfaces';\nimport { extractDeclaration, isOptional, stringifyType } from '../shared/type-utils';\nimport { extractValueDescriptions } from './extract-value-descriptions';\n\nfunction isArrayType(type: ts.Type) {\n const symbol = type.getSymbol();\n if (!symbol) {\n return false;\n }\n return symbol.getName() === 'Array' || symbol.getName() === 'ReadonlyArray';\n}\n\nexport function getObjectDefinition(\n type: string,\n rawType: ts.Type,\n rawTypeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker\n): { type: string; inlineType?: TypeDefinition } {\n const realType = rawType.getNonNullableType();\n const realTypeName = stringifyType(realType, checker);\n if (\n realType.flags & ts.TypeFlags.String ||\n realType.flags & ts.TypeFlags.Literal ||\n realType.flags & ts.TypeFlags.Boolean ||\n realType.flags & ts.TypeFlags.Number ||\n isArrayType(realType) ||\n realTypeName === 'HTMLElement' ||\n realTypeName.split('.')[0] === 'Highcharts' ||\n type === 'React.ReactNode'\n ) {\n // do not expand built-in Javascript methods or primitive values\n return { type };\n }\n if (realType.isUnionOrIntersection()) {\n return getUnionTypeDefinition(realTypeName, realType, rawTypeNode, checker);\n }\n if (realType.getProperties().length > 0) {\n const properties = realType\n .getProperties()\n .map(prop => {\n const propNode = extractDeclaration(prop) as ts.PropertyDeclaration;\n const propType = checker.getTypeAtLocation(propNode);\n const typeString = stringifyType(propType, checker);\n\n return {\n name: prop.getName(),\n optional: isOptional(propType),\n ...getObjectDefinition(typeString, propType, propNode.type, checker),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n return {\n type: type,\n inlineType: {\n name: realTypeName.length < 100 ? realTypeName : 'object',\n type: 'object',\n properties: properties,\n },\n };\n }\n if (realType.getCallSignatures().length > 0) {\n if (realType.getCallSignatures().length > 1) {\n throw new Error('Multiple call signatures are not supported');\n }\n const signature = realType.getCallSignatures()[0];\n\n return {\n type,\n inlineType: {\n name: realTypeName,\n type: 'function',\n returnType: stringifyType(signature.getReturnType(), checker),\n parameters: signature.getParameters().map(param => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.getName(),\n type: stringifyType(paramType, checker),\n };\n }),\n },\n };\n }\n return { type };\n}\n\nfunction getPrimitiveType(type: ts.UnionOrIntersectionType) {\n if (type.types.every(subtype => subtype.isStringLiteral())) {\n return 'string';\n }\n if (type.types.every(subtype => subtype.isNumberLiteral())) {\n return 'number';\n }\n return undefined;\n}\n\nfunction getUnionTypeDefinition(\n realTypeName: string,\n realType: ts.UnionOrIntersectionType,\n typeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker\n): { type: string; inlineType: UnionTypeDefinition } {\n const valueDescriptions = extractValueDescriptions(realType, typeNode);\n const primitiveType = getPrimitiveType(realType);\n const values = realType.types.map(subtype =>\n primitiveType ? (subtype as ts.LiteralType).value.toString() : stringifyType(subtype, checker)\n );\n\n return {\n type: primitiveType ?? realTypeName,\n inlineType: {\n name: realTypeName,\n type: 'union',\n valueDescriptions: valueDescriptions.length > 0 ? zipValueDescriptions(values, valueDescriptions) : undefined,\n values: values,\n },\n };\n}\n\nfunction zipValueDescriptions(values: Array, descriptions: Array) {\n const descriptionsMap: Record = {};\n values.forEach((value, index) => {\n const description = descriptions[index];\n if (description) {\n descriptionsMap[value] = description;\n }\n });\n return descriptionsMap;\n}\n"]} \ No newline at end of file +{"version":3,"file":"object-definition.js","sourceRoot":"","sources":["../../src/components/object-definition.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport type { TypeDefinition, UnionTypeDefinition, ValueDescription } from './interfaces';\nimport { extractDeclaration, isOptional, stringifyType } from '../shared/type-utils';\nimport { extractValueDescriptions } from './extract-value-descriptions';\n\nfunction isArrayType(type: ts.Type) {\n const symbol = type.getSymbol();\n if (!symbol) {\n return false;\n }\n return symbol.getName() === 'Array' || symbol.getName() === 'ReadonlyArray';\n}\n\nexport function getObjectDefinition(\n type: string,\n rawType: ts.Type,\n rawTypeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker,\n): { type: string; inlineType?: TypeDefinition } {\n const realType = rawType.getNonNullableType();\n const realTypeName = stringifyType(realType, checker);\n if (\n realType.flags & ts.TypeFlags.String ||\n realType.flags & ts.TypeFlags.Literal ||\n realType.flags & ts.TypeFlags.Boolean ||\n realType.flags & ts.TypeFlags.Number ||\n isArrayType(realType) ||\n realTypeName === 'HTMLElement' ||\n realTypeName.split('.')[0] === 'Highcharts' ||\n type === 'React.ReactNode'\n ) {\n // do not expand built-in Javascript methods or primitive values\n return { type };\n }\n if (realType.isUnionOrIntersection()) {\n return getUnionTypeDefinition(realTypeName, realType, rawTypeNode, checker);\n }\n if (realType.getProperties().length > 0) {\n const properties = realType\n .getProperties()\n .map(prop => {\n const propNode = extractDeclaration(prop) as ts.PropertyDeclaration;\n const propType = checker.getTypeAtLocation(propNode);\n const typeString = stringifyType(propType, checker);\n\n return {\n name: prop.getName(),\n optional: isOptional(propType),\n ...getObjectDefinition(typeString, propType, propNode.type, checker),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n return {\n type: type,\n inlineType: {\n name: realTypeName.length < 100 ? realTypeName : 'object',\n type: 'object',\n properties: properties,\n },\n };\n }\n if (realType.getCallSignatures().length > 0) {\n if (realType.getCallSignatures().length > 1) {\n throw new Error('Multiple call signatures are not supported');\n }\n const signature = realType.getCallSignatures()[0];\n\n return {\n type,\n inlineType: {\n name: realTypeName,\n type: 'function',\n returnType: stringifyType(signature.getReturnType(), checker),\n parameters: signature.getParameters().map(param => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(param));\n return {\n name: param.getName(),\n type: stringifyType(paramType, checker),\n };\n }),\n },\n };\n }\n return { type };\n}\n\nfunction getPrimitiveType(type: ts.UnionOrIntersectionType) {\n if (type.types.every(subtype => subtype.isStringLiteral())) {\n return 'string';\n }\n if (type.types.every(subtype => subtype.isNumberLiteral())) {\n return 'number';\n }\n return undefined;\n}\n\nfunction getUnionTypeDefinition(\n realTypeName: string,\n realType: ts.UnionOrIntersectionType,\n typeNode: ts.TypeNode | undefined,\n checker: ts.TypeChecker,\n): { type: string; inlineType: UnionTypeDefinition } {\n const valueDescriptions = extractValueDescriptions(realType, typeNode);\n const primitiveType = getPrimitiveType(realType);\n const values = realType.types.map(subtype =>\n primitiveType ? (subtype as ts.LiteralType).value.toString() : stringifyType(subtype, checker),\n );\n\n return {\n type: primitiveType ?? realTypeName,\n inlineType: {\n name: realTypeName,\n type: 'union',\n valueDescriptions: valueDescriptions.length > 0 ? zipValueDescriptions(values, valueDescriptions) : undefined,\n values: values,\n },\n };\n}\n\nfunction zipValueDescriptions(values: Array, descriptions: Array) {\n const descriptionsMap: Record = {};\n values.forEach((value, index) => {\n const description = descriptions[index];\n if (description) {\n descriptionsMap[value] = description;\n }\n });\n return descriptionsMap;\n}\n"]} \ No newline at end of file diff --git a/lib/package.json b/lib/package.json index 0e9eeb5..6644474 100644 --- a/lib/package.json +++ b/lib/package.json @@ -11,7 +11,7 @@ ".": "./lib/index.js" }, "scripts": { - "lint": "eslint --ignore-path .gitignore --ignore-path .eslintignore --ext js,ts,tsx .", + "lint": "eslint .", "prebuild": "rimraf lib", "build": "tsc -p tsconfig.json && tsc -p tsconfig.test.json", "postbuild": "cp package.json README.md NOTICE LICENSE lib", @@ -23,19 +23,20 @@ "@types/node": "^20.0.0", "@types/react": "^16.14.8", "@types/react-dom": "^16.9.8", - "@typescript-eslint/eslint-plugin": "^4.28.5", - "@typescript-eslint/parser": "^4.28.5", "@vitest/coverage-v8": "^3.1.3", - "eslint": "^7.31.0", - "eslint-config-prettier": "^8.3.0", + "eslint": "^9.20.1", + "@eslint/compat": "^1.2.9", + "eslint-config-prettier": "^10.1.5", "eslint-plugin-header": "^3.1.1", - "eslint-plugin-prettier": "^3.4.0", - "eslint-plugin-unicorn": "^34.0.1", + "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-react": "^7.31.11", + "eslint-plugin-unicorn": "^60.0.0", "husky": "^9.0.11", "lint-staged": "^13.2.1", - "prettier": "^2.3.2", + "prettier": "^3.6.1", "rimraf": "^5.0.5", "typescript": "^5.9.2", + "typescript-eslint": "^8.44.0", "vitest": "^3.1.3" }, "dependencies": { diff --git a/lib/shared/type-utils.js b/lib/shared/type-utils.js index a6ce286..d2ac21b 100644 --- a/lib/shared/type-utils.js +++ b/lib/shared/type-utils.js @@ -72,9 +72,9 @@ function extractDeclaration(symbol) { } function printFlags(flags, mapping) { return Object.entries(mapping) - .filter(([key, value]) => typeof value === 'number') - .filter(([key, value]) => value & flags) - .map(([key, value]) => key); + .filter(([, value]) => typeof value === 'number') + .filter(([, value]) => value & flags) + .map(([key]) => key); } function extractTypeArguments(type, checker) { const typeParameters = checker.getTypeArguments(type); diff --git a/lib/shared/type-utils.js.map b/lib/shared/type-utils.js.map index acd45ed..e53d224 100644 --- a/lib/shared/type-utils.js.map +++ b/lib/shared/type-utils.js.map @@ -1 +1 @@ -{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/shared/type-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nexport function isOptional(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Undefined);\n}\n\nexport function isNullable(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Null);\n}\n\nexport function unwrapNamespaceDeclaration(declaration: ts.Declaration | undefined) {\n if (!declaration) {\n return [];\n }\n const namespaceBlock = declaration.getChildren().find(node => node.kind === ts.SyntaxKind.ModuleBlock);\n if (!namespaceBlock) {\n return [];\n }\n const moduleContent = namespaceBlock.getChildren().find(node => node.kind === ts.SyntaxKind.SyntaxList);\n if (!moduleContent) {\n return [];\n }\n return moduleContent.getChildren();\n}\n\nfunction stripUndefined(typeString: string) {\n return typeString.replace(/\\| undefined$/, '').trim();\n}\n\nexport function stringifyType(type: ts.Type, checker: ts.TypeChecker) {\n return stripUndefined(\n checker.typeToString(\n type,\n undefined,\n ts.TypeFormatFlags.WriteArrayAsGenericType |\n ts.TypeFormatFlags.UseFullyQualifiedType |\n ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope\n )\n );\n}\n\nfunction expandTags(extraTags: ReadonlyArray) {\n return extraTags.map(tag => ({\n name: tag.tagName.text,\n text: ts.getTextOfJSDocComment(tag.comment),\n }));\n}\n\nexport function getDescription(docComment: Array, declaration: ts.Node) {\n return {\n text: docComment.length > 0 ? ts.displayPartsToString(docComment) : undefined,\n tags: expandTags(ts.getJSDocTags(declaration)),\n };\n}\n\nexport function extractDeclaration(symbol: ts.Symbol) {\n const declarations = symbol.getDeclarations();\n if (!declarations || declarations.length === 0) {\n throw new Error(`No declaration found for symbol: ${symbol.getName()}`);\n }\n if (declarations.length > 1) {\n throw new Error(`Multiple declarations found for symbol: ${symbol.getName()}`);\n }\n return declarations[0];\n}\n\nexport function printFlags(flags: number, mapping: Record) {\n return Object.entries(mapping)\n .filter(([key, value]) => typeof value === 'number')\n .filter(([key, value]) => (value as number) & flags)\n .map(([key, value]) => key);\n}\n\nexport function extractTypeArguments(type: ts.Type, checker: ts.TypeChecker) {\n const typeParameters = checker.getTypeArguments(type as ts.TypeReference);\n\n if (typeParameters.length <= 0) {\n return { typeName: stringifyType(type, checker) };\n }\n const symbol = type.getSymbol();\n if (!symbol) {\n throw new Error(`Unknown generic type without symbol: ${stringifyType(type, checker)}`);\n }\n return { typeParameters, typeName: checker.symbolToString(symbol) };\n}\n"]} \ No newline at end of file +{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/shared/type-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nexport function isOptional(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Undefined);\n}\n\nexport function isNullable(type: ts.Type) {\n if (!type.isUnionOrIntersection()) {\n return false;\n }\n return !!type.types.find(t => t.flags & ts.TypeFlags.Null);\n}\n\nexport function unwrapNamespaceDeclaration(declaration: ts.Declaration | undefined) {\n if (!declaration) {\n return [];\n }\n const namespaceBlock = declaration.getChildren().find(node => node.kind === ts.SyntaxKind.ModuleBlock);\n if (!namespaceBlock) {\n return [];\n }\n const moduleContent = namespaceBlock.getChildren().find(node => node.kind === ts.SyntaxKind.SyntaxList);\n if (!moduleContent) {\n return [];\n }\n return moduleContent.getChildren();\n}\n\nfunction stripUndefined(typeString: string) {\n return typeString.replace(/\\| undefined$/, '').trim();\n}\n\nexport function stringifyType(type: ts.Type, checker: ts.TypeChecker) {\n return stripUndefined(\n checker.typeToString(\n type,\n undefined,\n ts.TypeFormatFlags.WriteArrayAsGenericType |\n ts.TypeFormatFlags.UseFullyQualifiedType |\n ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope,\n ),\n );\n}\n\nfunction expandTags(extraTags: ReadonlyArray) {\n return extraTags.map(tag => ({\n name: tag.tagName.text,\n text: ts.getTextOfJSDocComment(tag.comment),\n }));\n}\n\nexport function getDescription(docComment: Array, declaration: ts.Node) {\n return {\n text: docComment.length > 0 ? ts.displayPartsToString(docComment) : undefined,\n tags: expandTags(ts.getJSDocTags(declaration)),\n };\n}\n\nexport function extractDeclaration(symbol: ts.Symbol) {\n const declarations = symbol.getDeclarations();\n if (!declarations || declarations.length === 0) {\n throw new Error(`No declaration found for symbol: ${symbol.getName()}`);\n }\n if (declarations.length > 1) {\n throw new Error(`Multiple declarations found for symbol: ${symbol.getName()}`);\n }\n return declarations[0];\n}\n\nexport function printFlags(flags: number, mapping: Record) {\n return Object.entries(mapping)\n .filter(([, value]) => typeof value === 'number')\n .filter(([, value]) => (value as number) & flags)\n .map(([key]) => key);\n}\n\nexport function extractTypeArguments(type: ts.Type, checker: ts.TypeChecker) {\n const typeParameters = checker.getTypeArguments(type as ts.TypeReference);\n\n if (typeParameters.length <= 0) {\n return { typeName: stringifyType(type, checker) };\n }\n const symbol = type.getSymbol();\n if (!symbol) {\n throw new Error(`Unknown generic type without symbol: ${stringifyType(type, checker)}`);\n }\n return { typeParameters, typeName: checker.symbolToString(symbol) };\n}\n"]} \ No newline at end of file diff --git a/lib/test-utils/extractor.js.map b/lib/test-utils/extractor.js.map index d7cd2ec..25a434a 100644 --- a/lib/test-utils/extractor.js.map +++ b/lib/test-utils/extractor.js.map @@ -1 +1 @@ -{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/test-utils/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport {\n extractDeclaration,\n extractTypeArguments,\n getDescription,\n isNullable,\n isOptional,\n stringifyType,\n} from '../shared/type-utils';\nimport { TestUtilsDoc } from './interfaces';\n\nfunction getInheritedFrom(declaration: ts.Declaration, currentClassName: string) {\n if (!ts.isMethodDeclaration(declaration) || !ts.isClassDeclaration(declaration.parent) || !declaration.parent.name) {\n throw new Error(`Unexpected declaration parent: ${declaration.getText()}`);\n }\n const parentName = declaration.parent.name.getText();\n if (parentName === currentClassName) {\n return undefined;\n }\n return { className: parentName, methodName: declaration.name.getText() };\n}\n\nfunction getDefaultValue(declaration: ts.Declaration) {\n if (!ts.isParameter(declaration)) {\n throw new Error(`Unexpected declaration: ${declaration.getText()}`);\n }\n if (!declaration.initializer) {\n return undefined;\n }\n return declaration.initializer.getText();\n}\n\nexport default function extractDocumentation(\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n extraExports: Array,\n includeCoreMethods: boolean\n): Array {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const definitions = new Map();\n\n for (const symbol of exportSymbols) {\n const className = symbol.getName();\n if (extraExports.includes(className)) {\n continue;\n }\n const classType = checker.getDeclaredTypeOfSymbol(symbol);\n documentClass(definitions, symbol, classType, checker, includeCoreMethods);\n }\n\n return Array.from(definitions.values());\n}\n\nfunction documentClass(\n definitions: Map,\n symbol: ts.Symbol,\n classType: ts.Type,\n checker: ts.TypeChecker,\n includeCoreMethods: boolean\n) {\n if (!classType.isClass()) {\n throw new Error(`Exported symbol is not a class, got ${checker.symbolToString(symbol)}`);\n }\n const className = checker.symbolToString(symbol);\n const definition: TestUtilsDoc = { name: className, methods: [] };\n definitions.set(className, definition);\n\n for (const property of classType.getProperties()) {\n const declaration = property.valueDeclaration;\n if (!declaration) {\n throw new Error(`Unexpected member on ${className} – ${property.getName()}`);\n }\n const modifiers = (ts.canHaveModifiers(declaration) && ts.getModifiers(declaration)) || [];\n if (\n modifiers.find(\n modifier => modifier.kind === ts.SyntaxKind.ProtectedKeyword || modifier.kind === ts.SyntaxKind.PrivateKeyword\n )\n ) {\n continue;\n }\n const type = checker.getTypeAtLocation(declaration);\n // report each function signature as a separate method\n for (const signature of type.getCallSignatures()) {\n const maybeReturnType = signature.getReturnType();\n // non-nullable type of `void` is `never`\n const returnType =\n maybeReturnType.flags & ts.TypeFlags.Void ? maybeReturnType : maybeReturnType.getNonNullableType();\n const dependency = findDependencyType(returnType, checker);\n if (dependency && !definitions.has(dependency.typeName)) {\n documentClass(definitions, dependency.symbol, dependency.type, checker, includeCoreMethods);\n }\n\n const { typeName, typeParameters } = extractTypeArguments(returnType, checker);\n\n const inheritedFrom = getInheritedFrom(declaration, className);\n if (\n inheritedFrom &&\n !includeCoreMethods &&\n ['AbstractWrapper', 'ElementWrapper'].includes(inheritedFrom?.className)\n ) {\n continue;\n }\n\n definition.methods.push({\n name: property.getName(),\n description: getDescription(property.getDocumentationComment(checker), declaration).text,\n returnType: {\n name: typeName,\n isNullable: isNullable(maybeReturnType),\n typeArguments: typeParameters?.map(typeArgument => ({\n name: stringifyType(typeArgument, checker),\n })),\n },\n parameters: signature.parameters.map(parameter => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(parameter));\n return {\n name: parameter.name,\n typeName: stringifyType(paramType, checker),\n description: getDescription(parameter.getDocumentationComment(checker), declaration).text,\n flags: { isOptional: isOptional(paramType) },\n defaultValue: getDefaultValue(extractDeclaration(parameter)),\n };\n }),\n inheritedFrom: inheritedFrom ? { name: `${inheritedFrom.className}.${inheritedFrom.methodName}` } : undefined,\n });\n }\n }\n definition.methods.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction findDependencyType(\n type: ts.Type,\n checker: ts.TypeChecker\n): { typeName: string; type: ts.Type; symbol: ts.Symbol } | undefined {\n const symbol = type.getSymbol();\n if (!symbol) {\n return;\n }\n\n const typeName = checker.symbolToString(symbol);\n if (typeName === 'Array' || typeName === 'MultiElementWrapper') {\n const itemType = checker.getTypeArguments(type as ts.TypeReference)[0];\n return findDependencyType(itemType, checker);\n }\n if (\n !typeName.endsWith('Wrapper') ||\n ['ElementWrapper', 'ComponentWrapper'].includes(typeName) ||\n !type.isClassOrInterface()\n ) {\n return;\n }\n\n return {\n typeName,\n type,\n symbol,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/test-utils/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\nimport {\n extractDeclaration,\n extractTypeArguments,\n getDescription,\n isNullable,\n isOptional,\n stringifyType,\n} from '../shared/type-utils';\nimport { TestUtilsDoc } from './interfaces';\n\nfunction getInheritedFrom(declaration: ts.Declaration, currentClassName: string) {\n if (!ts.isMethodDeclaration(declaration) || !ts.isClassDeclaration(declaration.parent) || !declaration.parent.name) {\n throw new Error(`Unexpected declaration parent: ${declaration.getText()}`);\n }\n const parentName = declaration.parent.name.getText();\n if (parentName === currentClassName) {\n return undefined;\n }\n return { className: parentName, methodName: declaration.name.getText() };\n}\n\nfunction getDefaultValue(declaration: ts.Declaration) {\n if (!ts.isParameter(declaration)) {\n throw new Error(`Unexpected declaration: ${declaration.getText()}`);\n }\n if (!declaration.initializer) {\n return undefined;\n }\n return declaration.initializer.getText();\n}\n\nexport default function extractDocumentation(\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n extraExports: Array,\n includeCoreMethods: boolean,\n): Array {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) {\n throw new Error(`Unable to resolve module: ${sourceFile.fileName}`);\n }\n\n const exportSymbols = checker.getExportsOfModule(moduleSymbol);\n const definitions = new Map();\n\n for (const symbol of exportSymbols) {\n const className = symbol.getName();\n if (extraExports.includes(className)) {\n continue;\n }\n const classType = checker.getDeclaredTypeOfSymbol(symbol);\n documentClass(definitions, symbol, classType, checker, includeCoreMethods);\n }\n\n return Array.from(definitions.values());\n}\n\nfunction documentClass(\n definitions: Map,\n symbol: ts.Symbol,\n classType: ts.Type,\n checker: ts.TypeChecker,\n includeCoreMethods: boolean,\n) {\n if (!classType.isClass()) {\n throw new Error(`Exported symbol is not a class, got ${checker.symbolToString(symbol)}`);\n }\n const className = checker.symbolToString(symbol);\n const definition: TestUtilsDoc = { name: className, methods: [] };\n definitions.set(className, definition);\n\n for (const property of classType.getProperties()) {\n const declaration = property.valueDeclaration;\n if (!declaration) {\n throw new Error(`Unexpected member on ${className} – ${property.getName()}`);\n }\n const modifiers = (ts.canHaveModifiers(declaration) && ts.getModifiers(declaration)) || [];\n if (\n modifiers.find(\n modifier => modifier.kind === ts.SyntaxKind.ProtectedKeyword || modifier.kind === ts.SyntaxKind.PrivateKeyword,\n )\n ) {\n continue;\n }\n const type = checker.getTypeAtLocation(declaration);\n // report each function signature as a separate method\n for (const signature of type.getCallSignatures()) {\n const maybeReturnType = signature.getReturnType();\n // non-nullable type of `void` is `never`\n const returnType =\n maybeReturnType.flags & ts.TypeFlags.Void ? maybeReturnType : maybeReturnType.getNonNullableType();\n const dependency = findDependencyType(returnType, checker);\n if (dependency && !definitions.has(dependency.typeName)) {\n documentClass(definitions, dependency.symbol, dependency.type, checker, includeCoreMethods);\n }\n\n const { typeName, typeParameters } = extractTypeArguments(returnType, checker);\n\n const inheritedFrom = getInheritedFrom(declaration, className);\n if (\n inheritedFrom &&\n !includeCoreMethods &&\n ['AbstractWrapper', 'ElementWrapper'].includes(inheritedFrom?.className)\n ) {\n continue;\n }\n\n definition.methods.push({\n name: property.getName(),\n description: getDescription(property.getDocumentationComment(checker), declaration).text,\n returnType: {\n name: typeName,\n isNullable: isNullable(maybeReturnType),\n typeArguments: typeParameters?.map(typeArgument => ({\n name: stringifyType(typeArgument, checker),\n })),\n },\n parameters: signature.parameters.map(parameter => {\n const paramType = checker.getTypeAtLocation(extractDeclaration(parameter));\n return {\n name: parameter.name,\n typeName: stringifyType(paramType, checker),\n description: getDescription(parameter.getDocumentationComment(checker), declaration).text,\n flags: { isOptional: isOptional(paramType) },\n defaultValue: getDefaultValue(extractDeclaration(parameter)),\n };\n }),\n inheritedFrom: inheritedFrom ? { name: `${inheritedFrom.className}.${inheritedFrom.methodName}` } : undefined,\n });\n }\n }\n definition.methods.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction findDependencyType(\n type: ts.Type,\n checker: ts.TypeChecker,\n): { typeName: string; type: ts.Type; symbol: ts.Symbol } | undefined {\n const symbol = type.getSymbol();\n if (!symbol) {\n return;\n }\n\n const typeName = checker.symbolToString(symbol);\n if (typeName === 'Array' || typeName === 'MultiElementWrapper') {\n const itemType = checker.getTypeArguments(type as ts.TypeReference)[0];\n return findDependencyType(itemType, checker);\n }\n if (\n !typeName.endsWith('Wrapper') ||\n ['ElementWrapper', 'ComponentWrapper'].includes(typeName) ||\n !type.isClassOrInterface()\n ) {\n return;\n }\n\n return {\n typeName,\n type,\n symbol,\n };\n}\n"]} \ No newline at end of file diff --git a/lib/test-utils/index.js.map b/lib/test-utils/index.js.map index 35284f0..25b1e80 100644 --- a/lib/test-utils/index.js.map +++ b/lib/test-utils/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test-utils/index.ts"],"names":[],"mappings":";;;;;AAyBA,8CA8BC;AAED,kEAqBC;AA9ED,qEAAqE;AACrE,sCAAsC;AACtC,sDAAyB;AACzB,kDAA0B;AAC1B,mDAAiE;AACjE,4DAA+C;AAoB/C,SAAgB,iBAAiB,CAAC,OAAmC;;IACnE,MAAM,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,IAAA,sCAA0B,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;IAC3F,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,SAAS,YAAY,aAAa,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,kBAAkB,CAAC,CAAC;IACvG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,SAAS,kBAAkB,aAAa,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,kBAAkB,GAAG,MAAA,OAAO,CAAC,kBAAkB,mCAAI,KAAK,CAAC;IAC/D,OAAO;QACL,cAAc,EAAE,IAAA,mBAAoB,EAClC,YAAY,EACZ,OAAO,EACP,MAAA,OAAO,CAAC,QAAQ,CAAC,YAAY,mCAAI,EAAE,EACnC,kBAAkB,CACnB;QACD,oBAAoB,EAAE,IAAA,mBAAoB,EACxC,kBAAkB,EAClB,OAAO,EACP,MAAA,OAAO,CAAC,cAAc,CAAC,YAAY,mCAAI,EAAE,EACzC,kBAAkB,CACnB;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,GAAG,IAAI,EACyC;IAChD,MAAM,EAAE,cAAc,EAAE,oBAAoB,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzE,iBAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,+BAA+B,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAC5E,CAAC;IACF,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,+BAA+B,IAAI,CAAC,SAAS,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAClF,CAAC;IACF,iBAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7F,MAAM,WAAW,GAAG;;;GAGnB,CAAC;IACF,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9D,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAAC;AACtE,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport pathe from 'pathe';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport extractDocumentation from './extractor';\nimport { TestUtilsDoc } from './interfaces';\n\nexport interface TestUtilsVariantOptions {\n root: string;\n extraExports?: Array;\n}\n\nexport interface TestUtilsDocumenterOptions {\n tsconfigPath: string;\n includeCoreMethods?: boolean;\n domUtils: TestUtilsVariantOptions;\n selectorsUtils: TestUtilsVariantOptions;\n}\n\ninterface TestUtilsDefinitions {\n domDefinitions: Array;\n selectorsDefinitions: Array;\n}\n\nexport function documentTestUtils(options: TestUtilsDocumenterOptions): TestUtilsDefinitions {\n const domUtilsRoot = pathe.resolve(options.domUtils.root);\n const selectorsUtilsRoot = pathe.resolve(options.selectorsUtils.root);\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const domUtilsFile = program.getSourceFiles().find(file => file.fileName === domUtilsRoot);\n if (!domUtilsFile) {\n throw new Error(`File '${domUtilsRoot}' not found`);\n }\n\n const selectorsUtilsFile = program.getSourceFiles().find(file => file.fileName === selectorsUtilsRoot);\n if (!selectorsUtilsFile) {\n throw new Error(`File '${selectorsUtilsFile}' not found`);\n }\n const includeCoreMethods = options.includeCoreMethods ?? false;\n return {\n domDefinitions: extractDocumentation(\n domUtilsFile,\n checker,\n options.domUtils.extraExports ?? [],\n includeCoreMethods\n ),\n selectorsDefinitions: extractDocumentation(\n selectorsUtilsFile,\n checker,\n options.selectorsUtils.extraExports ?? [],\n includeCoreMethods\n ),\n };\n}\n\nexport function writeTestUtilsDocumentation({\n outDir,\n ...rest\n}: TestUtilsDocumenterOptions & { outDir: string }): void {\n const { domDefinitions, selectorsDefinitions } = documentTestUtils(rest);\n fs.mkdirSync(outDir, { recursive: true });\n fs.writeFileSync(\n pathe.join(outDir, 'dom.js'),\n `module.exports = { classes: ${JSON.stringify(domDefinitions, null, 2)} };`\n );\n fs.writeFileSync(\n pathe.join(outDir, 'selectors.js'),\n `module.exports = { classes: ${JSON.stringify(selectorsDefinitions, null, 2)} };`\n );\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n const dtsTemplate = `import { TestUtilsDefinition } from './interfaces';\n declare const definitions: TestUtilsDefinition;\n export = definitions;\n `;\n fs.writeFileSync(pathe.join(outDir, 'dom.d.ts'), dtsTemplate);\n fs.writeFileSync(pathe.join(outDir, 'selectors.d.ts'), dtsTemplate);\n}\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test-utils/index.ts"],"names":[],"mappings":";;;;;AAyBA,8CA8BC;AAED,kEAqBC;AA9ED,qEAAqE;AACrE,sCAAsC;AACtC,sDAAyB;AACzB,kDAA0B;AAC1B,mDAAiE;AACjE,4DAA+C;AAoB/C,SAAgB,iBAAiB,CAAC,OAAmC;;IACnE,MAAM,YAAY,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,IAAA,sCAA0B,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;IAC3F,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,SAAS,YAAY,aAAa,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,kBAAkB,CAAC,CAAC;IACvG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,SAAS,kBAAkB,aAAa,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,kBAAkB,GAAG,MAAA,OAAO,CAAC,kBAAkB,mCAAI,KAAK,CAAC;IAC/D,OAAO;QACL,cAAc,EAAE,IAAA,mBAAoB,EAClC,YAAY,EACZ,OAAO,EACP,MAAA,OAAO,CAAC,QAAQ,CAAC,YAAY,mCAAI,EAAE,EACnC,kBAAkB,CACnB;QACD,oBAAoB,EAAE,IAAA,mBAAoB,EACxC,kBAAkB,EAClB,OAAO,EACP,MAAA,OAAO,CAAC,cAAc,CAAC,YAAY,mCAAI,EAAE,EACzC,kBAAkB,CACnB;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,GAAG,IAAI,EACyC;IAChD,MAAM,EAAE,cAAc,EAAE,oBAAoB,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzE,iBAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,+BAA+B,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAC5E,CAAC;IACF,iBAAE,CAAC,aAAa,CACd,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,+BAA+B,IAAI,CAAC,SAAS,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAClF,CAAC;IACF,iBAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7F,MAAM,WAAW,GAAG;;;GAGnB,CAAC;IACF,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9D,iBAAE,CAAC,aAAa,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAAC;AACtE,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport fs from 'node:fs';\nimport pathe from 'pathe';\nimport { bootstrapTypescriptProject } from '../shared/bootstrap';\nimport extractDocumentation from './extractor';\nimport { TestUtilsDoc } from './interfaces';\n\nexport interface TestUtilsVariantOptions {\n root: string;\n extraExports?: Array;\n}\n\nexport interface TestUtilsDocumenterOptions {\n tsconfigPath: string;\n includeCoreMethods?: boolean;\n domUtils: TestUtilsVariantOptions;\n selectorsUtils: TestUtilsVariantOptions;\n}\n\ninterface TestUtilsDefinitions {\n domDefinitions: Array;\n selectorsDefinitions: Array;\n}\n\nexport function documentTestUtils(options: TestUtilsDocumenterOptions): TestUtilsDefinitions {\n const domUtilsRoot = pathe.resolve(options.domUtils.root);\n const selectorsUtilsRoot = pathe.resolve(options.selectorsUtils.root);\n const program = bootstrapTypescriptProject(options.tsconfigPath);\n const checker = program.getTypeChecker();\n\n const domUtilsFile = program.getSourceFiles().find(file => file.fileName === domUtilsRoot);\n if (!domUtilsFile) {\n throw new Error(`File '${domUtilsRoot}' not found`);\n }\n\n const selectorsUtilsFile = program.getSourceFiles().find(file => file.fileName === selectorsUtilsRoot);\n if (!selectorsUtilsFile) {\n throw new Error(`File '${selectorsUtilsFile}' not found`);\n }\n const includeCoreMethods = options.includeCoreMethods ?? false;\n return {\n domDefinitions: extractDocumentation(\n domUtilsFile,\n checker,\n options.domUtils.extraExports ?? [],\n includeCoreMethods,\n ),\n selectorsDefinitions: extractDocumentation(\n selectorsUtilsFile,\n checker,\n options.selectorsUtils.extraExports ?? [],\n includeCoreMethods,\n ),\n };\n}\n\nexport function writeTestUtilsDocumentation({\n outDir,\n ...rest\n}: TestUtilsDocumenterOptions & { outDir: string }): void {\n const { domDefinitions, selectorsDefinitions } = documentTestUtils(rest);\n fs.mkdirSync(outDir, { recursive: true });\n fs.writeFileSync(\n pathe.join(outDir, 'dom.js'),\n `module.exports = { classes: ${JSON.stringify(domDefinitions, null, 2)} };`,\n );\n fs.writeFileSync(\n pathe.join(outDir, 'selectors.js'),\n `module.exports = { classes: ${JSON.stringify(selectorsDefinitions, null, 2)} };`,\n );\n fs.copyFileSync(require.resolve('./interfaces.d.ts'), pathe.join(outDir, 'interfaces.d.ts'));\n const dtsTemplate = `import { TestUtilsDefinition } from './interfaces';\n declare const definitions: TestUtilsDefinition;\n export = definitions;\n `;\n fs.writeFileSync(pathe.join(outDir, 'dom.d.ts'), dtsTemplate);\n fs.writeFileSync(pathe.join(outDir, 'selectors.d.ts'), dtsTemplate);\n}\n"]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 560f9a6..d60c388 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1154,6 +1154,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 6" } @@ -1194,7 +1195,6 @@ "integrity": "sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -1212,7 +1212,6 @@ "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "^0.16", @@ -1282,7 +1281,6 @@ "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/types": "8.46.4", @@ -1692,7 +1690,8 @@ "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true, "license": "BSD-3-Clause", - "optional": true + "optional": true, + "peer": true }, "node_modules/acorn": { "version": "7.4.1", @@ -1715,6 +1714,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "acorn": "^7.1.1", "acorn-walk": "^7.1.1" @@ -1737,6 +1737,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.4.0" } @@ -1748,6 +1749,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "debug": "4" }, @@ -1968,7 +1970,8 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/available-typed-arrays": { "version": "1.0.7", @@ -2032,7 +2035,8 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true, "license": "BSD-2-Clause", - "optional": true + "optional": true, + "peer": true }, "node_modules/browserslist": { "version": "4.28.0", @@ -2054,7 +2058,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -2361,6 +2364,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2431,7 +2435,8 @@ "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/cssstyle": { "version": "2.3.0", @@ -2440,6 +2445,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "cssom": "~0.3.6" }, @@ -2453,7 +2459,8 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/csstype": { "version": "3.1.3", @@ -2469,6 +2476,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "abab": "^2.0.3", "whatwg-mimetype": "^2.3.0", @@ -2556,7 +2564,8 @@ "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/deep-eql": { "version": "5.0.2", @@ -2617,6 +2626,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.4.0" } @@ -2642,6 +2652,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "webidl-conversions": "^5.0.0" }, @@ -2656,6 +2667,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -2959,6 +2971,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -2981,7 +2994,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3042,7 +3054,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -3301,6 +3312,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3565,6 +3577,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3932,6 +3945,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "whatwg-encoding": "^1.0.5" }, @@ -3953,6 +3967,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -3969,6 +3984,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -4000,6 +4016,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -4353,7 +4370,8 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/is-regex": { "version": "1.2.1", @@ -4614,6 +4632,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "abab": "^2.0.5", "acorn": "^8.2.4", @@ -4662,6 +4681,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4999,7 +5019,8 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -5199,6 +5220,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -5210,6 +5232,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -5305,7 +5328,8 @@ "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/object-assign": { "version": "4.1.1", @@ -5535,7 +5559,8 @@ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/pascal-case": { "version": "3.1.2", @@ -5719,7 +5744,6 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -5762,6 +5786,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "punycode": "^2.3.1" }, @@ -5785,7 +5810,8 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -5901,7 +5927,8 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/resolve": { "version": "2.0.0-next.5", @@ -6106,7 +6133,8 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/saxes": { "version": "5.0.1", @@ -6115,6 +6143,7 @@ "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -6355,6 +6384,7 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6670,7 +6700,8 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/synckit": { "version": "0.11.11", @@ -6737,7 +6768,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -6793,6 +6823,7 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, + "peer": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -6810,6 +6841,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "punycode": "^2.1.1" }, @@ -6933,7 +6965,6 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6999,6 +7030,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -7069,6 +7101,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -7121,7 +7154,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -7204,12 +7236,29 @@ } } }, + "node_modules/vite-node/node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/vitest": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz", "integrity": "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==", "dev": true, - "peer": true, "dependencies": { "@vitest/expect": "3.1.3", "@vitest/mocker": "3.1.3", @@ -7327,7 +7376,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -7341,7 +7389,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -7411,6 +7458,24 @@ } } }, + "node_modules/vitest/node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -7419,6 +7484,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "browser-process-hrtime": "^1.0.0" } @@ -7430,6 +7496,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "xml-name-validator": "^3.0.0" }, @@ -7444,6 +7511,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "engines": { "node": ">=10.4" } @@ -7455,6 +7523,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "0.4.24" } @@ -7465,7 +7534,8 @@ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/whatwg-url": { "version": "8.7.0", @@ -7474,6 +7544,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "lodash": "^4.7.0", "tr46": "^2.1.0", @@ -7733,6 +7804,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=8.3.0" }, @@ -7755,7 +7827,8 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true, "license": "Apache-2.0", - "optional": true + "optional": true, + "peer": true }, "node_modules/xmlchars": { "version": "2.2.0", @@ -7763,7 +7836,8 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/yaml": { "version": "2.3.1", From d45f66a67a5bfc810b186fd20ae4751accebdf3e Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 15:30:18 +0100 Subject: [PATCH 6/7] support named exports --- src/components/extractor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/extractor.ts b/src/components/extractor.ts index 45671c2..a0ec9ba 100644 --- a/src/components/extractor.ts +++ b/src/components/extractor.ts @@ -146,7 +146,7 @@ export function extractExports( let propsSymbol; const unknownExports: Array = []; for (const exportSymbol of exportSymbols) { - if (exportSymbol.name === 'default') { + if (exportSymbol.name === 'default' || exportSymbol.name === componentName) { validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker); componentSymbol = exportSymbol; } else if (exportSymbol.name === `${componentName}Props`) { From 5bcae9a1f0b0b2397f30889113ad010980f43270 Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 5 Jan 2026 15:30:42 +0100 Subject: [PATCH 7/7] update assets --- lib/components/extractor.js | 2 +- lib/components/extractor.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/components/extractor.js b/lib/components/extractor.js index eb81ab7..7be8e49 100644 --- a/lib/components/extractor.js +++ b/lib/components/extractor.js @@ -117,7 +117,7 @@ function extractExports(componentName, exportSymbols, checker, extraExports) { let propsSymbol; const unknownExports = []; for (const exportSymbol of exportSymbols) { - if (exportSymbol.name === 'default') { + if (exportSymbol.name === 'default' || exportSymbol.name === componentName) { validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker); componentSymbol = exportSymbol; } diff --git a/lib/components/extractor.js.map b/lib/components/extractor.js.map index c81f649..9c8bcb4 100644 --- a/lib/components/extractor.js.map +++ b/lib/components/extractor.js.map @@ -1 +1 @@ -{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/components/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport {\n extractDeclaration,\n getDescription,\n isOptional,\n stringifyType,\n unwrapNamespaceDeclaration,\n} from '../shared/type-utils';\n\nexport interface ExtractedDescription {\n text: string | undefined;\n tags: Array<{ name: string; text: string | undefined }>;\n}\n\nexport interface ExpandedProp {\n name: string;\n type: string;\n isOptional: boolean;\n rawType: ts.Type;\n rawTypeNode: ts.TypeNode | undefined;\n description: ExtractedDescription;\n}\n\nexport function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker) {\n let declaration: ts.Node = extractDeclaration(exportSymbol);\n if (ts.isExportAssignment(declaration)) {\n // Traverse from \"export default Something;\" to the actual \"Something\"\n const symbol = checker.getSymbolAtLocation(declaration.expression);\n if (!symbol) {\n throw new Error('Cannot resolve symbol');\n }\n declaration = extractDeclaration(symbol);\n }\n // Extract \"Something\" from \"const Component = Something\"\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n declaration = declaration.initializer;\n }\n // Extract \"Something\" from \"Something as MyComponentType\"\n if (ts.isAsExpression(declaration)) {\n declaration = declaration.expression;\n }\n // Extract \"Something from React.forwardRef(Something)\"\n if (\n ts.isCallExpression(declaration) &&\n (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')\n ) {\n declaration = declaration.arguments[0];\n }\n\n // In the component function, find arguments destructuring\n let argument: ts.Node | undefined;\n if (\n ts.isFunctionDeclaration(declaration) ||\n ts.isFunctionExpression(declaration) ||\n ts.isArrowFunction(declaration)\n ) {\n if (declaration.parameters.length === 0) {\n return {};\n }\n argument = declaration.parameters[0].name;\n }\n if (!argument) {\n throw new Error(`Unsupported component declaration type ${ts.SyntaxKind[declaration.kind]}`);\n }\n if (!ts.isObjectBindingPattern(argument)) {\n // if a component does not use props de-structuring, we do not detect default values\n return {};\n }\n const values: Record = {};\n for (const element of argument.elements) {\n if (ts.isIdentifier(element.name) && element.initializer) {\n values[element.name.escapedText as string] = element.initializer.getText();\n }\n }\n return values;\n}\n\nexport function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol);\n\n return exportType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n return {\n name: value.name,\n type: stringifyType(type, checker),\n rawType: type,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const propsName = propsSymbol.getName();\n const namespaceDeclaration = [\n // if we got the namespace directly\n ...(propsSymbol.getDeclarations() ?? []),\n // find namespace declaration from the interface with the same name\n ...(checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()?.getDeclarations() ?? []),\n ].find(decl => decl.kind === ts.SyntaxKind.ModuleDeclaration);\n const refType = unwrapNamespaceDeclaration(namespaceDeclaration)\n .map(child => checker.getTypeAtLocation(child))\n .find(type => (type.getSymbol() ?? type.aliasSymbol)?.getName() === 'Ref');\n\n if (!refType) {\n return [];\n }\n return refType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n const realType = type.getNonNullableType();\n if (realType.getCallSignatures().length === 0) {\n throw new Error(\n `${propsName}.Ref should contain only methods, \"${value.name}\" has a \"${stringifyType(type, checker)}\" type`,\n );\n }\n return {\n name: value.name,\n type: stringifyType(realType, checker),\n rawType: realType,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractExports(\n componentName: string,\n exportSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n extraExports: Record> | false,\n) {\n let componentSymbol;\n let propsSymbol;\n const unknownExports: Array = [];\n for (const exportSymbol of exportSymbols) {\n if (exportSymbol.name === 'default') {\n validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker);\n componentSymbol = exportSymbol;\n } else if (exportSymbol.name === `${componentName}Props`) {\n propsSymbol = exportSymbol;\n } else if (\n extraExports !== false &&\n (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name))\n ) {\n unknownExports.push(exportSymbol.name);\n }\n }\n if (unknownExports.length > 0) {\n throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`);\n }\n if (!componentSymbol) {\n throw new Error(`Missing default export for ${componentName}`);\n }\n if (!propsSymbol) {\n throw new Error(`Missing ${componentName}Props export`);\n }\n return { componentSymbol, propsSymbol };\n}\n\nfunction validateComponentType(type: ts.Type, checker: ts.TypeChecker) {\n if (\n // React.forwardRef\n type.getSymbol()?.name !== 'ForwardRefExoticComponent' &&\n // Plain function returning JSX\n type.getCallSignatures().some(signature => {\n const returnTypeName = checker.typeToString(signature.getReturnType());\n return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal';\n })\n ) {\n throw new Error(`Unknown default export type ${checker.typeToString(type)}`);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/components/extractor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport ts from 'typescript';\n\nimport {\n extractDeclaration,\n getDescription,\n isOptional,\n stringifyType,\n unwrapNamespaceDeclaration,\n} from '../shared/type-utils';\n\nexport interface ExtractedDescription {\n text: string | undefined;\n tags: Array<{ name: string; text: string | undefined }>;\n}\n\nexport interface ExpandedProp {\n name: string;\n type: string;\n isOptional: boolean;\n rawType: ts.Type;\n rawTypeNode: ts.TypeNode | undefined;\n description: ExtractedDescription;\n}\n\nexport function extractDefaultValues(exportSymbol: ts.Symbol, checker: ts.TypeChecker) {\n let declaration: ts.Node = extractDeclaration(exportSymbol);\n if (ts.isExportAssignment(declaration)) {\n // Traverse from \"export default Something;\" to the actual \"Something\"\n const symbol = checker.getSymbolAtLocation(declaration.expression);\n if (!symbol) {\n throw new Error('Cannot resolve symbol');\n }\n declaration = extractDeclaration(symbol);\n }\n // Extract \"Something\" from \"const Component = Something\"\n if (ts.isVariableDeclaration(declaration) && declaration.initializer) {\n declaration = declaration.initializer;\n }\n // Extract \"Something\" from \"Something as MyComponentType\"\n if (ts.isAsExpression(declaration)) {\n declaration = declaration.expression;\n }\n // Extract \"Something from React.forwardRef(Something)\"\n if (\n ts.isCallExpression(declaration) &&\n (declaration.expression.getText() === 'React.forwardRef' || declaration.expression.getText() === 'forwardRef')\n ) {\n declaration = declaration.arguments[0];\n }\n\n // In the component function, find arguments destructuring\n let argument: ts.Node | undefined;\n if (\n ts.isFunctionDeclaration(declaration) ||\n ts.isFunctionExpression(declaration) ||\n ts.isArrowFunction(declaration)\n ) {\n if (declaration.parameters.length === 0) {\n return {};\n }\n argument = declaration.parameters[0].name;\n }\n if (!argument) {\n throw new Error(`Unsupported component declaration type ${ts.SyntaxKind[declaration.kind]}`);\n }\n if (!ts.isObjectBindingPattern(argument)) {\n // if a component does not use props de-structuring, we do not detect default values\n return {};\n }\n const values: Record = {};\n for (const element of argument.elements) {\n if (ts.isIdentifier(element.name) && element.initializer) {\n values[element.name.escapedText as string] = element.initializer.getText();\n }\n }\n return values;\n}\n\nexport function extractProps(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const exportType = checker.getDeclaredTypeOfSymbol(propsSymbol);\n\n return exportType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n return {\n name: value.name,\n type: stringifyType(type, checker),\n rawType: type,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractFunctions(propsSymbol: ts.Symbol, checker: ts.TypeChecker) {\n const propsName = propsSymbol.getName();\n const namespaceDeclaration = [\n // if we got the namespace directly\n ...(propsSymbol.getDeclarations() ?? []),\n // find namespace declaration from the interface with the same name\n ...(checker.getDeclaredTypeOfSymbol(propsSymbol).getSymbol()?.getDeclarations() ?? []),\n ].find(decl => decl.kind === ts.SyntaxKind.ModuleDeclaration);\n const refType = unwrapNamespaceDeclaration(namespaceDeclaration)\n .map(child => checker.getTypeAtLocation(child))\n .find(type => (type.getSymbol() ?? type.aliasSymbol)?.getName() === 'Ref');\n\n if (!refType) {\n return [];\n }\n return refType\n .getProperties()\n .map((value): ExpandedProp => {\n const declaration = extractDeclaration(value);\n const type = checker.getTypeAtLocation(declaration);\n const realType = type.getNonNullableType();\n if (realType.getCallSignatures().length === 0) {\n throw new Error(\n `${propsName}.Ref should contain only methods, \"${value.name}\" has a \"${stringifyType(type, checker)}\" type`,\n );\n }\n return {\n name: value.name,\n type: stringifyType(realType, checker),\n rawType: realType,\n rawTypeNode: (declaration as ts.PropertyDeclaration).type,\n isOptional: isOptional(type),\n description: getDescription(value.getDocumentationComment(checker), declaration),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function extractExports(\n componentName: string,\n exportSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n extraExports: Record> | false,\n) {\n let componentSymbol;\n let propsSymbol;\n const unknownExports: Array = [];\n for (const exportSymbol of exportSymbols) {\n if (exportSymbol.name === 'default' || exportSymbol.name === componentName) {\n validateComponentType(checker.getDeclaredTypeOfSymbol(exportSymbol), checker);\n componentSymbol = exportSymbol;\n } else if (exportSymbol.name === `${componentName}Props`) {\n propsSymbol = exportSymbol;\n } else if (\n extraExports !== false &&\n (!extraExports[componentName] || !extraExports[componentName].includes(exportSymbol.name))\n ) {\n unknownExports.push(exportSymbol.name);\n }\n }\n if (unknownExports.length > 0) {\n throw new Error(`Unexpected exports in ${componentName}: ${unknownExports.join(', ')}`);\n }\n if (!componentSymbol) {\n throw new Error(`Missing default export for ${componentName}`);\n }\n if (!propsSymbol) {\n throw new Error(`Missing ${componentName}Props export`);\n }\n return { componentSymbol, propsSymbol };\n}\n\nfunction validateComponentType(type: ts.Type, checker: ts.TypeChecker) {\n if (\n // React.forwardRef\n type.getSymbol()?.name !== 'ForwardRefExoticComponent' &&\n // Plain function returning JSX\n type.getCallSignatures().some(signature => {\n const returnTypeName = checker.typeToString(signature.getReturnType());\n return returnTypeName !== 'Element' && returnTypeName !== 'ReactPortal';\n })\n ) {\n throw new Error(`Unknown default export type ${checker.typeToString(type)}`);\n }\n}\n"]} \ No newline at end of file