diff --git a/History.md b/History.md
index ee30411c1dc..7707f66f220 100644
--- a/History.md
+++ b/History.md
@@ -1,5 +1,22 @@
## v.NEXT
+* Applications may now specify client and server entry point modules in a
+ newly-supported `"meteor"` section of `package.json`:
+ ```js
+ "meteor": {
+ "mainModule": {
+ "client": "client/main.js",
+ "server": "server/main.js"
+ }
+ }
+ ```
+ When specified, these entry points override Meteor's default module
+ loading semantics, rendering `imports` directories unnecessary. If
+ `mainModule` is left unspecified for either client or server, the
+ default rules will apply for that architecture, as before.
+ [Feature #135](https://github.com/meteor/meteor-feature-requests/issues/135)
+ [PR #9690](https://github.com/meteor/meteor/pull/9690)
+
* The `reify` npm package has been updated to version 0.14.2.
* The `meteor-babel` npm package has been updated to version
diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js
index 39756afd124..a528c8bcbb3 100644
--- a/tools/isobuild/compiler-plugin.js
+++ b/tools/isobuild/compiler-plugin.js
@@ -591,7 +591,7 @@ class ResourceSlot {
return fileOptions && fileOptions[name];
}
- _isLazy(options) {
+ _isLazy(options, isJavaScript) {
let lazy = this._getOption("lazy", options);
if (typeof lazy === "boolean") {
@@ -607,18 +607,36 @@ class ResourceSlot {
return false;
}
- const splitPath = this.inputResource.path.split(files.pathSep);
- const isInImports = splitPath.indexOf("imports") >= 0;
+ const runningTests = global.testCommandMetadata &&
+ (global.testCommandMetadata.isTest ||
+ global.testCommandMetadata.isAppTest);
- if (global.testCommandMetadata &&
- (global.testCommandMetadata.isTest ||
- global.testCommandMetadata.isAppTest)) {
- // test files should always be included, if we're running app
- // tests.
- return isInImports && !isTestFilePath(this.inputResource.path);
- } else {
- return isInImports;
+ if (runningTests &&
+ isTestFilePath(this.inputResource.path)) {
+ // Test files are never lazy if we're running tests.
+ return false;
+ }
+
+ if (isJavaScript) {
+ // PackageSource#_inferFileOptions (in package-source.js) sets the
+ // mainModule option to false to indicate a meteor.mainModule was
+ // configured for this architecture, but this module was not it.
+ // It's important to wait until this point (ResourceSlot#_isLazy) to
+ // make the final call, because we can finally tell whether the
+ // output resource is JavaScript or not (non-JS resources are not
+ // affected by the meteor.mainModule option).
+ const mainModule = this._getOption("mainModule", options);
+ if (typeof mainModule === "boolean") {
+ return ! mainModule;
+ }
}
+
+ // In other words, the imports directory remains relevant for non-JS
+ // resources, and for JS resources in the absence of an explicit
+ // meteor.mainModule configuration in package.json.
+ const splitPath = this.inputResource.path.split(files.pathSep);
+ const isInImports = splitPath.indexOf("imports") >= 0;
+ return isInImports;
}
addStylesheet(options) {
@@ -637,7 +655,7 @@ class ResourceSlot {
targetPath,
servePath: self.packageSourceBatch.unibuild.pkg._getServePath(targetPath),
hash: sha1(data),
- lazy: this._isLazy(options),
+ lazy: this._isLazy(options, false),
};
if (useMeteorInstall && resource.lazy) {
@@ -711,7 +729,7 @@ class ResourceSlot {
sourceMap: options.sourceMap,
// intentionally preserve a possible `undefined` value for files
// in apps, rather than convert it into `false` via `!!`
- lazy: self._isLazy(options),
+ lazy: self._isLazy(options, true),
bare: !! self._getOption("bare", options),
mainModule: !! self._getOption("mainModule", options),
});
@@ -739,7 +757,7 @@ class ResourceSlot {
servePath: self.packageSourceBatch.unibuild.pkg._getServePath(
options.path),
hash: sha1(options.data),
- lazy: self._isLazy(options),
+ lazy: self._isLazy(options, false),
});
}
@@ -763,7 +781,7 @@ class ResourceSlot {
self.outputResources.push({
type: options.section,
data: Buffer.from(files.convertToStandardLineEndings(options.data), 'utf8'),
- lazy: self._isLazy(options),
+ lazy: self._isLazy(options, false),
});
}
diff --git a/tools/isobuild/package-api.js b/tools/isobuild/package-api.js
index 1bd236889a5..c0f58852d38 100644
--- a/tools/isobuild/package-api.js
+++ b/tools/isobuild/package-api.js
@@ -48,7 +48,7 @@ function toArchArray (arch) {
// 'client' -> 'web'
// 'server' -> 'os'
// '*' -> '*'
-function mapWhereToArch (where) {
+export function mapWhereToArch(where) {
if (where === 'server') {
return 'os';
} else if (where === 'client') {
diff --git a/tools/isobuild/package-source.js b/tools/isobuild/package-source.js
index 1fdad7561aa..ab41420d88c 100644
--- a/tools/isobuild/package-source.js
+++ b/tools/isobuild/package-source.js
@@ -837,7 +837,10 @@ _.extend(PackageSource.prototype, {
constraint: constraint.constraintString });
});
- var projectWatchSet = projectContext.getProjectWatchSet();
+ const projectWatchSet = projectContext.getProjectWatchSet();
+ const mainModulesByArch =
+ projectContext.meteorConfig.getMainModulesByArch();
+ projectWatchSet.merge(projectContext.meteorConfig.watchSet);
_.each(compiler.ALL_ARCHES, function (arch) {
// We don't need to build a Cordova SourceArch if there are no Cordova
@@ -847,6 +850,9 @@ _.extend(PackageSource.prototype, {
return;
}
+ const mainModule = projectContext.meteorConfig
+ .getMainModuleForArch(arch, mainModulesByArch);
+
// XXX what about /web.browser/* etc, these directories could also
// be for specific client targets.
@@ -867,20 +873,42 @@ _.extend(PackageSource.prototype, {
isApp: true,
};
+ // If this architecture has a mainModule defined in
+ // package.json, it's an error if _findSources doesn't find that
+ // module. If no mainModule is defined, anything goes.
+ let missingMainModule = !! mainModule;
+
+ const sources = self._findSources(findOptions).sort(
+ loadOrderSort(sourceProcessorSet, arch)
+ ).map(relPath => {
+ if (relPath === mainModule) {
+ missingMainModule = false;
+ }
+
+ const fileOptions = self._inferFileOptions(relPath, {
+ arch,
+ isApp: true,
+ mainModule,
+ });
+
+ return {
+ relPath,
+ fileOptions,
+ };
+ });
+
+ if (missingMainModule) {
+ buildmessage.error([
+ "Could not find mainModule for '" + arch + "' architecture: " + mainModule,
+ 'Check the "meteor" section of your package.json file?'
+ ].join("\n"));
+ }
+
+ const assets = self._findAssets(findOptions);
+
return {
- sources: self._findSources(findOptions).sort(
- loadOrderSort(sourceProcessorSet, arch)
- ).map(relPath => {
- return {
- relPath,
- fileOptions: self._inferFileOptions(relPath, {
- arch,
- isApp: true,
- }),
- };
- }),
-
- assets: self._findAssets(findOptions),
+ sources,
+ assets,
};
}
});
@@ -919,7 +947,11 @@ _.extend(PackageSource.prototype, {
}
}),
- _inferFileOptions(relPath, {arch, isApp}) {
+ _inferFileOptions(relPath, {
+ arch,
+ isApp,
+ mainModule,
+ }) {
const fileOptions = {};
const isTest = global.testCommandMetadata
&& global.testCommandMetadata.isTest;
@@ -974,6 +1006,17 @@ _.extend(PackageSource.prototype, {
}
}
+ if (isApp && mainModule) {
+ if (relPath === mainModule) {
+ fileOptions.lazy = false;
+ fileOptions.mainModule = true;
+ } else if (typeof fileOptions.lazy === "undefined") {
+ // Used in ResourceSlot#_isLazy (in compiler-plugin.js) to make a
+ // final determination of whether the file should be lazy.
+ fileOptions.mainModule = false;
+ }
+ }
+
return fileOptions;
},
diff --git a/tools/project-context.js b/tools/project-context.js
index 095ca9a83d0..5eb25b43fdc 100644
--- a/tools/project-context.js
+++ b/tools/project-context.js
@@ -17,6 +17,17 @@ var watch = require('./fs/watch.js');
var Profile = require('./tool-env/profile.js').Profile;
import { KNOWN_ISOBUILD_FEATURE_PACKAGES } from './isobuild/compiler.js';
+import {
+ optimisticReadJsonOrNull,
+ optimisticHashOrNull,
+} from "./fs/optimistic.js";
+
+import {
+ mapWhereToArch,
+} from "./isobuild/package-api.js";
+
+import Resolver from "./isobuild/resolver.js";
+
// The ProjectContext represents all the context associated with an app:
// metadata files in the `.meteor` directory, the choice of package versions
// used by it, etc. Any time you want to work with an app, create a
@@ -363,6 +374,13 @@ _.extend(ProjectContext.prototype, {
});
if (buildmessage.jobHasMessages())
return;
+
+ self.meteorConfig = new MeteorConfig({
+ appDirectory: self.projectDir,
+ });
+ if (buildmessage.jobHasMessages()) {
+ return;
+ }
});
self._completedStage = STAGE.READ_PROJECT_METADATA;
@@ -1580,3 +1598,100 @@ _.extend(exports.FinishedUpgraders.prototype, {
files.appendFile(self.filename, appendText);
}
});
+
+export class MeteorConfig {
+ constructor({
+ appDirectory,
+ }) {
+ this.appDirectory = appDirectory;
+ this.packageJsonPath = files.pathJoin(appDirectory, "package.json");
+ this.watchSet = new watch.WatchSet;
+ this._resolversByArch = Object.create(null);
+ }
+
+ _ensureInitialized() {
+ if (! _.has(this, "_config")) {
+ const json = optimisticReadJsonOrNull(this.packageJsonPath);
+ this._config = json && json.meteor || null;
+ this.watchSet.addFile(
+ this.packageJsonPath,
+ optimisticHashOrNull(this.packageJsonPath)
+ );
+ }
+
+ return this._config;
+ }
+
+ // General utility for querying the "meteor" section of package.json.
+ // TODO Implement an API for setting these values?
+ get(...keys) {
+ let config = this._ensureInitialized();
+ if (config) {
+ keys.every(key => {
+ if (config && _.has(config, key)) {
+ config = config[key];
+ return true;
+ }
+ });
+ return config;
+ }
+ }
+
+ // Call this first if you plan to call getMainModuleForArch multiple
+ // times, so that you can avoid repeating this work each time.
+ getMainModulesByArch(arch) {
+ const configMainModule = this.get("mainModule");
+ const mainModulesByArch = Object.create(null);
+
+ if (configMainModule) {
+ if (typeof configMainModule === "string") {
+ // If packageJson.meteor.mainModule is a string, use that string
+ // as the mainModule for all architectures.
+ mainModulesByArch["os"] = configMainModule;
+ mainModulesByArch["web"] = configMainModule;
+ } else if (typeof configMainModule === "object") {
+ // If packageJson.meteor.mainModule is an object, use its
+ // properties to select a mainModule for each architecture.
+ Object.keys(configMainModule).forEach(where => {
+ mainModulesByArch[mapWhereToArch(where)] = configMainModule[where];
+ });
+ }
+ }
+
+ return mainModulesByArch;
+ }
+
+ // Given an architecture like web.browser, get the best mainModule for
+ // that architecture. For example, if this.config.mainModule.client is
+ // defined, then because mapWhereToArch("client") === "web", and "web"
+ // matches web.browser, return this.config.mainModule.client.
+ getMainModuleForArch(
+ arch,
+ mainModulesByArch = this.getMainModulesByArch(),
+ ) {
+ const mainMatch = archinfo.mostSpecificMatch(
+ arch, Object.keys(mainModulesByArch));
+
+ if (mainMatch) {
+ if (! this._resolversByArch[arch]) {
+ this._resolversByArch[arch] = new Resolver({
+ sourceRoot: this.appDirectory,
+ targetArch: arch,
+ });
+ }
+
+ // Use a Resolver to allow the mainModule strings to omit .js or
+ // .json file extensions, and to enable resolving directories
+ // containing package.json or index.js files.
+ const res = this._resolversByArch[arch].resolve(
+ // Only relative paths are allowed (not top-level packages).
+ "./" + files.pathNormalize(mainModulesByArch[mainMatch]),
+ this.packageJsonPath
+ );
+
+ if (res && typeof res === "object") {
+ return files.pathRelative(this.appDirectory, res.path);
+ }
+ }
+ }
+}
diff --git a/tools/tests/app-config.js b/tools/tests/app-config.js
new file mode 100644
index 00000000000..d6acbd7e8e7
--- /dev/null
+++ b/tools/tests/app-config.js
@@ -0,0 +1,110 @@
+var selftest = require('../tool-testing/selftest.js');
+var Sandbox = selftest.Sandbox;
+
+selftest.define("mainModule", function () {
+ const s = new Sandbox();
+ s.createApp("app-config-mainModule", "app-config");
+ s.cd("app-config-mainModule");
+
+ const run = s.run(
+ "test",
+ "--full-app",
+ "--driver-package", "dispatch:mocha-phantomjs"
+ );
+
+ run.waitSecs(60);
+ run.match("App running at");
+
+ function check(mainModule) {
+ const json = JSON.parse(s.read("package.json"));
+
+ let shouldWrite = true;
+ if (typeof mainModule === "undefined") {
+ if ("meteor" in json) {
+ delete json.meteor;
+ } else {
+ shouldWrite = false;
+ }
+ } else {
+ json.meteor = { mainModule };
+ }
+
+ if (shouldWrite) {
+ s.write("package.json", JSON.stringify(json, null, 2) + "\n");
+ }
+
+ run.waitSecs(10);
+ run.match("SERVER FAILURES: 0");
+ run.match("CLIENT FAILURES: 0");
+ }
+
+ check();
+
+ check(null);
+
+ check("oyez");
+
+ check({});
+
+ check({
+ client: "a",
+ os: "bc",
+ });
+
+ check({
+ client: "b.js",
+ server: "abc",
+ });
+
+ check({
+ client: "./c",
+ server: "/ac",
+ });
+
+ check({
+ server: "./a",
+ web: "ab",
+ });
+
+ check({
+ client: "ac.js",
+ os: "a",
+ });
+
+ check({
+ web: "bc",
+ server: "a",
+ });
+
+ check({
+ server: "b.js",
+ client: "abc",
+ });
+
+ check({
+ client: "abc",
+ });
+
+ check({
+ server: "b.js",
+ });
+
+ check({
+ client: "/ac",
+ server: "./c",
+ });
+
+ check({
+ os: "ab",
+ client: "./a",
+ });
+
+ check({
+ server: "ac.js",
+ web: "a",
+ });
+
+ check(null);
+
+ check();
+});
diff --git a/tools/tests/apps/app-config/.gitignore b/tools/tests/apps/app-config/.gitignore
new file mode 100644
index 00000000000..c2658d7d1b3
--- /dev/null
+++ b/tools/tests/apps/app-config/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/tools/tests/apps/app-config/.meteor/.finished-upgraders b/tools/tests/apps/app-config/.meteor/.finished-upgraders
new file mode 100644
index 00000000000..910574ce2df
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.finished-upgraders
@@ -0,0 +1,17 @@
+# This file contains information which helps Meteor properly upgrade your
+# app when you run 'meteor update'. You should check it into version control
+# with your project.
+
+notices-for-0.9.0
+notices-for-0.9.1
+0.9.4-platform-file
+notices-for-facebook-graph-api-2
+1.2.0-standard-minifiers-package
+1.2.0-meteor-platform-split
+1.2.0-cordova-changes
+1.2.0-breaking-changes
+1.3.0-split-minifiers-package
+1.4.0-remove-old-dev-bundle-link
+1.4.1-add-shell-server-package
+1.4.3-split-account-service-packages
+1.5-add-dynamic-import-package
diff --git a/tools/tests/apps/app-config/.meteor/.gitignore b/tools/tests/apps/app-config/.meteor/.gitignore
new file mode 100644
index 00000000000..40830374235
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.gitignore
@@ -0,0 +1 @@
+local
diff --git a/tools/tests/apps/app-config/.meteor/.id b/tools/tests/apps/app-config/.meteor/.id
new file mode 100644
index 00000000000..a7468fe68d0
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.id
@@ -0,0 +1,7 @@
+# This file contains a token that is unique to your project.
+# Check it into your repository along with the rest of this directory.
+# It can be used for purposes such as:
+# - ensuring you don't accidentally deploy one app on top of another
+# - providing package authors with aggregated statistics
+
+h9uim8gzzdn7.vu1xo1jmqcme
diff --git a/tools/tests/apps/app-config/.meteor/packages b/tools/tests/apps/app-config/.meteor/packages
new file mode 100644
index 00000000000..46098f7d48b
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/packages
@@ -0,0 +1,14 @@
+# Meteor packages used by this project, one per line.
+# Check this file (and the other files in this directory) into your repository.
+#
+# 'meteor add' and 'meteor remove' will edit this file for you,
+# but you can also edit it by hand.
+
+meteor-base # Packages every Meteor app needs to have
+static-html # Define static page content in .html files
+standard-minifier-css # CSS minifier run for production mode
+standard-minifier-js # JS minifier run for production mode
+es5-shim # ECMAScript 5 compatibility for older browsers
+ecmascript # Enable ECMAScript2015+ syntax in app code
+shell-server # Server-side component of the `meteor shell` command
+less # Support .less files for defining CSS styles
diff --git a/tools/tests/apps/app-config/.meteor/platforms b/tools/tests/apps/app-config/.meteor/platforms
new file mode 100644
index 00000000000..efeba1b50c7
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/platforms
@@ -0,0 +1,2 @@
+server
+browser
diff --git a/tools/tests/apps/app-config/.meteor/release b/tools/tests/apps/app-config/.meteor/release
new file mode 100644
index 00000000000..621e94f0ec9
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/release
@@ -0,0 +1 @@
+none
diff --git a/tools/tests/apps/app-config/.meteor/versions b/tools/tests/apps/app-config/.meteor/versions
new file mode 100644
index 00000000000..8b323e2c759
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/versions
@@ -0,0 +1,66 @@
+allow-deny@1.1.0
+autoupdate@1.4.0
+babel-compiler@7.0.5
+babel-runtime@1.2.2
+base64@1.0.11
+binary-heap@1.0.10
+blaze-tools@1.0.10
+boilerplate-generator@1.5.0
+caching-compiler@1.1.11
+caching-html-compiler@1.1.2
+callback-hook@1.1.0
+check@1.3.0
+ddp@1.4.0
+ddp-client@2.3.1
+ddp-common@1.4.0
+ddp-server@2.1.2
+diff-sequence@1.1.0
+dispatch:mocha-browser@0.0.4
+dynamic-import@0.3.0
+ecmascript@0.10.5
+ecmascript-runtime@0.5.0
+ecmascript-runtime-client@0.6.2
+ecmascript-runtime-server@0.5.0
+ejson@1.1.0
+es5-shim@4.7.3
+geojson-utils@1.0.10
+hot-code-push@1.0.4
+html-tools@1.0.11
+htmljs@1.0.11
+http@1.4.0
+id-map@1.1.0
+less@2.7.12
+livedata@1.0.18
+logging@1.1.19
+meteor@1.8.3
+meteor-base@1.3.0
+minifier-css@1.3.1
+minifier-js@2.3.3
+minimongo@1.4.3
+modules@0.11.5
+modules-runtime@0.9.2
+mongo@1.4.4
+mongo-dev-server@1.1.0
+mongo-id@1.0.6
+npm-mongo@2.2.33
+ordered-dict@1.1.0
+practicalmeteor:mocha-core@1.0.1
+promise@0.10.2
+random@1.1.0
+reload@1.2.0
+retry@1.1.0
+routepolicy@1.0.12
+server-render@0.3.0
+shell-server@0.3.1
+shim-common@0.1.0
+socket-stream-client@0.1.0
+spacebars-compiler@1.1.3
+standard-minifier-css@1.4.1
+standard-minifier-js@2.3.2
+static-html@1.2.2
+templating-tools@1.1.2
+tracker@1.2.0
+underscore@1.0.10
+url@1.2.0
+webapp@1.5.0
+webapp-hashing@1.0.9
diff --git a/tools/tests/apps/app-config/a.js b/tools/tests/apps/app-config/a.js
new file mode 100644
index 00000000000..508c569e069
--- /dev/null
+++ b/tools/tests/apps/app-config/a.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/ab.js b/tools/tests/apps/app-config/ab.js
new file mode 100644
index 00000000000..a4c5b255682
--- /dev/null
+++ b/tools/tests/apps/app-config/ab.js
@@ -0,0 +1,2 @@
+import "./a.js";
+import "./b.js";
diff --git a/tools/tests/apps/app-config/abc.js b/tools/tests/apps/app-config/abc.js
new file mode 100644
index 00000000000..07d1effb8f8
--- /dev/null
+++ b/tools/tests/apps/app-config/abc.js
@@ -0,0 +1,2 @@
+import "./ab.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/ac.js b/tools/tests/apps/app-config/ac.js
new file mode 100644
index 00000000000..7dc139edf8e
--- /dev/null
+++ b/tools/tests/apps/app-config/ac.js
@@ -0,0 +1,2 @@
+import "./a.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/b.js b/tools/tests/apps/app-config/b.js
new file mode 100644
index 00000000000..508c569e069
--- /dev/null
+++ b/tools/tests/apps/app-config/b.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/bc.js b/tools/tests/apps/app-config/bc.js
new file mode 100644
index 00000000000..402dc1115af
--- /dev/null
+++ b/tools/tests/apps/app-config/bc.js
@@ -0,0 +1,2 @@
+import "./b.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/c.js b/tools/tests/apps/app-config/c.js
new file mode 100644
index 00000000000..508c569e069
--- /dev/null
+++ b/tools/tests/apps/app-config/c.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/client/main.css b/tools/tests/apps/app-config/client/main.css
new file mode 100644
index 00000000000..5b5a91897d9
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.css
@@ -0,0 +1,3 @@
+body {
+ font-weight: 700;
+}
diff --git a/tools/tests/apps/app-config/client/main.html b/tools/tests/apps/app-config/client/main.html
new file mode 100644
index 00000000000..c0e549e6376
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.html
@@ -0,0 +1,14 @@
+
+ app-config
+
+
+
+ Welcome to Meteor!
+ Learn Meteor!
+
+
diff --git a/tools/tests/apps/app-config/client/main.js b/tools/tests/apps/app-config/client/main.js
new file mode 100644
index 00000000000..bebaa30ed8c
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.js
@@ -0,0 +1,2 @@
+import { report } from "../tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/client/main.less b/tools/tests/apps/app-config/client/main.less
new file mode 100644
index 00000000000..579899c6d3a
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.less
@@ -0,0 +1,3 @@
+body {
+ background: #add8e6;
+}
diff --git a/tools/tests/apps/app-config/package-lock.json b/tools/tests/apps/app-config/package-lock.json
new file mode 100644
index 00000000000..82fe1359d14
--- /dev/null
+++ b/tools/tests/apps/app-config/package-lock.json
@@ -0,0 +1,683 @@
+{
+ "name": "app-config",
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.0.0-beta.40",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.40.tgz",
+ "integrity": "sha512-vIM68NUCWauZJTFoVUG1lggva1I8FLB9zFKwWG7Xjin4FkHpEKJv2y4x1DGVPVt93S5/zHSBj1bXYEuxOkFGzg==",
+ "requires": {
+ "core-js": "2.5.3",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "core-js": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
+ "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4="
+ },
+ "meteor-node-stubs": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.2.tgz",
+ "integrity": "sha512-l93SS/HutbqBRJODO2m7hup8cYI2acF5bB39+ZvP2BX8HMmCSCXeFH7v0sr4hD7zrVvHQA5UqS0pcDYKn0VM6g==",
+ "requires": {
+ "assert": "1.4.1",
+ "browserify-zlib": "0.1.4",
+ "buffer": "4.9.1",
+ "console-browserify": "1.1.0",
+ "constants-browserify": "1.0.0",
+ "crypto-browserify": "3.11.1",
+ "domain-browser": "1.1.7",
+ "events": "1.1.1",
+ "http-browserify": "1.7.0",
+ "https-browserify": "0.0.1",
+ "os-browserify": "0.2.1",
+ "path-browserify": "0.0.0",
+ "process": "0.11.10",
+ "punycode": "1.4.1",
+ "querystring-es3": "0.2.1",
+ "readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
+ "stream-browserify": "2.0.1",
+ "string_decoder": "1.0.3",
+ "timers-browserify": "1.4.2",
+ "tty-browserify": "0.0.0",
+ "url": "0.11.0",
+ "util": "0.10.3",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "Base64": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
+ "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
+ },
+ "asn1.js": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz",
+ "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "requires": {
+ "util": "0.10.3"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.0.tgz",
+ "integrity": "sha512-W2bIMLYoZ9oow7TyePpMJk9l9LY7O3R61a/68bVCDOtnJynnwe3ZeW2IzzSkrQnPKNdJrxVDn3ALZNisSBwb7g==",
+ "requires": {
+ "buffer-xor": "1.0.3",
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "requires": {
+ "browserify-aes": "1.1.0",
+ "browserify-des": "1.0.0",
+ "evp_bytestokey": "1.0.3"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "des.js": "1.0.0",
+ "inherits": "2.0.1"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "randombytes": "2.0.5"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "elliptic": "6.4.0",
+ "inherits": "2.0.1",
+ "parse-asn1": "5.1.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+ "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+ "requires": {
+ "pako": "0.2.9"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "requires": {
+ "base64-js": "1.2.1",
+ "ieee754": "1.1.8",
+ "isarray": "1.0.0"
+ }
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "requires": {
+ "date-now": "0.1.4"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "elliptic": "6.4.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "inherits": "2.0.1",
+ "ripemd160": "2.0.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "inherits": "2.0.1",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.11.1",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz",
+ "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==",
+ "requires": {
+ "browserify-cipher": "1.0.0",
+ "browserify-sign": "4.0.4",
+ "create-ecdh": "4.0.0",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "diffie-hellman": "5.0.2",
+ "inherits": "2.0.1",
+ "pbkdf2": "3.0.14",
+ "public-encrypt": "4.0.0",
+ "randombytes": "2.0.5"
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "requires": {
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "miller-rabin": "4.0.1",
+ "randombytes": "2.0.5"
+ }
+ },
+ "domain-browser": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw="
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0",
+ "hash.js": "1.1.3",
+ "hmac-drbg": "1.0.1",
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "1.3.4",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.1",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+ "requires": {
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "1.1.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "http-browserify": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
+ "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
+ "requires": {
+ "Base64": "0.2.1",
+ "inherits": "2.0.1"
+ }
+ },
+ "https-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz",
+ "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI="
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.1"
+ },
+ "dependencies": {
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-browserify": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz",
+ "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8="
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "requires": {
+ "asn1.js": "4.9.1",
+ "browserify-aes": "1.1.0",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "pbkdf2": "3.0.14"
+ }
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "pbkdf2": {
+ "version": "3.0.14",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+ "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+ "requires": {
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "parse-asn1": "5.1.0",
+ "randombytes": "2.0.5"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "randombytes": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
+ "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "readable-stream": {
+ "version": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
+ "requires": {
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "requires": {
+ "hash-base": "2.0.2",
+ "inherits": "2.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "sha.js": {
+ "version": "2.4.9",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
+ "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "requires": {
+ "inherits": "2.0.1",
+ "readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+ "requires": {
+ "process": "0.11.10"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+}
diff --git a/tools/tests/apps/app-config/package.json b/tools/tests/apps/app-config/package.json
new file mode 100644
index 00000000000..eeb7e1bb759
--- /dev/null
+++ b/tools/tests/apps/app-config/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "app-config",
+ "private": true,
+ "scripts": {
+ "start": "meteor run"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.0.0-beta.36",
+ "meteor-node-stubs": "^0.3.2"
+ }
+}
diff --git a/tools/tests/apps/app-config/server/main.js b/tools/tests/apps/app-config/server/main.js
new file mode 100644
index 00000000000..bebaa30ed8c
--- /dev/null
+++ b/tools/tests/apps/app-config/server/main.js
@@ -0,0 +1,2 @@
+import { report } from "../tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/tests.js b/tools/tests/apps/app-config/tests.js
new file mode 100644
index 00000000000..0882961844f
--- /dev/null
+++ b/tools/tests/apps/app-config/tests.js
@@ -0,0 +1,97 @@
+import assert from "assert";
+
+const ids = [];
+export function report(id) {
+ ids.push(id);
+}
+
+const startupPromise = new Promise(resolve => {
+ Meteor.startup(resolve);
+});
+
+describe("meteor.mainModule", () => {
+ // These tests test the consequences of having various meteor.mainModule
+ // configurations in package.json.
+ const config = require("./package.json").meteor;
+
+ if (Meteor.isClient) {
+ it("always loads static HTML", () => {
+ assert.strictEqual(
+ document.getElementsByTagName("h1").item(0).innerText,
+ "Welcome to Meteor!"
+ );
+
+ assert.strictEqual(
+ document.getElementsByTagName("h2").item(0).innerText,
+ "Learn Meteor!"
+ );
+
+ const listItems = document
+ .getElementById("meteor-reading-list")
+ .getElementsByTagName("li");
+ assert.strictEqual(listItems.length, 4);
+ });
+
+ it("always loads CSS resources", () => {
+ let { fontWeight } = getComputedStyle(document.body);
+ assert(fontWeight === "bold" ||
+ fontWeight === "700",
+ fontWeight);
+ });
+
+ it("always loads LESS styles", () => {
+ assert.strictEqual(
+ getComputedStyle(document.body)["background-color"],
+ "rgb(173, 216, 230)" // #add8e6
+ );
+ });
+ }
+
+ it("loads the right files", async () => {
+ await startupPromise;
+
+ function checkNoMainModule() {
+ assert.deepEqual(ids, [
+ "/a.js",
+ "/b.js",
+ "/c.js",
+ Meteor.isClient
+ ? "/client/main.js"
+ : "/server/main.js"
+ ]);
+ }
+
+ if (! config ||
+ ! config.mainModule) {
+ return checkNoMainModule();
+ }
+
+ let mainId;
+
+ if (Meteor.isClient) {
+ mainId =
+ config.mainModule.client ||
+ config.mainModule.web;
+ console.log("client config:", config);
+ } else if (Meteor.isServer) {
+ mainId =
+ config.mainModule.server ||
+ config.mainModule.os;
+ console.log("server config:", config);
+ }
+
+ if (! mainId) {
+ return checkNoMainModule();
+ }
+
+ const absId = require.resolve("./" + mainId);
+ const basename = absId.split("/").pop();
+ const name = basename.split(".", 1)[0];
+ const chars = name.split("");
+
+ assert.deepEqual(
+ ids,
+ chars.map(ch => "/" + ch + ".js"),
+ );
+ });
+});