@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 +2 -0
- package/out/main.js +8 -3
- package/out/package.js +71 -38
- package/out/util.js +161 -42
- package/out/zip.js +2 -1
- package/package.json +1 -1
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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()] =
|
|
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="
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
1397
|
-
|
|
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.
|
|
1413
|
+
* Lists the files included in the extension's package.
|
|
1423
1414
|
*/
|
|
1424
1415
|
async function ls(options = {}) {
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
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
|
|
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 = '
|
|
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
|
-
|
|
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
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
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 += `
|
|
1450
|
-
message +=
|
|
1451
|
-
message +=
|
|
1452
|
-
|
|
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 =>
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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] >
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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] !==
|
|
203
|
-
const sortedFileKeys = Object.keys(tree).filter(key => tree[key] ===
|
|
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] ===
|
|
350
|
+
if (typeof tree[key] === 'number') {
|
|
211
351
|
// It's a file
|
|
212
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
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
|
}
|