UNPKG

8.27 kBJavaScriptView Raw
1"use strict";
2// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3// See LICENSE in the project root for license information.
4var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5 if (k2 === undefined) k2 = k;
6 var desc = Object.getOwnPropertyDescriptor(m, k);
7 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8 desc = { enumerable: true, get: function() { return m[k]; } };
9 }
10 Object.defineProperty(o, k2, desc);
11}) : (function(o, m, k, k2) {
12 if (k2 === undefined) k2 = k;
13 o[k2] = m[k];
14}));
15var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16 Object.defineProperty(o, "default", { enumerable: true, value: v });
17}) : function(o, v) {
18 o["default"] = v;
19});
20var __importStar = (this && this.__importStar) || function (mod) {
21 if (mod && mod.__esModule) return mod;
22 var result = {};
23 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24 __setModuleDefault(result, mod);
25 return result;
26};
27Object.defineProperty(exports, "__esModule", { value: true });
28exports.PackageMetadataManager = exports.PackageMetadata = void 0;
29const path = __importStar(require("path"));
30const node_core_library_1 = require("@rushstack/node-core-library");
31const Extractor_1 = require("../api/Extractor");
32/**
33 * Represents analyzed information for a package.json file.
34 * This object is constructed and returned by PackageMetadataManager.
35 */
36class PackageMetadata {
37 constructor(packageJsonPath, packageJson, aedocSupported) {
38 this.packageJsonPath = packageJsonPath;
39 this.packageJson = packageJson;
40 this.aedocSupported = aedocSupported;
41 }
42}
43exports.PackageMetadata = PackageMetadata;
44/**
45 * This class maintains a cache of analyzed information obtained from package.json
46 * files. It is built on top of the PackageJsonLookup class.
47 *
48 * @remarks
49 *
50 * IMPORTANT: Don't use PackageMetadataManager to analyze source files from the current project:
51 * 1. Files such as tsdoc-metadata.json may not have been built yet, and thus may contain incorrect information.
52 * 2. The current project is not guaranteed to have a package.json file at all. For example, API Extractor can
53 * be invoked on a bare .d.ts file.
54 *
55 * Use ts.program.isSourceFileFromExternalLibrary() to test source files before passing the to PackageMetadataManager.
56 */
57class PackageMetadataManager {
58 constructor(packageJsonLookup, messageRouter) {
59 this._packageMetadataByPackageJsonPath = new Map();
60 this._packageJsonLookup = packageJsonLookup;
61 this._messageRouter = messageRouter;
62 }
63 // This feature is still being standardized: https://github.com/microsoft/tsdoc/issues/7
64 // In the future we will use the @microsoft/tsdoc library to read this file.
65 static _resolveTsdocMetadataPathFromPackageJson(packageFolder, packageJson) {
66 const tsdocMetadataFilename = PackageMetadataManager.tsdocMetadataFilename;
67 let tsdocMetadataRelativePath;
68 if (packageJson.tsdocMetadata) {
69 // 1. If package.json contains a field such as "tsdocMetadata": "./path1/path2/tsdoc-metadata.json",
70 // then that takes precedence. This convention will be rarely needed, since the other rules below generally
71 // produce a good result.
72 tsdocMetadataRelativePath = packageJson.tsdocMetadata;
73 }
74 else if (packageJson.typings) {
75 // 2. If package.json contains a field such as "typings": "./path1/path2/index.d.ts", then we look
76 // for the file under "./path1/path2/tsdoc-metadata.json"
77 tsdocMetadataRelativePath = path.join(path.dirname(packageJson.typings), tsdocMetadataFilename);
78 }
79 else if (packageJson.main) {
80 // 3. If package.json contains a field such as "main": "./path1/path2/index.js", then we look for
81 // the file under "./path1/path2/tsdoc-metadata.json"
82 tsdocMetadataRelativePath = path.join(path.dirname(packageJson.main), tsdocMetadataFilename);
83 }
84 else {
85 // 4. If none of the above rules apply, then by default we look for the file under "./tsdoc-metadata.json"
86 // since the default entry point is "./index.js"
87 tsdocMetadataRelativePath = tsdocMetadataFilename;
88 }
89 // Always resolve relative to the package folder.
90 const tsdocMetadataPath = path.resolve(packageFolder, tsdocMetadataRelativePath);
91 return tsdocMetadataPath;
92 }
93 /**
94 * @param tsdocMetadataPath - An explicit path that can be configured in api-extractor.json.
95 * If this parameter is not an empty string, it overrides the normal path calculation.
96 * @returns the absolute path to the TSDoc metadata file
97 */
98 static resolveTsdocMetadataPath(packageFolder, packageJson, tsdocMetadataPath) {
99 if (tsdocMetadataPath) {
100 return path.resolve(packageFolder, tsdocMetadataPath);
101 }
102 return PackageMetadataManager._resolveTsdocMetadataPathFromPackageJson(packageFolder, packageJson);
103 }
104 /**
105 * Writes the TSDoc metadata file to the specified output file.
106 */
107 static writeTsdocMetadataFile(tsdocMetadataPath, newlineKind) {
108 const fileObject = {
109 tsdocVersion: '0.12',
110 toolPackages: [
111 {
112 packageName: '@microsoft/api-extractor',
113 packageVersion: Extractor_1.Extractor.version
114 }
115 ]
116 };
117 const fileContent = '// This file is read by tools that parse documentation comments conforming to the TSDoc standard.\n' +
118 '// It should be published with your NPM package. It should not be tracked by Git.\n' +
119 node_core_library_1.JsonFile.stringify(fileObject);
120 node_core_library_1.FileSystem.writeFile(tsdocMetadataPath, fileContent, {
121 convertLineEndings: newlineKind,
122 ensureFolderExists: true
123 });
124 }
125 /**
126 * Finds the package.json in a parent folder of the specified source file, and
127 * returns a PackageMetadata object. If no package.json was found, then undefined
128 * is returned. The results are cached.
129 */
130 tryFetchPackageMetadata(sourceFilePath) {
131 const packageJsonFilePath = this._packageJsonLookup.tryGetPackageJsonFilePathFor(sourceFilePath);
132 if (!packageJsonFilePath) {
133 return undefined;
134 }
135 let packageMetadata = this._packageMetadataByPackageJsonPath.get(packageJsonFilePath);
136 if (!packageMetadata) {
137 const packageJson = this._packageJsonLookup.loadNodePackageJson(packageJsonFilePath);
138 const packageJsonFolder = path.dirname(packageJsonFilePath);
139 let aedocSupported = false;
140 const tsdocMetadataPath = PackageMetadataManager._resolveTsdocMetadataPathFromPackageJson(packageJsonFolder, packageJson);
141 if (node_core_library_1.FileSystem.exists(tsdocMetadataPath)) {
142 this._messageRouter.logVerbose("console-found-tsdoc-metadata" /* ConsoleMessageId.FoundTSDocMetadata */, 'Found metadata in ' + tsdocMetadataPath);
143 // If the file exists at all, assume it was written by API Extractor
144 aedocSupported = true;
145 }
146 packageMetadata = new PackageMetadata(packageJsonFilePath, packageJson, aedocSupported);
147 this._packageMetadataByPackageJsonPath.set(packageJsonFilePath, packageMetadata);
148 }
149 return packageMetadata;
150 }
151 /**
152 * Returns true if the source file is part of a package whose .d.ts files support AEDoc annotations.
153 */
154 isAedocSupportedFor(sourceFilePath) {
155 const packageMetadata = this.tryFetchPackageMetadata(sourceFilePath);
156 if (!packageMetadata) {
157 return false;
158 }
159 return packageMetadata.aedocSupported;
160 }
161}
162exports.PackageMetadataManager = PackageMetadataManager;
163PackageMetadataManager.tsdocMetadataFilename = 'tsdoc-metadata.json';
164//# sourceMappingURL=PackageMetadataManager.js.map
\No newline at end of file