Skip to content

Commit 5bba62e

Browse files
author
ekatek
committed
display exports for packages in ‘meteor show’
Contains: - method to aggregate exports for a package in packageSource (exports are per-architecture). - get this data from packageSource in PackageQuery for ‘meteor show’. Don’t store it in the local catalog — while it is not a particularly expensive operation, it is still more expensive than a simple lookup. We really do care about minimizing any sort of computation when we are initializing packages, since we want the tool to be fast. - display the data in ‘meteor show’. It makes sense to line wrap this with the ‘Exports:’ label as a bulletPoint (just look at the test to see an example where this improves user experience). Since we are doing that, we might as well use that bulletPoint functionality on the other labels as well. - There is also a test. Run ‘meteor self-test show’ to test, or run ‘meteor show’ on a local package with exports. The Troposphere counterpoint to this is: meteor/troposphere#5
1 parent a66bb6b commit 5bba62e

File tree

6 files changed

+338
-78
lines changed

6 files changed

+338
-78
lines changed

tools/commands-packages-query.js

+195-31
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var main = require('./main.js');
1212
var packageVersionParser = require('./package-version-parser.js');
1313
var projectContextModule = require('./project-context.js');
1414
var utils = require('./utils.js');
15+
var compiler = require('./compiler.js');
1516

1617
// We want these queries to be relatively fast, so we will only refresh the
1718
// catalog if it is > 15 minutes old
@@ -197,6 +198,61 @@ var itemNotFound = function (item) {
197198
return 1;
198199
};
199200

201+
// This class stores exports from a given package.
202+
//
203+
// Stores exports for a given package and returns them to the caller in a given
204+
// format. Takes in the raw exports from the package.
205+
var PkgExports = function (pkgExports) {
206+
var self = this;
207+
// Process and save the export data.
208+
self.data = _.map(pkgExports, function (exp) {
209+
var arches = exp.architectures;
210+
// Replace 'os' (what we store) with 'server' (what you would put in a
211+
// package.js file). That's more user friendly, and avoids confusing this
212+
// with different OS arches used in binary packages.
213+
if ( _.indexOf(arches, "os") !== -1) {
214+
arches = _.without(arches, "os");
215+
arches.push("server");
216+
}
217+
// Sort architectures alphabetically.
218+
arches.sort();
219+
return { name: exp.name, architectures: arches };
220+
});
221+
// Sort exports alphabetically by name.
222+
self.data = _.sortBy(self.data, "name");
223+
};
224+
225+
_.extend(PkgExports.prototype, {
226+
// Returns true if this class does not contain any exports.
227+
isEmpty : function () {
228+
var self = this;
229+
return _.isEmpty(self.data);
230+
},
231+
// Get exports as a raw object.
232+
getObject : function () {
233+
var self = this;
234+
return self.data;
235+
},
236+
// Convert package exports into a pretty, Console non-wrappable string. If an
237+
// export is only declared for certain architectures, mentions those
238+
// architectures in a user-friendly format.
239+
getConsoleStr: function () {
240+
var self = this;
241+
var strExports = _.map(self.data, function (exp) {
242+
// If this export is valid for all architectures, don't specify
243+
// architectures here.
244+
if (exp.architectures.length === compiler.ALL_ARCHES.length)
245+
return exp.name;
246+
247+
// Don't split descriptions of individual pkgExports between lines.
248+
return Console.noWrap(
249+
exp.name + " (" + exp.architectures.join(", ") + ")");
250+
});
251+
return strExports.join(", ");
252+
}
253+
});
254+
255+
200256
// The two classes below collect and print relevant information about Meteor
201257
// packages and Meteor releases, respectively. Specifically, they query the
202258
// official catalog and, if applicable, relevant local sources. They also handle
@@ -304,14 +360,10 @@ _.extend(PackageQuery.prototype, {
304360
// If we are asking for an EJSON-style output, we will only print out the
305361
// relevant fields.
306362
if (options.ejson) {
307-
var versionFields = [
308-
"name", "version", "description", "summary", "git", "dependencies",
309-
"publishedBy", "publishedOn", "installed", "local", "OSarchitectures"
310-
];
311-
var packageFields =
312-
[ "name", "homepage", "maintainers", "versions", "totalVersions" ];
313-
var fields = self.data.version ? versionFields : packageFields;
314-
Console.rawInfo(formatEJSON(_.pick(self.data, fields)));
363+
Console.rawInfo(convertToEJSON(
364+
self.data.version ?
365+
self._generateVersionObject(self.data) :
366+
self._generatePackageObject(self.data)));
315367
return;
316368
}
317369

@@ -396,24 +448,31 @@ _.extend(PackageQuery.prototype, {
396448
// The local version doesn't count against the version limit. Look up relevant
397449
// information about the local version.
398450
var localVersion = self.localCatalog.getLatestVersion(self.name);
451+
var local;
399452
if (localVersion) {
400-
var local = self._getLocalVersion(localVersion);
453+
local = self._getLocalVersion(localVersion);
401454
data["versions"].push(local);
402455
totalVersions++;
403456
}
404457

405-
// Record the total number of versions, including the ones we hid from the user.
458+
// Record the total number of versions, including the ones we hid from the
459+
// user.
406460
data["totalVersions"] = totalVersions;
407461

408462
// Some per-version information gets displayed with the rest of the package
409463
// information. We want to use the right version for that. (We don't want
410464
// to display data from unofficial or un-migrated versions just because they
411465
// are recent.)
412-
data["defaultVersion"] =
413-
local ||
414-
catalog.official.getLatestMainlineVersion(self.name) ||
415-
_.last(data.versions);
416-
466+
if (local) {
467+
data["defaultVersion"] = local;
468+
} else {
469+
var mainRecord = catalog.official.getLatestMainlineVersion(self.name);
470+
if (mainRecord) {
471+
data["defaultVersion"] = self._getOfficialVersion(mainRecord);
472+
} else {
473+
data["defaultVersion"] = _.last(data.versions);
474+
}
475+
}
417476
return data;
418477
},
419478
// Takes in a version record from the official catalog and looks up extra
@@ -448,9 +507,13 @@ _.extend(PackageQuery.prototype, {
448507
publishedBy:
449508
versionRecord.publishedBy && versionRecord.publishedBy.username,
450509
publishedOn: new Date(versionRecord.published),
451-
git: versionRecord.git
510+
git: versionRecord.git,
511+
exports: versionRecord.exports
452512
};
453513

514+
// Get the export data, if the record has any.
515+
data["exports"] = new PkgExports(versionRecord.exports);
516+
454517
// Processing and formatting architectures takes time, so we don't want to
455518
// do this if we don't have to.
456519
if (self.showArchitecturesOS) {
@@ -524,6 +587,9 @@ _.extend(PackageQuery.prototype, {
524587
var packageSource = self.localCatalog.getPackageSource(self.name);
525588
data["directory"] = packageSource.sourceRoot;
526589

590+
// Get the exports.
591+
data["exports"] = new PkgExports(packageSource.getExports());
592+
527593
// If the version was not explicitly set by the user, the catalog backfills
528594
// a placeholder version for the constraint solver. We don't want to show
529595
// that version to the user.
@@ -538,8 +604,9 @@ _.extend(PackageQuery.prototype, {
538604

539605
return data;
540606
},
541-
// Displays version information from this PackageQuery to the terminal in a human-friendly
542-
// format. Takes in an object that contains some, but not all, of the following keys:
607+
// Displays version information from this PackageQuery to the terminal in a
608+
// human-friendly format. Takes in an object that contains some, but not all,
609+
// of the following keys:
543610
//
544611
// - name: (mandatory) package Name
545612
// - version: (mandatory) package version
@@ -561,21 +628,34 @@ _.extend(PackageQuery.prototype, {
561628
// - weak: true if this is a weak dependency.
562629
_displayVersion: function (data) {
563630
var self = this;
564-
Console.info("Package:", data.name);
565-
Console.info("Version:", data.version);
631+
Console.info(
632+
data.name,
633+
Console.options({ bulletPoint: "Package: " }));
634+
Console.info(
635+
data.version,
636+
Console.options({ bulletPoint: "Version: " }));
566637
if (data.summary) {
567-
Console.info("Summary:", data.summary);
638+
Console.info(
639+
data.summary,
640+
Console.options({ bulletPoint: "Summary: " }));
568641
}
569642
if (data.publishedBy) {
570643
var publisher = data.publishedBy;
571644
var pubDate = utils.longformDate(data.publishedOn);
572645
Console.info("Published by", publisher, "on", pubDate);
573646
}
647+
if (data.directory) {
648+
Console.info("Directory: " + Console.path(data.directory));
649+
}
574650
if (data.git) {
575-
Console.info("Git:", Console.url(data.git));
651+
Console.info(
652+
Console.url(data.git),
653+
Console.options({ bulletPoint: "Git: " }));
576654
}
577-
if (data.directory) {
578-
Console.info("Directory:", Console.path(data.directory));
655+
if (data.exports && ! data.exports.isEmpty()) {
656+
Console.info(
657+
data["exports"].getConsoleStr(),
658+
Console.options({ bulletPoint: "Exports: " }));
579659
}
580660
Console.info();
581661

@@ -616,6 +696,38 @@ _.extend(PackageQuery.prototype, {
616696
"from outside the project.");
617697
}
618698
},
699+
// Returns a user-friendly object from this PackageQuery to the caller. Takes
700+
// in a data object with the same keys as _displayVersion.
701+
//
702+
// Returns an object with some of the following keys:
703+
// - name: String. Name of the package.
704+
// - version: String. Meteor version number.
705+
// - description: String. Longform description.
706+
// - summary: String. Short summary.
707+
// - git: String. Git URL.
708+
// - publishedBy: String. Username of the publisher.
709+
// - publishedOn: Date. Time of publication.
710+
// - local: Boolean. True if this is a local package.
711+
// - directory: source directory of this package.
712+
// - installed: Boolean. True if the isopack for this package has been
713+
// downloaded, or if the package is local.
714+
// - dependencies: Array of objects representing package dependencies, sorted
715+
// alphabetically by package name.
716+
// - OSarchitectures: Array of OS architectures on for which an isopack of
717+
// this package exists (server packages only).
718+
// - exports: Array of objects representing the package exports, sorted by
719+
// name of export.
720+
_generateVersionObject: function (data) {
721+
var versionFields = [
722+
"name", "version", "description", "summary", "git", "dependencies",
723+
"publishedBy", "publishedOn", "installed", "local", "OSarchitectures",
724+
"directory"
725+
];
726+
var processedData = data["exports"] ?
727+
{ exports: data["exports"].getObject() } : {};
728+
return _.extend(processedData, _.pick(data, versionFields));
729+
},
730+
619731
// Displays general package data from this PackageQuery to the terminal in a
620732
// human-friendly format. Takes in an object that contains some, but not
621733
// always all, of the following keys:
@@ -650,17 +762,28 @@ _.extend(PackageQuery.prototype, {
650762
var defaultVersion = data.defaultVersion;
651763

652764
// Every package has a name. Some packages have a homepage.
653-
Console.info("Package:", data.name);
765+
Console.info(data.name,
766+
Console.options({ bulletPoint: "Package: " }));
654767
if (data.homepage) {
655-
Console.info("Homepage:", Console.url(data.homepage));
768+
Console.info(Console.url(data.homepage),
769+
Console.options({ bulletPoint: "Homepage: " }));
770+
}
771+
// Local packages might not have any maintainers.
772+
if (! _.isEmpty(data.maintainers)) {
773+
Console.info(data.maintainers.join(", "),
774+
Console.options({ bulletPoint: "Maintainers: " }));
656775
}
657776
// Git is per-version, so we will print the latest one, if one exists.
658777
if (defaultVersion && defaultVersion.git) {
659-
Console.info("Git:", Console.url(defaultVersion.git));
778+
Console.info(Console.url(defaultVersion.git),
779+
Console.options({ bulletPoint: "Git: " }));
660780
}
661-
// Local packages might not have any maintainers.
662-
if (! _.isEmpty(data.maintainers)) {
663-
Console.info("Maintainers:", data.maintainers.join(", "));
781+
// Print the exports.
782+
if (defaultVersion && defaultVersion.exports &&
783+
! defaultVersion.exports.isEmpty()) {
784+
Console.info(
785+
defaultVersion["exports"].getConsoleStr(),
786+
Console.options({ bulletPoint: "Exports: " }));
664787
}
665788
Console.info();
666789

@@ -736,7 +859,48 @@ _.extend(PackageQuery.prototype, {
736859
"To see " + allVersionsPluralizer + ", run",
737860
Console.command("'meteor show --show-all " + self.name + "'") + ".");
738861
}
739-
}
862+
},
863+
// Returns a user-friendly object from this PackageQuery to the caller. Takes
864+
// in a data object with the same keys as _displayPackage.
865+
//
866+
// Returns an object with some of the following keys:
867+
// - name: String. Name of the package.
868+
// - homepage: String. URL of the package homepage.
869+
// - maintainers: Array of strings. Usernames of package maintainers.
870+
// - totalVersions: Number. Total number of versions that exist for this
871+
// package.
872+
// - versions: Array of objects, representing versions of this
873+
// package. Objects have the following keys:
874+
// - name: String. Name of the package.
875+
// - version: String. Meteor version number.
876+
// - description: String. Longform description.
877+
// - summary: String. Short summary.
878+
// - git: String. Git URL.
879+
// - publishedBy: String. Username of the publisher.
880+
// - publishedOn: Date. Time of publication.
881+
// - local: Boolean. True if this is a local package.
882+
// - directory: source directory of this package.
883+
// - installed: Boolean. True if the isopack for this package has been
884+
// downloaded, or if the package is local.
885+
// - exports: Array of objects representing the package exports, sorted by
886+
// name of export.
887+
_generatePackageObject: function (data) {
888+
var packageFields =
889+
[ "name", "homepage", "maintainers", "totalVersions" ];
890+
// Process the versions array. We only want some of the keys, and we want to
891+
// make sure to get the right exports object.
892+
var versions = _.map(data["versions"], function (version) {
893+
var versionFields = [
894+
"name", "version", "description", "summary", "git", "publishedBy",
895+
"publishedOn", "installed", "local", "directory"
896+
];
897+
var processedData = version["exports"] ?
898+
{ exports: version["exports"].getObject() } : {};
899+
return _.extend(processedData, _.pick(version, versionFields));
900+
});
901+
return _.extend({ versions: versions }, _.pick(data, packageFields));
902+
},
903+
740904
});
741905

742906
// This class looks up release-related information in the official catalog.

tools/compiler.js

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ var compiler = exports;
2828
// update BUILT_BY, though you will need to quit and rerun "meteor run".)
2929
compiler.BUILT_BY = 'meteor/15';
3030

31+
// This is a list of all possible architectures that a build can target. (Client
32+
// is expanded into 'web.browser' and 'web.cordova')
33+
compiler.ALL_ARCHES = [ "os", "web.browser", "web.cordova" ];
34+
3135
compiler.compile = function (packageSource, options) {
3236
buildmessage.assertInCapture();
3337

tools/package-client.js

+1
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ exports.publishPackage = function (options) {
565565
compilerVersion: compiler.BUILT_BY,
566566
containsPlugins: packageSource.containsPlugins(),
567567
debugOnly: packageSource.debugOnly,
568+
exports: packageSource.getExports(),
568569
releaseName: release.current.name,
569570
dependencies: packageDeps
570571
};

0 commit comments

Comments
 (0)