@vscode/vsce 2.30.0 → 2.30.1-1

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.
package/dist/vsce.d.ts CHANGED
@@ -117,6 +117,7 @@ export declare interface IPackageOptions {
117
117
  readonly preRelease?: boolean;
118
118
  readonly allowStarActivation?: boolean;
119
119
  readonly allowMissingRepository?: boolean;
120
+ readonly allowUnusedFilesPattern?: boolean;
120
121
  readonly skipLicense?: boolean;
121
122
  readonly signTool?: string;
122
123
  }
@@ -172,6 +173,7 @@ export declare interface IPublishOptions {
172
173
  readonly preRelease?: boolean;
173
174
  readonly allowStarActivation?: boolean;
174
175
  readonly allowMissingRepository?: boolean;
176
+ readonly allowUnusedFilesPattern?: boolean;
175
177
  readonly skipDuplicate?: boolean;
176
178
  readonly skipLicense?: boolean;
177
179
  readonly sigzipPath?: string[];
package/out/main.js CHANGED
@@ -77,6 +77,7 @@ module.exports = function (argv) {
77
77
  commander_1.default
78
78
  .command('ls')
79
79
  .description('Lists all the files that will be published/packaged')
80
+ .option('--tree', 'Prints the files in a tree format', false)
80
81
  .option('--yarn', 'Use yarn instead of npm (default inferred from presence of yarn.lock or .yarnrc)')
81
82
  .option('--no-yarn', 'Use npm instead of yarn (default inferred from absence of yarn.lock or .yarnrc)')
82
83
  .option('--packagedDependencies <path>', 'Select packages that should be published only (includes dependencies)', (val, all) => (all ? all.concat(val) : [val]), undefined)
@@ -84,7 +85,7 @@ module.exports = function (argv) {
84
85
  // default must remain undefined for dependencies or we will fail to load defaults from package.json
85
86
  .option('--dependencies', 'Enable dependency detection via npm or yarn', undefined)
86
87
  .option('--no-dependencies', 'Disable dependency detection via npm or yarn', undefined)
87
- .action(({ yarn, packagedDependencies, ignoreFile, dependencies }) => main((0, package_1.ls)({ useYarn: yarn, packagedDependencies, ignoreFile, dependencies })));
88
+ .action(({ tree, yarn, packagedDependencies, ignoreFile, dependencies }) => main((0, package_1.ls)({ tree, useYarn: yarn, packagedDependencies, ignoreFile, dependencies })));
88
89
  commander_1.default
89
90
  .command('package [version]')
90
91
  .alias('pack')
@@ -113,9 +114,10 @@ module.exports = function (argv) {
113
114
  .option('--pre-release', 'Mark this package as a pre-release')
114
115
  .option('--allow-star-activation', 'Allow using * in activation events')
115
116
  .option('--allow-missing-repository', 'Allow missing a repository URL in package.json')
117
+ .option('--allow-unused-files-pattern', 'Allow include patterns for the files field in package.json that does not match any file')
116
118
  .option('--skip-license', 'Allow packaging without license file')
117
119
  .option('--sign-tool <path>', 'Path to the VSIX signing tool. Will be invoked with two arguments: `SIGNTOOL <path/to/extension.signature.manifest> <path/to/extension.signature.p7s>`.')
118
- .action((version, { out, target, ignoreOtherTargetFolders, readmePath, changelogPath, message, gitTagVersion, updatePackageJson, githubBranch, gitlabBranch, rewriteRelativeLinks, baseContentUrl, baseImagesUrl, yarn, ignoreFile, gitHubIssueLinking, gitLabIssueLinking, dependencies, preRelease, allowStarActivation, allowMissingRepository, skipLicense, signTool, }) => main((0, package_1.packageCommand)({
120
+ .action((version, { out, target, ignoreOtherTargetFolders, readmePath, changelogPath, message, gitTagVersion, updatePackageJson, githubBranch, gitlabBranch, rewriteRelativeLinks, baseContentUrl, baseImagesUrl, yarn, ignoreFile, gitHubIssueLinking, gitLabIssueLinking, dependencies, preRelease, allowStarActivation, allowMissingRepository, allowUnusedFilesPattern, skipLicense, signTool, }) => main((0, package_1.packageCommand)({
119
121
  packagePath: out,
120
122
  version,
121
123
  target,
@@ -138,6 +140,7 @@ module.exports = function (argv) {
138
140
  preRelease,
139
141
  allowStarActivation,
140
142
  allowMissingRepository,
143
+ allowUnusedFilesPattern,
141
144
  skipLicense,
142
145
  signTool,
143
146
  })));
@@ -174,9 +177,10 @@ module.exports = function (argv) {
174
177
  .option('--pre-release', 'Mark this package as a pre-release')
175
178
  .option('--allow-star-activation', 'Allow using * in activation events')
176
179
  .option('--allow-missing-repository', 'Allow missing a repository URL in package.json')
180
+ .option('--allow-unused-files-pattern', 'Allow include patterns for the files field in package.json that does not match any file')
177
181
  .option('--skip-duplicate', 'Fail silently if version already exists on the marketplace')
178
182
  .option('--skip-license', 'Allow publishing without license file')
179
- .action((version, { pat, azureCredential, target, ignoreOtherTargetFolders, readmePath, changelogPath, message, gitTagVersion, updatePackageJson, packagePath, manifestPath, signaturePath, sigzipPath, githubBranch, gitlabBranch, baseContentUrl, baseImagesUrl, yarn, noVerify, allowProposedApis, allowAllProposedApis, ignoreFile, dependencies, preRelease, allowStarActivation, allowMissingRepository, skipDuplicate, skipLicense, signTool, }) => main((0, publish_1.publish)({
183
+ .action((version, { pat, azureCredential, target, ignoreOtherTargetFolders, readmePath, changelogPath, message, gitTagVersion, updatePackageJson, packagePath, manifestPath, signaturePath, sigzipPath, githubBranch, gitlabBranch, baseContentUrl, baseImagesUrl, yarn, noVerify, allowProposedApis, allowAllProposedApis, ignoreFile, dependencies, preRelease, allowStarActivation, allowMissingRepository, allowUnusedFilesPattern, skipDuplicate, skipLicense, signTool, }) => main((0, publish_1.publish)({
180
184
  pat,
181
185
  azureCredential,
182
186
  version,
@@ -204,6 +208,7 @@ module.exports = function (argv) {
204
208
  preRelease,
205
209
  allowStarActivation,
206
210
  allowMissingRepository,
211
+ allowUnusedFilesPattern,
207
212
  skipDuplicate,
208
213
  skipLicense,
209
214
  signTool
package/out/package.js CHANGED
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.printPackagedFiles = exports.ls = exports.listFiles = exports.packageCommand = exports.createSignatureArchive = exports.generateManifest = exports.signPackage = exports.pack = exports.prepublish = exports.collect = exports.createDefaultProcessors = exports.processFiles = exports.toContentTypes = exports.toVsixManifest = exports.readManifest = exports.validateManifest = exports.ValidationProcessor = exports.NLSProcessor = exports.isWebKind = exports.LicenseProcessor = exports.ChangelogProcessor = exports.ReadmeProcessor = exports.MarkdownProcessor = exports.TagsProcessor = exports.ManifestProcessor = exports.Targets = exports.versionBump = exports.BaseProcessor = exports.read = void 0;
29
+ exports.printAndValidatePackagedFiles = exports.ls = exports.listFiles = exports.packageCommand = exports.createSignatureArchive = exports.generateManifest = exports.signPackage = exports.pack = exports.prepublish = exports.collect = exports.createDefaultProcessors = exports.processFiles = exports.toContentTypes = exports.toVsixManifest = exports.readManifest = exports.validateManifest = exports.ValidationProcessor = exports.NLSProcessor = exports.isWebKind = exports.LicenseProcessor = exports.ChangelogProcessor = exports.ReadmeProcessor = exports.MarkdownProcessor = exports.TagsProcessor = exports.ManifestProcessor = exports.Targets = exports.versionBump = exports.BaseProcessor = exports.read = void 0;
30
30
  const fs = __importStar(require("fs"));
31
31
  const path = __importStar(require("path"));
32
32
  const util_1 = require("util");
@@ -500,7 +500,7 @@ class MarkdownProcessor extends BaseProcessor {
500
500
  super(manifest);
501
501
  this.name = name;
502
502
  this.assetType = assetType;
503
- this.regexp = new RegExp(`^extension/${filePath}$`, 'i');
503
+ this.regexp = new RegExp(`^${util.filePathToVsixPath(filePath)}$`, 'i');
504
504
  const guess = this.guessBaseUrls(options.githubBranch || options.gitlabBranch);
505
505
  this.baseContentUrl = options.baseContentUrl || (guess && guess.content);
506
506
  this.baseImagesUrl = options.baseImagesUrl || options.baseContentUrl || (guess && guess.images);
@@ -682,7 +682,7 @@ class LicenseProcessor extends BaseProcessor {
682
682
  }
683
683
  else {
684
684
  this.expectedLicenseName = match[1];
685
- const regexp = new RegExp('^extension/' + match[1] + '$');
685
+ const regexp = new RegExp(`^${util.filePathToVsixPath(match[1])}$`);
686
686
  this.filter = regexp.test.bind(regexp);
687
687
  }
688
688
  delete this.vsix.license;
@@ -744,7 +744,7 @@ class IconProcessor extends BaseProcessor {
744
744
  constructor(manifest) {
745
745
  super(manifest);
746
746
  this.didFindIcon = false;
747
- this.icon = manifest.icon && path.posix.normalize(`extension/${manifest.icon}`);
747
+ this.icon = manifest.icon && path.posix.normalize(util.filePathToVsixPath(manifest.icon));
748
748
  delete this.vsix.icon;
749
749
  }
750
750
  onFile(file) {
@@ -839,7 +839,7 @@ class NLSProcessor extends BaseProcessor {
839
839
  for (const translation of localization.translations) {
840
840
  if (translation.id === 'vscode' && !!translation.path) {
841
841
  const translationPath = util.normalize(translation.path.replace(/^\.[\/\\]/, ''));
842
- translations[localization.languageId.toUpperCase()] = `extension/${translationPath}`;
842
+ translations[localization.languageId.toUpperCase()] = util.filePathToVsixPath(translationPath);
843
843
  }
844
844
  }
845
845
  }
@@ -1110,7 +1110,7 @@ async function toVsixManifest(vsix) {
1110
1110
  </Installation>
1111
1111
  <Dependencies/>
1112
1112
  <Assets>
1113
- <Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" />
1113
+ <Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="${util.filePathToVsixPath('package.json')}" Addressable="true" />
1114
1114
  ${vsix.assets
1115
1115
  .map(asset => `<Asset Type="${escape(asset.type)}" Path="${escape(asset.path)}" Addressable="true" />`)
1116
1116
  .join('\n')}
@@ -1275,7 +1275,7 @@ function collect(manifest, options = {}) {
1275
1275
  const ignoreFile = options.ignoreFile || undefined;
1276
1276
  const processors = createDefaultProcessors(manifest, options);
1277
1277
  return collectFiles(cwd, getDependenciesOption(options), packagedDependencies, ignoreFile, manifest.files).then(fileNames => {
1278
- const files = fileNames.map(f => ({ path: `extension/${f}`, localPath: path.join(cwd, f) }));
1278
+ const files = fileNames.map(f => ({ path: util.filePathToVsixPath(f), localPath: path.join(cwd, f) }));
1279
1279
  return processFiles(processors, files);
1280
1280
  });
1281
1281
  }
@@ -1346,7 +1346,7 @@ async function pack(options = {}) {
1346
1346
  const cwd = options.cwd || process.cwd();
1347
1347
  const manifest = await readManifest(cwd);
1348
1348
  const files = await collect(manifest, options);
1349
- printPackagedFiles(files, cwd, manifest, options);
1349
+ await printAndValidatePackagedFiles(files, cwd, manifest, options);
1350
1350
  if (options.version && !(options.updatePackageJson ?? true)) {
1351
1351
  manifest.version = options.version;
1352
1352
  }
@@ -1393,17 +1393,8 @@ async function packageCommand(options = {}) {
1393
1393
  await signPackage(packagePath, options.signTool);
1394
1394
  }
1395
1395
  const stats = await fs.promises.stat(packagePath);
1396
- let size = 0;
1397
- let unit = '';
1398
- if (stats.size > 1048576) {
1399
- size = Math.round(stats.size / 10485.76) / 100;
1400
- unit = 'MB';
1401
- }
1402
- else {
1403
- size = Math.round(stats.size / 10.24) / 100;
1404
- unit = 'KB';
1405
- }
1406
- util.log.done(`Packaged: ${packagePath} (${files.length} files, ${size}${unit})`);
1396
+ const packageSize = util.bytesToString(stats.size);
1397
+ util.log.done(`Packaged: ${packagePath} ` + chalk_1.default.bold(`(${files.length} files, ${packageSize})`));
1407
1398
  }
1408
1399
  exports.packageCommand = packageCommand;
1409
1400
  /**
@@ -1411,7 +1402,7 @@ exports.packageCommand = packageCommand;
1411
1402
  */
1412
1403
  async function listFiles(options = {}) {
1413
1404
  const cwd = options.cwd ?? process.cwd();
1414
- const manifest = await readManifest(cwd);
1405
+ const manifest = options.manifest ?? await readManifest(cwd);
1415
1406
  if (options.prepublish) {
1416
1407
  await prepublish(cwd, manifest, options.useYarn);
1417
1408
  }
@@ -1419,49 +1410,91 @@ async function listFiles(options = {}) {
1419
1410
  }
1420
1411
  exports.listFiles = listFiles;
1421
1412
  /**
1422
- * Lists the files included in the extension's package. Runs prepublish.
1413
+ * Lists the files included in the extension's package.
1423
1414
  */
1424
1415
  async function ls(options = {}) {
1425
- const files = await listFiles({ ...options, prepublish: true });
1426
- for (const file of files) {
1427
- console.log(`${file}`);
1416
+ const cwd = process.cwd();
1417
+ const manifest = await readManifest(cwd);
1418
+ const files = await listFiles({ ...options, cwd, manifest });
1419
+ if (options.tree) {
1420
+ const printableFileStructure = await util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f => ({ origin: f, tree: f })));
1421
+ console.log(printableFileStructure.join('\n'));
1422
+ }
1423
+ else {
1424
+ console.log(files.join('\n'));
1428
1425
  }
1429
1426
  }
1430
1427
  exports.ls = ls;
1431
1428
  /**
1432
1429
  * Prints the packaged files of an extension.
1433
1430
  */
1434
- function printPackagedFiles(files, cwd, manifest, options) {
1431
+ async function printAndValidatePackagedFiles(files, cwd, manifest, options) {
1435
1432
  // Warn if the extension contains a lot of files
1436
1433
  const jsFiles = files.filter(f => /\.js$/i.test(f.path));
1437
1434
  if (files.length > 5000 || jsFiles.length > 100) {
1438
- let message = '\n';
1435
+ let message = '';
1439
1436
  message += `This extension consists of ${chalk_1.default.bold(String(files.length))} files, out of which ${chalk_1.default.bold(String(jsFiles.length))} are JavaScript files. `;
1440
1437
  message += `For performance reasons, you should bundle your extension: ${chalk_1.default.underline('https://aka.ms/vscode-bundle-extension')}. `;
1441
1438
  message += `You should also exclude unnecessary files by adding them to your .vscodeignore: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}.\n`;
1442
- console.log(message);
1439
+ util.log.warn(message);
1443
1440
  }
1444
1441
  // Warn if the extension does not have a .vscodeignore file or a files property in package.json
1445
- if (!options.ignoreFile && !manifest.files) {
1446
- const hasDeaultIgnore = fs.existsSync(path.join(cwd, '.vscodeignore'));
1447
- if (!hasDeaultIgnore) {
1442
+ const hasIgnoreFile = fs.existsSync(options.ignoreFile ?? path.join(cwd, '.vscodeignore'));
1443
+ if (!hasIgnoreFile && !manifest.files) {
1444
+ let message = '';
1445
+ message += `Neither a ${chalk_1.default.bold('.vscodeignore')} file nor a ${chalk_1.default.bold('"files"')} property in package.json was found. `;
1446
+ message += `To ensure only necessary files are included in your extension, `;
1447
+ message += `add a .vscodeignore file or specify the "files" property in package.json. More info: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}\n`;
1448
+ util.log.warn(message);
1449
+ }
1450
+ // Throw an error if the extension uses both a .vscodeignore file and the files property in package.json
1451
+ else if (hasIgnoreFile && manifest.files !== undefined && manifest.files.length > 0) {
1452
+ let message = '';
1453
+ message += `Both a ${chalk_1.default.bold('.vscodeignore')} file and a ${chalk_1.default.bold('"files"')} property in package.json were found. `;
1454
+ message += `VSCE does not support combining both strategies. `;
1455
+ message += `Either remove the ${chalk_1.default.bold('.vscodeignore')} file or the ${chalk_1.default.bold('"files"')} property in package.json.`;
1456
+ util.log.error(message);
1457
+ process.exit(1);
1458
+ }
1459
+ // Throw an error if the extension uses the files property in package.json and
1460
+ // the package does not include at least one file for each include pattern
1461
+ else if (manifest.files !== undefined && manifest.files.length > 0 && !options.allowUnusedFilesPattern) {
1462
+ const originalFilePaths = files.map(f => util.vsixPathToFilePath(f.path));
1463
+ const unusedIncludePatterns = [];
1464
+ for (const includePattern of manifest.files) {
1465
+ const hasMatchingFile = originalFilePaths.some(file => (0, minimatch_1.default)(file, includePattern, MinimatchOptions));
1466
+ if (!hasMatchingFile) {
1467
+ unusedIncludePatterns.push(includePattern);
1468
+ }
1469
+ }
1470
+ if (unusedIncludePatterns.length > 0) {
1448
1471
  let message = '';
1449
- message += `Neither a ${chalk_1.default.bold('.vscodeignore')} file nor a ${chalk_1.default.bold('"files"')} property in package.json was found. `;
1450
- message += `To ensure only necessary files are included in your extension package, `;
1451
- message += `add a .vscodeignore file or specify the "files" property in package.json. More info: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}`;
1452
- util.log.warn(message);
1472
+ message += `The following include patterns in the ${chalk_1.default.bold('"files"')} property in package.json do not match any files packaged in the extension:\n`;
1473
+ message += unusedIncludePatterns.map(p => ` - ${p}`).join('\n');
1474
+ message += '\nRemove any include pattern which is not needed.\n';
1475
+ message += `\n=> Run ${chalk_1.default.bold('vsce ls --tree')} to see all included files.\n`;
1476
+ message += `=> Use ${chalk_1.default.bold('--allow-unused-files-patterns')} to skip this check`;
1477
+ util.log.error(message);
1478
+ process.exit(1);
1453
1479
  }
1454
1480
  }
1455
1481
  // Print the files included in the package
1456
- const printableFileStructure = util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f => f.path), 35);
1482
+ const printableFileStructure = await util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f => ({
1483
+ // File path relative to the extension root
1484
+ origin: util.vsixPathToFilePath(f.path),
1485
+ // File path in the VSIX
1486
+ tree: f.path
1487
+ })), 35 // Print up to 35 files/folders
1488
+ );
1457
1489
  let message = '';
1458
1490
  message += chalk_1.default.bold.blue(`Files included in the VSIX:\n`);
1459
1491
  message += printableFileStructure.join('\n');
1492
+ // If not all files have been printed, mention how all files can be printed
1460
1493
  if (files.length + 1 > printableFileStructure.length) {
1461
- // If not all files have been printed, mention how all files can be printed
1462
- message += `\n\n=> Run ${chalk_1.default.bold('vsce ls')} to see a list of all included files.\n`;
1494
+ message += `\n\n=> Run ${chalk_1.default.bold('vsce ls --tree')} to see all included files.`;
1463
1495
  }
1496
+ message += '\n';
1464
1497
  util.log.info(message);
1465
1498
  }
1466
- exports.printPackagedFiles = printPackagedFiles;
1499
+ exports.printAndValidatePackagedFiles = printAndValidatePackagedFiles;
1467
1500
  //# sourceMappingURL=package.js.map
package/out/util.js CHANGED
@@ -1,10 +1,34 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateFileStructureTree = exports.patchOptionsWithManifest = exports.log = exports.sequence = exports.CancellationToken = exports.isCancelledError = exports.nonnull = exports.flatten = exports.chain = exports.normalize = exports.getPublicGalleryAPI = exports.getSecurityRolesAPI = exports.getGalleryAPI = exports.getHubUrl = exports.getMarketplaceUrl = exports.getPublishedUrl = exports.read = void 0;
29
+ exports.generateFileStructureTree = exports.vsixPathToFilePath = exports.filePathToVsixPath = exports.bytesToString = exports.patchOptionsWithManifest = exports.log = exports.sequence = exports.CancellationToken = exports.isCancelledError = exports.nonnull = exports.flatten = exports.chain = exports.normalize = exports.getPublicGalleryAPI = exports.getSecurityRolesAPI = exports.getGalleryAPI = exports.getHubUrl = exports.getMarketplaceUrl = exports.getPublishedUrl = exports.read = void 0;
7
30
  const util_1 = require("util");
31
+ const fs = __importStar(require("fs"));
8
32
  const read_1 = __importDefault(require("read"));
9
33
  const WebApi_1 = require("azure-devops-node-api/WebApi");
10
34
  const GalleryApi_1 = require("azure-devops-node-api/GalleryApi");
@@ -166,82 +190,177 @@ function patchOptionsWithManifest(options, manifest) {
166
190
  }
167
191
  }
168
192
  exports.patchOptionsWithManifest = patchOptionsWithManifest;
169
- function generateFileStructureTree(rootFolder, filePaths, maxPrint = Number.MAX_VALUE) {
193
+ function bytesToString(bytes) {
194
+ let size = 0;
195
+ let unit = '';
196
+ if (bytes > 1048576) {
197
+ size = Math.round(bytes / 10485.76) / 100;
198
+ unit = 'MB';
199
+ }
200
+ else {
201
+ size = Math.round(bytes / 10.24) / 100;
202
+ unit = 'KB';
203
+ }
204
+ return `${size} ${unit}`;
205
+ }
206
+ exports.bytesToString = bytesToString;
207
+ function filePathToVsixPath(originalFilePath) {
208
+ return `extension/${originalFilePath}`;
209
+ }
210
+ exports.filePathToVsixPath = filePathToVsixPath;
211
+ function vsixPathToFilePath(extensionFilePath) {
212
+ return extensionFilePath.startsWith('extension/') ? extensionFilePath.substring('extension/'.length) : extensionFilePath;
213
+ }
214
+ exports.vsixPathToFilePath = vsixPathToFilePath;
215
+ const FOLDER_SIZE_KEY = "/__FOlDER_SIZE__\\";
216
+ const FOLDER_FILES_TOTAL_KEY = "/__FOLDER_CHILDREN__\\";
217
+ const FILE_SIZE_WARNING_THRESHOLD = 0.85;
218
+ const FILE_SIZE_LARGE_THRESHOLD = 0.2;
219
+ async function generateFileStructureTree(rootFolder, filePaths, printLinesLimit = Number.MAX_VALUE) {
170
220
  const folderTree = {};
171
221
  const depthCounts = [];
172
222
  // Build a tree structure from the file paths
173
- filePaths.forEach(filePath => {
174
- const parts = filePath.split('/');
223
+ // Store the file size in the leaf node and the folder size in the folder node
224
+ // Store the number of children in the folder node
225
+ for (const filePath of filePaths) {
226
+ const parts = filePath.tree.split('/');
175
227
  let currentLevel = folderTree;
176
228
  parts.forEach((part, depth) => {
229
+ const isFile = depth === parts.length - 1;
230
+ // Create the node if it doesn't exist
177
231
  if (!currentLevel[part]) {
178
- currentLevel[part] = depth === parts.length - 1 ? null : {};
232
+ if (isFile) {
233
+ // The file size is stored in the leaf node,
234
+ currentLevel[part] = 0;
235
+ }
236
+ else {
237
+ // The folder size is stored in the folder node
238
+ currentLevel[part] = {};
239
+ currentLevel[part][FOLDER_SIZE_KEY] = 0;
240
+ currentLevel[part][FOLDER_FILES_TOTAL_KEY] = 0;
241
+ }
242
+ // Count the number of items at each depth
179
243
  if (depthCounts.length <= depth) {
180
244
  depthCounts.push(0);
181
245
  }
182
246
  depthCounts[depth]++;
183
247
  }
184
248
  currentLevel = currentLevel[part];
249
+ // Count the total number of children in the nested folders
250
+ if (!isFile) {
251
+ currentLevel[FOLDER_FILES_TOTAL_KEY]++;
252
+ }
185
253
  });
186
- });
187
- // Get max depth
254
+ }
255
+ ;
256
+ // Get max depth depending on the maximum number of lines allowed to print
188
257
  let currentDepth = 0;
189
- let countUpToCurrentDepth = depthCounts[0];
258
+ let countUpToCurrentDepth = depthCounts[0] + 1 /* root folder */;
190
259
  for (let i = 1; i < depthCounts.length; i++) {
191
- if (countUpToCurrentDepth + depthCounts[i] > maxPrint) {
260
+ if (countUpToCurrentDepth + depthCounts[i] > printLinesLimit) {
192
261
  break;
193
262
  }
194
263
  currentDepth++;
195
264
  countUpToCurrentDepth += depthCounts[i];
196
265
  }
197
266
  const maxDepth = currentDepth;
198
- let message = [];
199
- // Helper function to print the tree
200
- const printTree = (tree, depth, prefix) => {
267
+ // Get all file sizes
268
+ const fileSizes = await Promise.all(filePaths.map(async (filePath) => {
269
+ try {
270
+ const stats = await fs.promises.stat(filePath.origin);
271
+ return [stats.size, filePath.tree];
272
+ }
273
+ catch (error) {
274
+ return [0, filePath.origin];
275
+ }
276
+ }));
277
+ // Store all file sizes in the tree
278
+ let totalFileSizes = 0;
279
+ fileSizes.forEach(([size, filePath]) => {
280
+ totalFileSizes += size;
281
+ const parts = filePath.split('/');
282
+ let currentLevel = folderTree;
283
+ parts.forEach(part => {
284
+ if (typeof currentLevel[part] === 'number') {
285
+ currentLevel[part] = size;
286
+ }
287
+ else if (currentLevel[part]) {
288
+ currentLevel[part][FOLDER_SIZE_KEY] += size;
289
+ }
290
+ currentLevel = currentLevel[part];
291
+ });
292
+ });
293
+ let output = [];
294
+ output.push(chalk_1.default.bold(rootFolder));
295
+ output.push(...createTreeOutput(folderTree, maxDepth, totalFileSizes));
296
+ for (const [size, filePath] of fileSizes) {
297
+ if (size > FILE_SIZE_WARNING_THRESHOLD * totalFileSizes) {
298
+ output.push(`\nThe file ${filePath} is ${chalk_1.default.red('large')} (${bytesToString(size)})`);
299
+ break;
300
+ }
301
+ }
302
+ return output;
303
+ }
304
+ exports.generateFileStructureTree = generateFileStructureTree;
305
+ function createTreeOutput(fileSystem, maxDepth, totalFileSizes) {
306
+ const getColorFromSize = (size) => {
307
+ if (size > FILE_SIZE_WARNING_THRESHOLD * totalFileSizes) {
308
+ return chalk_1.default.red;
309
+ }
310
+ else if (size > FILE_SIZE_LARGE_THRESHOLD * totalFileSizes) {
311
+ return chalk_1.default.yellow;
312
+ }
313
+ else {
314
+ return chalk_1.default.grey;
315
+ }
316
+ };
317
+ const createFileOutput = (prefix, fileName, fileSize) => {
318
+ let fileSizeColored = '';
319
+ if (fileSize > 0) {
320
+ const fileSizeString = `[${bytesToString(fileSize)}]`;
321
+ fileSizeColored = getColorFromSize(fileSize)(fileSizeString);
322
+ }
323
+ return `${prefix}${fileName} ${fileSizeColored}`;
324
+ };
325
+ const createFolderOutput = (prefix, filesCount, folderSize, folderName, depth) => {
326
+ if (depth < maxDepth) {
327
+ // Max depth is not reached, print only the folder
328
+ // as children will be printed
329
+ return prefix + chalk_1.default.bold(`${folderName}/`);
330
+ }
331
+ // Max depth is reached, print the folder name and additional metadata
332
+ // as children will not be printed
333
+ const folderSizeString = bytesToString(folderSize);
334
+ const folder = chalk_1.default.bold(`${folderName}/`);
335
+ const numFilesString = chalk_1.default.green(`(${filesCount} ${filesCount === 1 ? 'file' : 'files'})`);
336
+ const folderSizeColored = getColorFromSize(folderSize)(`[${folderSizeString}]`);
337
+ return `${prefix}${folder} ${numFilesString} ${folderSizeColored}`;
338
+ };
339
+ const createTreeLayerOutput = (tree, depth, prefix, path) => {
201
340
  // Print all files before folders
202
- const sortedFolderKeys = Object.keys(tree).filter(key => tree[key] !== null).sort();
203
- const sortedFileKeys = Object.keys(tree).filter(key => tree[key] === null).sort();
204
- const sortedKeys = [...sortedFileKeys, ...sortedFolderKeys];
341
+ const sortedFolderKeys = Object.keys(tree).filter(key => typeof tree[key] !== 'number').sort();
342
+ const sortedFileKeys = Object.keys(tree).filter(key => typeof tree[key] === 'number').sort();
343
+ const sortedKeys = [...sortedFileKeys, ...sortedFolderKeys].filter(key => key !== FOLDER_SIZE_KEY && key !== FOLDER_FILES_TOTAL_KEY);
344
+ const output = [];
205
345
  for (let i = 0; i < sortedKeys.length; i++) {
206
346
  const key = sortedKeys[i];
207
347
  const isLast = i === sortedKeys.length - 1;
208
348
  const localPrefix = prefix + (isLast ? '└─ ' : '├─ ');
209
349
  const childPrefix = prefix + (isLast ? ' ' : '│ ');
210
- if (tree[key] === null) {
350
+ if (typeof tree[key] === 'number') {
211
351
  // It's a file
212
- message.push(localPrefix + key);
352
+ output.push(createFileOutput(localPrefix, key, tree[key]));
213
353
  }
214
354
  else {
215
355
  // It's a folder
356
+ output.push(createFolderOutput(localPrefix, tree[key][FOLDER_FILES_TOTAL_KEY], tree[key][FOLDER_SIZE_KEY], key, depth));
216
357
  if (depth < maxDepth) {
217
- // maxdepth is not reached, print the folder and its children
218
- message.push(localPrefix + chalk_1.default.bold(`${key}/`));
219
- printTree(tree[key], depth + 1, childPrefix);
220
- }
221
- else {
222
- // max depth is reached, print the folder but not its children
223
- const filesCount = countFiles(tree[key]);
224
- message.push(localPrefix + chalk_1.default.bold(`${key}/`) + chalk_1.default.green(` (${filesCount} ${filesCount === 1 ? 'file' : 'files'})`));
358
+ output.push(...createTreeLayerOutput(tree[key], depth + 1, childPrefix, path + key + '/'));
225
359
  }
226
360
  }
227
361
  }
362
+ return output;
228
363
  };
229
- // Helper function to count the number of files in a tree
230
- const countFiles = (tree) => {
231
- let filesCount = 0;
232
- for (const key in tree) {
233
- if (tree[key] === null) {
234
- filesCount++;
235
- }
236
- else {
237
- filesCount += countFiles(tree[key]);
238
- }
239
- }
240
- return filesCount;
241
- };
242
- message.push(chalk_1.default.bold(rootFolder));
243
- printTree(folderTree, 0, '');
244
- return message;
364
+ return createTreeLayerOutput(fileSystem, 0, '', '');
245
365
  }
246
- exports.generateFileStructureTree = generateFileStructureTree;
247
366
  //# sourceMappingURL=util.js.map
package/out/zip.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readVSIXPackage = exports.readZip = void 0;
4
4
  const yauzl_1 = require("yauzl");
5
5
  const xml_1 = require("./xml");
6
+ const util_1 = require("./util");
6
7
  async function bufferStream(stream) {
7
8
  return await new Promise((c, e) => {
8
9
  const buffers = [];
@@ -40,7 +41,7 @@ async function readZip(packagePath, filter) {
40
41
  exports.readZip = readZip;
41
42
  async function readVSIXPackage(packagePath) {
42
43
  const map = await readZip(packagePath, name => /^extension\/package\.json$|^extension\.vsixmanifest$/i.test(name));
43
- const rawManifest = map.get('extension/package.json');
44
+ const rawManifest = map.get((0, util_1.filePathToVsixPath)('package.json'));
44
45
  if (!rawManifest) {
45
46
  throw new Error('Manifest not found');
46
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vscode/vsce",
3
- "version": "2.30.0",
3
+ "version": "2.30.1-1",
4
4
  "description": "VS Code Extensions Manager",
5
5
  "repository": {
6
6
  "type": "git",