@rushstack/package-extractor 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.json +49 -0
  2. package/CHANGELOG.md +15 -1
  3. package/dist/scripts/create-links.js +17161 -1197
  4. package/dist/scripts/create-links.js.map +1 -1
  5. package/dist/tsdoc-metadata.json +1 -1
  6. package/lib-commonjs/ArchiveManager.js +64 -0
  7. package/lib-commonjs/ArchiveManager.js.map +1 -0
  8. package/lib-commonjs/AssetHandler.js +171 -0
  9. package/lib-commonjs/AssetHandler.js.map +1 -0
  10. package/lib-commonjs/PackageExtractor.js +568 -0
  11. package/lib-commonjs/PackageExtractor.js.map +1 -0
  12. package/lib-commonjs/PathConstants.js +11 -0
  13. package/lib-commonjs/PathConstants.js.map +1 -0
  14. package/lib-commonjs/SymlinkAnalyzer.js +159 -0
  15. package/lib-commonjs/SymlinkAnalyzer.js.map +1 -0
  16. package/lib-commonjs/Utils.js +85 -0
  17. package/lib-commonjs/Utils.js.map +1 -0
  18. package/lib-commonjs/index.js +8 -0
  19. package/lib-commonjs/index.js.map +1 -0
  20. package/lib-commonjs/scripts/createLinks/cli/CreateLinksCommandLineParser.js +35 -0
  21. package/lib-commonjs/scripts/createLinks/cli/CreateLinksCommandLineParser.js.map +1 -0
  22. package/lib-commonjs/scripts/createLinks/cli/actions/CreateLinksAction.js +91 -0
  23. package/lib-commonjs/scripts/createLinks/cli/actions/CreateLinksAction.js.map +1 -0
  24. package/lib-commonjs/scripts/createLinks/cli/actions/RemoveLinksAction.js +38 -0
  25. package/lib-commonjs/scripts/createLinks/cli/actions/RemoveLinksAction.js.map +1 -0
  26. package/lib-commonjs/scripts/createLinks/start.js +10 -0
  27. package/lib-commonjs/scripts/createLinks/start.js.map +1 -0
  28. package/lib-commonjs/scripts/createLinks/utilities/CreateLinksUtilities.js +14 -0
  29. package/lib-commonjs/scripts/createLinks/utilities/CreateLinksUtilities.js.map +1 -0
  30. package/lib-commonjs/scripts/createLinks/utilities/constants.js +44 -0
  31. package/lib-commonjs/scripts/createLinks/utilities/constants.js.map +1 -0
  32. package/lib-dts/ArchiveManager.d.ts +13 -0
  33. package/lib-dts/ArchiveManager.d.ts.map +1 -0
  34. package/lib-dts/AssetHandler.d.ts +52 -0
  35. package/lib-dts/AssetHandler.d.ts.map +1 -0
  36. package/lib-dts/PackageExtractor.d.ts +280 -0
  37. package/lib-dts/PackageExtractor.d.ts.map +1 -0
  38. package/lib-dts/PathConstants.d.ts +4 -0
  39. package/lib-dts/PathConstants.d.ts.map +1 -0
  40. package/lib-dts/SymlinkAnalyzer.d.ts +73 -0
  41. package/lib-dts/SymlinkAnalyzer.d.ts.map +1 -0
  42. package/lib-dts/Utils.d.ts +30 -0
  43. package/lib-dts/Utils.d.ts.map +1 -0
  44. package/lib-dts/index.d.ts +3 -0
  45. package/lib-dts/index.d.ts.map +1 -0
  46. package/lib-dts/scripts/createLinks/cli/CreateLinksCommandLineParser.d.ts +8 -0
  47. package/lib-dts/scripts/createLinks/cli/CreateLinksCommandLineParser.d.ts.map +1 -0
  48. package/lib-dts/scripts/createLinks/cli/actions/CreateLinksAction.d.ts +10 -0
  49. package/lib-dts/scripts/createLinks/cli/actions/CreateLinksAction.d.ts.map +1 -0
  50. package/lib-dts/scripts/createLinks/cli/actions/RemoveLinksAction.d.ts +10 -0
  51. package/lib-dts/scripts/createLinks/cli/actions/RemoveLinksAction.d.ts.map +1 -0
  52. package/lib-dts/scripts/createLinks/start.d.ts +2 -0
  53. package/lib-dts/scripts/createLinks/start.d.ts.map +1 -0
  54. package/lib-dts/scripts/createLinks/utilities/CreateLinksUtilities.d.ts +3 -0
  55. package/lib-dts/scripts/createLinks/utilities/CreateLinksUtilities.d.ts.map +1 -0
  56. package/lib-dts/scripts/createLinks/utilities/constants.d.ts +34 -0
  57. package/lib-dts/scripts/createLinks/utilities/constants.d.ts.map +1 -0
  58. package/lib-esm/ArchiveManager.js +57 -0
  59. package/lib-esm/ArchiveManager.js.map +1 -0
  60. package/lib-esm/AssetHandler.js +164 -0
  61. package/lib-esm/AssetHandler.js.map +1 -0
  62. package/lib-esm/PackageExtractor.js +528 -0
  63. package/lib-esm/PackageExtractor.js.map +1 -0
  64. package/lib-esm/PathConstants.js +8 -0
  65. package/lib-esm/PathConstants.js.map +1 -0
  66. package/lib-esm/SymlinkAnalyzer.js +122 -0
  67. package/lib-esm/SymlinkAnalyzer.js.map +1 -0
  68. package/lib-esm/Utils.js +76 -0
  69. package/lib-esm/Utils.js.map +1 -0
  70. package/lib-esm/index.js +4 -0
  71. package/lib-esm/index.js.map +1 -0
  72. package/lib-esm/scripts/createLinks/cli/CreateLinksCommandLineParser.js +31 -0
  73. package/lib-esm/scripts/createLinks/cli/CreateLinksCommandLineParser.js.map +1 -0
  74. package/lib-esm/scripts/createLinks/cli/actions/CreateLinksAction.js +84 -0
  75. package/lib-esm/scripts/createLinks/cli/actions/CreateLinksAction.js.map +1 -0
  76. package/lib-esm/scripts/createLinks/cli/actions/RemoveLinksAction.js +30 -0
  77. package/lib-esm/scripts/createLinks/cli/actions/RemoveLinksAction.js.map +1 -0
  78. package/lib-esm/scripts/createLinks/start.js +8 -0
  79. package/lib-esm/scripts/createLinks/start.js.map +1 -0
  80. package/lib-esm/scripts/createLinks/utilities/CreateLinksUtilities.js +11 -0
  81. package/lib-esm/scripts/createLinks/utilities/CreateLinksUtilities.js.map +1 -0
  82. package/lib-esm/scripts/createLinks/utilities/constants.js +38 -0
  83. package/lib-esm/scripts/createLinks/utilities/constants.js.map +1 -0
  84. package/package.json +9 -7
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.56.3"
8
+ "packageVersion": "7.57.0"
9
9
  }
10
10
  ]
11
11
  }
@@ -0,0 +1,64 @@
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.
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.ArchiveManager = void 0;
9
+ const jszip_1 = __importDefault(require("jszip"));
10
+ const node_core_library_1 = require("@rushstack/node-core-library");
11
+ // 755 are default permissions to allow read/write/execute for owner and read/execute for group and others.
12
+ const DEFAULT_FILE_PERMISSIONS = 0o755;
13
+ // This value sets the allowed permissions when preserving symbolic links.
14
+ // 120000 is the symbolic link identifier, and is OR'd with the default file permissions.
15
+ // See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h#n10
16
+ // eslint-disable-next-line no-bitwise
17
+ const SYMBOLIC_LINK_PERMISSIONS = 0o120000 | DEFAULT_FILE_PERMISSIONS;
18
+ class ArchiveManager {
19
+ constructor() {
20
+ this._zip = new jszip_1.default();
21
+ }
22
+ async addToArchiveAsync(options) {
23
+ var _a;
24
+ const { filePath, fileData, archivePath } = options;
25
+ let data;
26
+ let permissions;
27
+ if (filePath) {
28
+ const stats = (_a = options.stats) !== null && _a !== void 0 ? _a : (await node_core_library_1.FileSystem.getLinkStatisticsAsync(filePath));
29
+ if (stats.isSymbolicLink()) {
30
+ data = await node_core_library_1.FileSystem.readLinkAsync(filePath);
31
+ permissions = SYMBOLIC_LINK_PERMISSIONS;
32
+ }
33
+ else if (stats.isDirectory()) {
34
+ throw new Error('Directories cannot be added to the archive');
35
+ }
36
+ else {
37
+ data = await node_core_library_1.FileSystem.readFileToBufferAsync(filePath);
38
+ permissions = stats.mode;
39
+ }
40
+ }
41
+ else if (fileData) {
42
+ data = fileData;
43
+ permissions = DEFAULT_FILE_PERMISSIONS;
44
+ }
45
+ else {
46
+ throw new Error('Either filePath or fileData must be provided');
47
+ }
48
+ // Replace backslashes for Unix compat
49
+ const addPath = node_core_library_1.Path.convertToSlashes(archivePath);
50
+ this._zip.file(addPath, data, {
51
+ unixPermissions: permissions,
52
+ dir: false
53
+ });
54
+ }
55
+ async createArchiveAsync(archiveFilePath) {
56
+ const zipContent = await this._zip.generateAsync({
57
+ type: 'nodebuffer',
58
+ platform: 'UNIX'
59
+ });
60
+ await node_core_library_1.FileSystem.writeFileAsync(archiveFilePath, zipContent);
61
+ }
62
+ }
63
+ exports.ArchiveManager = ArchiveManager;
64
+ //# sourceMappingURL=ArchiveManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArchiveManager.js","sourceRoot":"","sources":["../src/ArchiveManager.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;AAE3D,kDAA0B;AAE1B,oEAAsF;AAEtF,2GAA2G;AAC3G,MAAM,wBAAwB,GAAW,KAAK,CAAC;AAC/C,0EAA0E;AAC1E,yFAAyF;AACzF,6GAA6G;AAC7G,sCAAsC;AACtC,MAAM,yBAAyB,GAAW,QAAQ,GAAG,wBAAwB,CAAC;AAS9E,MAAa,cAAc;IAA3B;QACU,SAAI,GAAU,IAAI,eAAK,EAAE,CAAC;IAwCpC,CAAC;IAtCQ,KAAK,CAAC,iBAAiB,CAAC,OAA6B;;QAC1D,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;QAEpD,IAAI,IAAqB,CAAC;QAC1B,IAAI,WAAmB,CAAC;QACxB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,KAAK,GAAoB,MAAA,OAAO,CAAC,KAAK,mCAAI,CAAC,MAAM,8BAAU,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpG,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC3B,IAAI,GAAG,MAAM,8BAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAChD,WAAW,GAAG,yBAAyB,CAAC;YAC1C,CAAC;iBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,MAAM,8BAAU,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;gBACxD,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,IAAI,GAAG,QAAQ,CAAC;YAChB,WAAW,GAAG,wBAAwB,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QAED,sCAAsC;QACtC,MAAM,OAAO,GAAW,wBAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE;YAC5B,eAAe,EAAE,WAAW;YAC5B,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,eAAuB;QACrD,MAAM,UAAU,GAAW,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;YACvD,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;QACH,MAAM,8BAAU,CAAC,cAAc,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC/D,CAAC;CACF;AAzCD,wCAyCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport JSZip from 'jszip';\n\nimport { FileSystem, type FileSystemStats, Path } from '@rushstack/node-core-library';\n\n// 755 are default permissions to allow read/write/execute for owner and read/execute for group and others.\nconst DEFAULT_FILE_PERMISSIONS: number = 0o755;\n// This value sets the allowed permissions when preserving symbolic links.\n// 120000 is the symbolic link identifier, and is OR'd with the default file permissions.\n// See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h#n10\n// eslint-disable-next-line no-bitwise\nconst SYMBOLIC_LINK_PERMISSIONS: number = 0o120000 | DEFAULT_FILE_PERMISSIONS;\n\nexport interface IAddToArchiveOptions {\n filePath?: string;\n fileData?: Buffer | string;\n archivePath: string;\n stats?: FileSystemStats;\n}\n\nexport class ArchiveManager {\n private _zip: JSZip = new JSZip();\n\n public async addToArchiveAsync(options: IAddToArchiveOptions): Promise<void> {\n const { filePath, fileData, archivePath } = options;\n\n let data: Buffer | string;\n let permissions: number;\n if (filePath) {\n const stats: FileSystemStats = options.stats ?? (await FileSystem.getLinkStatisticsAsync(filePath));\n if (stats.isSymbolicLink()) {\n data = await FileSystem.readLinkAsync(filePath);\n permissions = SYMBOLIC_LINK_PERMISSIONS;\n } else if (stats.isDirectory()) {\n throw new Error('Directories cannot be added to the archive');\n } else {\n data = await FileSystem.readFileToBufferAsync(filePath);\n permissions = stats.mode;\n }\n } else if (fileData) {\n data = fileData;\n permissions = DEFAULT_FILE_PERMISSIONS;\n } else {\n throw new Error('Either filePath or fileData must be provided');\n }\n\n // Replace backslashes for Unix compat\n const addPath: string = Path.convertToSlashes(archivePath);\n this._zip.file(addPath, data, {\n unixPermissions: permissions,\n dir: false\n });\n }\n\n public async createArchiveAsync(archiveFilePath: string): Promise<void> {\n const zipContent: Buffer = await this._zip.generateAsync({\n type: 'nodebuffer',\n platform: 'UNIX'\n });\n await FileSystem.writeFileAsync(archiveFilePath, zipContent);\n }\n}\n"]}
@@ -0,0 +1,171 @@
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.
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.AssetHandler = void 0;
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_core_library_1 = require("@rushstack/node-core-library");
12
+ const ArchiveManager_1 = require("./ArchiveManager");
13
+ const Utils_1 = require("./Utils");
14
+ class AssetHandler {
15
+ constructor(options) {
16
+ this._includedAssetPaths = new Set();
17
+ this._isFinalized = false;
18
+ const { terminal, sourceRootFolder, targetRootFolder, linkCreation, symlinkAnalyzer, createArchiveFilePath, createArchiveOnly = false } = options;
19
+ this._terminal = terminal;
20
+ this._sourceRootFolder = sourceRootFolder;
21
+ this._targetRootFolder = targetRootFolder;
22
+ this._symlinkAnalyzer = symlinkAnalyzer;
23
+ if (createArchiveFilePath) {
24
+ if (node_path_1.default.extname(createArchiveFilePath) !== '.zip') {
25
+ throw new Error('Only archives with the .zip file extension are currently supported.');
26
+ }
27
+ this._archiveFilePath = node_path_1.default.resolve(targetRootFolder, createArchiveFilePath);
28
+ this._archiveManager = new ArchiveManager_1.ArchiveManager();
29
+ }
30
+ if (createArchiveOnly && !this._archiveManager) {
31
+ throw new Error('createArchiveOnly cannot be true if createArchiveFilePath is not provided');
32
+ }
33
+ this._createArchiveOnly = createArchiveOnly;
34
+ this._linkCreationMode = linkCreation || 'default';
35
+ }
36
+ async includeAssetAsync(options) {
37
+ const { sourceFileContent, targetFilePath, ignoreIfExisting = false } = options;
38
+ let { sourceFilePath } = options;
39
+ if (this._isFinalized) {
40
+ throw new Error('includeAssetAsync() cannot be called after finalizeAsync()');
41
+ }
42
+ if (!sourceFilePath && !sourceFileContent) {
43
+ if (!node_core_library_1.Path.isUnder(targetFilePath, this._targetRootFolder)) {
44
+ throw new Error('The existing asset path must be under the target root folder');
45
+ }
46
+ sourceFilePath = targetFilePath;
47
+ }
48
+ if (sourceFilePath && sourceFileContent) {
49
+ throw new Error('Either sourceFilePath or sourceFileContent must be provided, but not both');
50
+ }
51
+ if (this._includedAssetPaths.has(targetFilePath)) {
52
+ if (ignoreIfExisting) {
53
+ return;
54
+ }
55
+ throw new Error(`The asset at path "${targetFilePath}" has already been included`);
56
+ }
57
+ if (!this._createArchiveOnly) {
58
+ // Ignore when the source file is the same as the target file, as it's a no-op
59
+ if (sourceFilePath && sourceFilePath !== targetFilePath) {
60
+ // Use the fs.copyFile API instead of FileSystem.copyFileAsync() since copyFileAsync performs
61
+ // a needless stat() call to determine if it's a file or folder, and we already know it's a file.
62
+ try {
63
+ await node_fs_1.default.promises.copyFile(sourceFilePath, targetFilePath, node_fs_1.default.constants.COPYFILE_EXCL);
64
+ }
65
+ catch (e) {
66
+ if (!node_core_library_1.FileSystem.isNotExistError(e)) {
67
+ throw e;
68
+ }
69
+ // The parent folder may not exist, so ensure it exists before trying to copy again
70
+ await node_core_library_1.FileSystem.ensureFolderAsync(node_path_1.default.dirname(targetFilePath));
71
+ await node_fs_1.default.promises.copyFile(sourceFilePath, targetFilePath, node_fs_1.default.constants.COPYFILE_EXCL);
72
+ }
73
+ }
74
+ else if (sourceFileContent) {
75
+ await node_core_library_1.FileSystem.writeFileAsync(targetFilePath, sourceFileContent, {
76
+ ensureFolderExists: true
77
+ });
78
+ }
79
+ }
80
+ if (this._archiveManager) {
81
+ const targetRelativeFilePath = node_path_1.default.relative(this._targetRootFolder, targetFilePath);
82
+ if (sourceFilePath) {
83
+ await this._archiveManager.addToArchiveAsync({
84
+ filePath: sourceFilePath,
85
+ archivePath: targetRelativeFilePath
86
+ });
87
+ }
88
+ else if (sourceFileContent) {
89
+ await this._archiveManager.addToArchiveAsync({
90
+ fileData: sourceFileContent,
91
+ archivePath: targetRelativeFilePath
92
+ });
93
+ }
94
+ }
95
+ this._includedAssetPaths.add(targetFilePath);
96
+ }
97
+ get assetPaths() {
98
+ return [...this._includedAssetPaths];
99
+ }
100
+ async finalizeAsync(options) {
101
+ const { onAfterExtractSymlinksAsync } = options !== null && options !== void 0 ? options : {};
102
+ if (this._isFinalized) {
103
+ throw new Error('finalizeAsync() has already been called');
104
+ }
105
+ if (this._linkCreationMode === 'default') {
106
+ this._terminal.writeLine('Creating symlinks');
107
+ const linksToCopy = this._symlinkAnalyzer.reportSymlinks();
108
+ await node_core_library_1.Async.forEachAsync(linksToCopy, async (linkToCopy) => {
109
+ await this._extractSymlinkAsync(linkToCopy);
110
+ });
111
+ }
112
+ await (onAfterExtractSymlinksAsync === null || onAfterExtractSymlinksAsync === void 0 ? void 0 : onAfterExtractSymlinksAsync());
113
+ if (this._archiveManager && this._archiveFilePath) {
114
+ this._terminal.writeLine(`Creating archive at "${this._archiveFilePath}"`);
115
+ await this._archiveManager.createArchiveAsync(this._archiveFilePath);
116
+ }
117
+ this._isFinalized = true;
118
+ }
119
+ /**
120
+ * Create a symlink as described by the ILinkInfo object.
121
+ */
122
+ async _extractSymlinkAsync(linkInfo) {
123
+ const { kind, linkPath, targetPath } = {
124
+ ...linkInfo,
125
+ linkPath: (0, Utils_1.remapSourcePathForTargetFolder)({
126
+ sourceRootFolder: this._sourceRootFolder,
127
+ targetRootFolder: this._targetRootFolder,
128
+ sourcePath: linkInfo.linkPath
129
+ }),
130
+ targetPath: (0, Utils_1.remapSourcePathForTargetFolder)({
131
+ sourceRootFolder: this._sourceRootFolder,
132
+ targetRootFolder: this._targetRootFolder,
133
+ sourcePath: linkInfo.targetPath
134
+ })
135
+ };
136
+ const newLinkFolder = node_path_1.default.dirname(linkPath);
137
+ await node_core_library_1.FileSystem.ensureFolderAsync(newLinkFolder);
138
+ // Link to the relative path for symlinks
139
+ const relativeTargetPath = node_path_1.default.relative(newLinkFolder, targetPath);
140
+ // NOTE: This logic is based on NpmLinkManager._createSymlink()
141
+ if (kind === 'fileLink') {
142
+ // For files, we use a Windows "hard link", because creating a symbolic link requires
143
+ // administrator permission. However hard links seem to cause build failures on Mac,
144
+ // so for all other operating systems we use symbolic links for this case.
145
+ if (process.platform === 'win32') {
146
+ await node_core_library_1.FileSystem.createHardLinkAsync({
147
+ linkTargetPath: relativeTargetPath,
148
+ newLinkPath: linkPath
149
+ });
150
+ }
151
+ else {
152
+ await node_core_library_1.FileSystem.createSymbolicLinkFileAsync({
153
+ linkTargetPath: relativeTargetPath,
154
+ newLinkPath: linkPath
155
+ });
156
+ }
157
+ }
158
+ else {
159
+ // Junctions are only supported on Windows. This will create a symbolic link on other platforms.
160
+ await node_core_library_1.FileSystem.createSymbolicLinkJunctionAsync({
161
+ linkTargetPath: relativeTargetPath,
162
+ newLinkPath: linkPath
163
+ });
164
+ }
165
+ // Since the created symlinks have the required relative paths, they can be added directly to
166
+ // the archive.
167
+ await this.includeAssetAsync({ targetFilePath: linkPath });
168
+ }
169
+ }
170
+ exports.AssetHandler = AssetHandler;
171
+ //# sourceMappingURL=AssetHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetHandler.js","sourceRoot":"","sources":["../src/AssetHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport { Async, FileSystem, Path, type FileSystemStats } from '@rushstack/node-core-library';\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { ArchiveManager } from './ArchiveManager';\nimport type { IExtractorOptions, LinkCreationMode } from './PackageExtractor';\nimport type { ILinkInfo, SymlinkAnalyzer } from './SymlinkAnalyzer';\nimport { remapSourcePathForTargetFolder } from './Utils';\n\nexport interface IIncludeAssetOptions {\n sourceFilePath?: string;\n sourceFileStats?: FileSystemStats;\n sourceFileContent?: string | Buffer;\n targetFilePath: string;\n ignoreIfExisting?: boolean;\n}\n\nexport interface IIncludeAssetPathOptions extends IIncludeAssetOptions {\n sourceFilePath: string;\n sourceFileContent?: never;\n}\n\nexport interface IIncludeExistingAssetPathOptions extends IIncludeAssetOptions {\n sourceFilePath?: never;\n sourceFileContent?: never;\n}\n\nexport interface IIncludeAssetContentOptions extends IIncludeAssetOptions {\n sourceFileContent: string | Buffer;\n sourceFilePath?: never;\n sourceFileStats?: never;\n}\n\nexport interface IAssetHandlerOptions extends IExtractorOptions {\n symlinkAnalyzer: SymlinkAnalyzer;\n}\n\nexport interface IFinalizeOptions {\n onAfterExtractSymlinksAsync: () => Promise<void>;\n}\n\nexport class AssetHandler {\n private readonly _terminal: ITerminal;\n private readonly _sourceRootFolder: string;\n private readonly _targetRootFolder: string;\n private readonly _createArchiveOnly: boolean;\n private readonly _symlinkAnalyzer: SymlinkAnalyzer;\n private readonly _archiveManager: ArchiveManager | undefined;\n private readonly _archiveFilePath: string | undefined;\n private readonly _linkCreationMode: LinkCreationMode;\n private readonly _includedAssetPaths: Set<string> = new Set<string>();\n private _isFinalized: boolean = false;\n\n public constructor(options: IAssetHandlerOptions) {\n const {\n terminal,\n sourceRootFolder,\n targetRootFolder,\n linkCreation,\n symlinkAnalyzer,\n createArchiveFilePath,\n createArchiveOnly = false\n } = options;\n this._terminal = terminal;\n this._sourceRootFolder = sourceRootFolder;\n this._targetRootFolder = targetRootFolder;\n this._symlinkAnalyzer = symlinkAnalyzer;\n if (createArchiveFilePath) {\n if (path.extname(createArchiveFilePath) !== '.zip') {\n throw new Error('Only archives with the .zip file extension are currently supported.');\n }\n this._archiveFilePath = path.resolve(targetRootFolder, createArchiveFilePath);\n this._archiveManager = new ArchiveManager();\n }\n if (createArchiveOnly && !this._archiveManager) {\n throw new Error('createArchiveOnly cannot be true if createArchiveFilePath is not provided');\n }\n this._createArchiveOnly = createArchiveOnly;\n this._linkCreationMode = linkCreation || 'default';\n }\n\n public async includeAssetAsync(options: IIncludeAssetPathOptions): Promise<void>;\n public async includeAssetAsync(options: IIncludeExistingAssetPathOptions): Promise<void>;\n public async includeAssetAsync(options: IIncludeAssetContentOptions): Promise<void>;\n public async includeAssetAsync(options: IIncludeAssetOptions): Promise<void> {\n const { sourceFileContent, targetFilePath, ignoreIfExisting = false } = options;\n let { sourceFilePath } = options;\n\n if (this._isFinalized) {\n throw new Error('includeAssetAsync() cannot be called after finalizeAsync()');\n }\n if (!sourceFilePath && !sourceFileContent) {\n if (!Path.isUnder(targetFilePath, this._targetRootFolder)) {\n throw new Error('The existing asset path must be under the target root folder');\n }\n sourceFilePath = targetFilePath;\n }\n if (sourceFilePath && sourceFileContent) {\n throw new Error('Either sourceFilePath or sourceFileContent must be provided, but not both');\n }\n if (this._includedAssetPaths.has(targetFilePath)) {\n if (ignoreIfExisting) {\n return;\n }\n throw new Error(`The asset at path \"${targetFilePath}\" has already been included`);\n }\n\n if (!this._createArchiveOnly) {\n // Ignore when the source file is the same as the target file, as it's a no-op\n if (sourceFilePath && sourceFilePath !== targetFilePath) {\n // Use the fs.copyFile API instead of FileSystem.copyFileAsync() since copyFileAsync performs\n // a needless stat() call to determine if it's a file or folder, and we already know it's a file.\n try {\n await fs.promises.copyFile(sourceFilePath, targetFilePath, fs.constants.COPYFILE_EXCL);\n } catch (e: unknown) {\n if (!FileSystem.isNotExistError(e as Error)) {\n throw e;\n }\n // The parent folder may not exist, so ensure it exists before trying to copy again\n await FileSystem.ensureFolderAsync(path.dirname(targetFilePath));\n await fs.promises.copyFile(sourceFilePath, targetFilePath, fs.constants.COPYFILE_EXCL);\n }\n } else if (sourceFileContent) {\n await FileSystem.writeFileAsync(targetFilePath, sourceFileContent, {\n ensureFolderExists: true\n });\n }\n }\n\n if (this._archiveManager) {\n const targetRelativeFilePath: string = path.relative(this._targetRootFolder, targetFilePath);\n if (sourceFilePath) {\n await this._archiveManager.addToArchiveAsync({\n filePath: sourceFilePath,\n archivePath: targetRelativeFilePath\n });\n } else if (sourceFileContent) {\n await this._archiveManager.addToArchiveAsync({\n fileData: sourceFileContent,\n archivePath: targetRelativeFilePath\n });\n }\n }\n\n this._includedAssetPaths.add(targetFilePath);\n }\n\n public get assetPaths(): string[] {\n return [...this._includedAssetPaths];\n }\n\n public async finalizeAsync(options?: IFinalizeOptions): Promise<void> {\n const { onAfterExtractSymlinksAsync } = options ?? {};\n\n if (this._isFinalized) {\n throw new Error('finalizeAsync() has already been called');\n }\n\n if (this._linkCreationMode === 'default') {\n this._terminal.writeLine('Creating symlinks');\n const linksToCopy: ILinkInfo[] = this._symlinkAnalyzer.reportSymlinks();\n await Async.forEachAsync(linksToCopy, async (linkToCopy: ILinkInfo) => {\n await this._extractSymlinkAsync(linkToCopy);\n });\n }\n\n await onAfterExtractSymlinksAsync?.();\n\n if (this._archiveManager && this._archiveFilePath) {\n this._terminal.writeLine(`Creating archive at \"${this._archiveFilePath}\"`);\n await this._archiveManager.createArchiveAsync(this._archiveFilePath);\n }\n\n this._isFinalized = true;\n }\n\n /**\n * Create a symlink as described by the ILinkInfo object.\n */\n private async _extractSymlinkAsync(linkInfo: ILinkInfo): Promise<void> {\n const { kind, linkPath, targetPath } = {\n ...linkInfo,\n linkPath: remapSourcePathForTargetFolder({\n sourceRootFolder: this._sourceRootFolder,\n targetRootFolder: this._targetRootFolder,\n sourcePath: linkInfo.linkPath\n }),\n targetPath: remapSourcePathForTargetFolder({\n sourceRootFolder: this._sourceRootFolder,\n targetRootFolder: this._targetRootFolder,\n sourcePath: linkInfo.targetPath\n })\n };\n\n const newLinkFolder: string = path.dirname(linkPath);\n await FileSystem.ensureFolderAsync(newLinkFolder);\n\n // Link to the relative path for symlinks\n const relativeTargetPath: string = path.relative(newLinkFolder, targetPath);\n\n // NOTE: This logic is based on NpmLinkManager._createSymlink()\n if (kind === 'fileLink') {\n // For files, we use a Windows \"hard link\", because creating a symbolic link requires\n // administrator permission. However hard links seem to cause build failures on Mac,\n // so for all other operating systems we use symbolic links for this case.\n if (process.platform === 'win32') {\n await FileSystem.createHardLinkAsync({\n linkTargetPath: relativeTargetPath,\n newLinkPath: linkPath\n });\n } else {\n await FileSystem.createSymbolicLinkFileAsync({\n linkTargetPath: relativeTargetPath,\n newLinkPath: linkPath\n });\n }\n } else {\n // Junctions are only supported on Windows. This will create a symbolic link on other platforms.\n await FileSystem.createSymbolicLinkJunctionAsync({\n linkTargetPath: relativeTargetPath,\n newLinkPath: linkPath\n });\n }\n\n // Since the created symlinks have the required relative paths, they can be added directly to\n // the archive.\n await this.includeAssetAsync({ targetFilePath: linkPath });\n }\n}\n"]}