diff --git a/History.md b/History.md index 60ce0c0116..c59b1414ee 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,53 @@ +## vNEXT, unreleased + +### Breaking changes + +N/A + +### Migration steps + +N/A + +### Changes + +* `--apollo` skeleton was missing client cache setup [PR #11146](https://github.com/meteor/meteor/pull/11146) + +## v1.11, 2020-08-18 + +### Breaking changes + +* `email` package dependencies have been update and package version has been bumped to 2.0.0 + There is a potential breaking change as the underlying package started to use `dns.resolve()` + instead of `dns.lookup()` which might be breaking on some environments. + See [nodemailer changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) for more information. + +### Migration steps + +N/A + +### Changes + +* `meteor create --apollo` is now available thanks to [@StorytellerCZ](https://github.com/StorytellerCZ). PR [#11119](https://github.com/meteor/meteor/pull/11119) + +* `meteor create --vue` is now available thanks to [@chris-visser](https://github.com/chris-visser). PR [#11086](https://github.com/meteor/meteor/pull/11086) + +* `--cache-build` option is now available on `meteor deploy` command and you can use it safely all the time if you are using a Git repository to run your deploy. This is helpful if your upload is failing then you can retry just the upload and also if you deploy the same bundle to multiple environments. [Read more](https://galaxy-guide.meteor.com/deploy-guide.html#cache-build). + +* Multiple optimizations in build performance, many of them for Windows thanks to [@zodern](https://github.com/zodern). PRs [#10838](https://github.com/meteor/meteor/pull/10838), [#11114](https://github.com/meteor/meteor/pull/11114), [#11115](https://github.com/meteor/meteor/pull/11115), [#11102](https://github.com/meteor/meteor/pull/11102), [#10839](https://github.com/meteor/meteor/pull/10839) + +* Fixes error when removing cordova plugin that depends on cli variables. PR [#10976](https://github.com/meteor/meteor/pull/11052) + +* `email` package now exposes `hookSend` that runs before emails are send. + +* Node.js has been updated to version + [12.18.3](https://nodejs.org/en/blog/release/v12.18.3/) + +* Updated npm to version 6.14.5 + +* `mongodb` driver npm dependency has been updated to 3.6.0 + +* The version of MongoDB used by Meteor in development has been updated + from 4.2.5 to 4.2.8 ## v1.10.2, 2020-04-21 diff --git a/Roadmap.md b/Roadmap.md index 919cde23aa..b71a61cce4 100644 --- a/Roadmap.md +++ b/Roadmap.md @@ -1,6 +1,6 @@ # Meteor Roadmap -**Up to date as of May 21, 2020** +**Up to date as of Aug 21, 2020** This document describes the high-level features and actions for the Meteor project in the near- to medium-term future. This roadmap was built based on community feedback and to improve areas where Meteor is already strong. The description of many items include sentences and ideas from Meteor community members. @@ -15,9 +15,9 @@ Ideally, every item in this roadmap should have at least two leaders, leaders ar ## Core ### Tree Shaking -- Leaders: [Filipe Névola](https://github.com/filipenevola) / [Renan Castro](https://github.com/renanccastro) +- Leaders: [Renan Castro](https://github.com/renanccastro) / [Filipe Névola](https://github.com/filipenevola) - Status: In Progress -- PRs: - +- PRs: [#11107](https://github.com/meteor/meteor/pull/11107) Implement tree shaking / dead code elimination, which involves pruning the dependency tree while scanning imports in the `ImportScanner`. We believe it should be possible to treat values like `Meteor.isProduction` and `Meteor.isServer` as constants during this process, and eliminate those branches if their conditions are false (as in https://github.com/meteor/meteor/pull/10056). @@ -29,25 +29,9 @@ Implement tree shaking / dead code elimination, which involves pruning the depen A proper service worker build target. Regular Web Workers can be built from a function.toString() but service-workers require an actual server route. ### Ultra-thin Meteor -- Leaders: [Ruither Borba](https://github.com/delki8) +- Leaders: [Ruither Borba](https://github.com/delki8) / [Christian Klaussner](https://github.com/klaussner) - Status: In Progress -- PRs: -Autoupdate package without ddp [#11034](https://github.com/meteor/meteor/pull/11034) - -[Meteor 1.7](https://github.com/meteor/meteor/blob/devel/History.md#v17-2018-05-28) introduced the `meteor create --minimal` command, which generates a new application without any unnecessary Meteor packages, like `mongo` and `ddp`. - -When minified and gzip-compressed, the JS bundle for this app weighs in at less than 20kB, which is much smaller than the default `meteor create` application. Nevertheless, there is still room for improvement, using techniques like bundle visualization (`meteor npm run visualize`) and converting static `import`s to dynamic `import()`s. - -Additionally, minimal Meteor applications do not include the `autoupdate` package by default, because it is not strictly necessary for building an application, and its dependencies (`ddp` in particular, but no longer `mongo` or `minimongo`, thanks to [PR #10238](https://github.com/meteor/meteor/pull/10238)) contribute an additional 30kB to the JS bundle. The drawback of not using `autoupdate` is that instantaneous client refreshes are disabled, which can slow down development, so it would be great to find a way of making `autoupdate` less expensive, or enable it only in development. - -In other words, we want minimal Meteor apps to be not only as tiny as possible, but also just as developer-friendly as a normal Meteor application. - -Related issues: -* [MFR #31](https://github.com/meteor/meteor-feature-requests/issues/31) -* [MFR #354](https://github.com/meteor/meteor-feature-requests/issues/354) -* [Issue #9960](https://github.com/meteor/meteor/issues/9960) -* [PR #8853](https://github.com/meteor/meteor/pull/8853) -* [PR #10238](https://github.com/meteor/meteor/pull/10238) +- PRs: https://github.com/meteor/meteor/pull/11034 https://github.com/meteor/meteor/pull/11106 ### Page load performance improvements - Leaders: [Seba Kerckhof](https://github.com/sebakerckhof) @@ -63,19 +47,13 @@ Make sure we are not delivering any dependency that is not used ([Issue #10701]( Explore ideas to improve rebuild time such as split main client bundle into several bundles, split the server bundle into several bundles, store less file content in memory, option to disabling the legacy build (at least in dev mode), etc -### Performance improvements on Windows -- Leaders: [zodern](https://github.com/zodern) -- Status: In Progress -- PRs: https://github.com/meteor/meteor/pull/10838 - -Explore ideas to improve performance on Windows such as build in place. ### Hot Module Replacement - Leaders: [zodern](https://github.com/zodern) - Status: In Progress -- PRs: - +- PRs: https://github.com/meteor/meteor/pull/11117 -Explore ideas to implement HMR in Meteor. +HMR in Meteor, we already have a work in progress here, you can provide feedback already, check the PR. ### Transition as much as possible to NPM - Leaders: @@ -116,11 +94,6 @@ Provide a nice and friendly introduction for people that are learning Meteor. Angular tutorial should reflect latest best practices for using Meteor and Angular together. -### Update React Tutorial -- Leaders: [Leonardo Venturini](https://github.com/leonardoventurini) -- Status: In Progress -- PRs: https://github.com/meteor/simple-todos-react/tree/tortilla-master - React tutorial should reflect latest best practices for using Meteor and React together. ### PWA documentation @@ -147,23 +120,6 @@ Relevant issues: Provide samples on how to run tests in Meteor these samples should include unit tests and also cypress tests. -## First-class citizen Technologies -Consider Vue.js, Svelte, React Native, and Apollo as first-class citizen, for -each technology we would like to have: -- skeleton (meteor create) -- tutorial -- documentation (how to use) -- examples - -as we already have for Blaze, React and Angular. - -### Vue.js -- Leaders: [Brian Mulhall](https://github.com/BrianMulhall) -- Status: In Progress -- PRs: https://github.com/meteor/simple-todos-vue - -Tutorial is ready. We want a create command (--vue) yet and more docs. - ### Svelte - Leaders: [Brian Mulhall](https://github.com/BrianMulhall) - Status: In Progress @@ -171,18 +127,6 @@ Tutorial is ready. We want a create command (--vue) yet and more docs. Tutorial is ready. We want a create command (--svelte) yet and more docs. -### React Native -- Leaders: [Nathaniel Dsouza](https://github.com/TheRealNate) -- Status: In Progress -- PRs: https://github.com/meteor/guide/pull/1041 https://github.com/meteor/guide/pull/1039 https://github.com/meteor/guide/pull/1035 - -We have some docs already maybe we could have an example in the examples folder. - -### Apollo -- Leaders: -- Status: - -- PRs: - - ### Third-party tools with their own build steps - Leaders: @@ -196,6 +140,39 @@ Relevant discussions: - https://github.com/storybookjs/storybook/issues/5975 ## Recently completed +### Vue.js +- Leaders: [Brian Mulhall](https://github.com/BrianMulhall) +- Status: shipped in August 2020 +- PRs: https://github.com/meteor/simple-todos-vue + +Tutorial is ready and create command meteor create --vue + +### Apollo +- Leaders: [Jan Dvorak](https://github.com/StorytellerCZ) +- Status: shipped in August 2020 +- PRs: https://github.com/meteor/meteor/pull/11119 + +Apollo skeleton, meteor create --apollo + +### Performance improvements on Windows +- Leaders: [zodern](https://github.com/zodern) +- Status: shipped in August 2020 +- PRs: https://github.com/meteor/meteor/pull/10838 https://github.com/meteor/meteor/pull/11114 https://github.com/meteor/meteor/pull/11115 https://github.com/meteor/meteor/pull/11102 + +Explore ideas to improve performance on Windows such as build in place. + +### Update React Tutorial +- Leaders: [Leonardo Venturini](https://github.com/leonardoventurini) / [Brian Mulhall](https://github.com/BrianMulhall) +- Status: shipped in July 2020 +- PRs: https://github.com/meteor/simple-todos-react + +### React Native +- Leaders: [Nathaniel Dsouza](https://github.com/TheRealNate) +- Status: shipped in June 2020 +- PRs: https://github.com/meteor/guide/pull/1041 https://github.com/meteor/guide/pull/1039 https://github.com/meteor/guide/pull/1035 + +Guide is ready ([check here](https://guide.meteor.com/react-native.html)). + ### Update Blaze Tutorial - Leaders: [Jan Küster](https://github.com/jankapunkt), [Harry Adel](https://github.com/harryadelb), [Brian Mulhall](https://github.com/BrianMulhall) - Status: shipped in April 2020 diff --git a/meteor b/meteor index 15264e56ef..8496e54b47 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=12.16.1.8 +BUNDLE_VERSION=12.18.3.2 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js index 02bd42a85b..eeea919ae5 100644 --- a/packages/accounts-base/accounts_server.js +++ b/packages/accounts-base/accounts_server.js @@ -71,9 +71,9 @@ export class AccountsServer extends AccountsCommon { resetPassword: token => Meteor.absoluteUrl(`#/reset-password/${token}`), verifyEmail: token => Meteor.absoluteUrl(`#/verify-email/${token}`), enrollAccount: token => Meteor.absoluteUrl(`#/enroll-account/${token}`), - } + }; - this.addDefaultRateLimit() + this.addDefaultRateLimit(); } /// @@ -117,6 +117,19 @@ export class AccountsServer extends AccountsCommon { this._validateNewUserHooks.push(func); } + /** + * @summary Validate login from external service + * @locus Server + * @param {Function} func Called whenever login/user creation from external service is attempted. Login or user creation based on this login can be aborted by passing a falsy value or throwing an exception. + */ + beforeExternalLogin(func) { + if (this._beforeExternalLoginHook) { + throw new Error("Can only call beforeExternalLogin once"); + } + + this._beforeExternalLoginHook = func; + } + /// /// CREATE USER HOOKS /// @@ -1211,6 +1224,11 @@ export class AccountsServer extends AccountsCommon { let user = this.users.findOne(selector, {fields: this._options.defaultFieldSelector}); + // Before continuing, run user hook to see if we should continue + if (this._beforeExternalLoginHook && !this._beforeExternalLoginHook(serviceName, serviceData, user)) { + throw new Meteor.Error(403, "Login forbidden"); + } + // When creating a new user we pass through all options. When updating an // existing user, by default we only process/pass through the serviceData // (eg, so that we keep an unexpired access token and don't cache old email diff --git a/packages/accounts-base/accounts_tests.js b/packages/accounts-base/accounts_tests.js index 0aa92459c9..fa52871a21 100644 --- a/packages/accounts-base/accounts_tests.js +++ b/packages/accounts-base/accounts_tests.js @@ -623,3 +623,44 @@ Tinytest.add( Accounts._options = accountsOptions; } ); + +Tinytest.add( + 'accounts - verify beforeExternalLogin hook can stop user login', + test => { + // Verify user data is saved properly when not using the + // beforeExternalLogin hook. + let facebookId = Random.id(); + const uid1 = Accounts.updateOrCreateUserFromExternalService( + 'facebook', + { id: facebookId }, + { profile: { foo: 1 } }, + ).userId; + const ignoreFieldName = "bigArray"; + const c = Meteor.users.update(uid1, {$set: {[ignoreFieldName]: [1]}}); + let users = + Meteor.users.find({ 'services.facebook.id': facebookId }).fetch(); + test.length(users, 1); + test.equal(users[0].profile.foo, 1); + test.isNotUndefined(users[0][ignoreFieldName], 'ignoreField - before limit fields'); + + // Verify that when beforeExternalLogin returns false + // that an error throws and user is not saved + Accounts.beforeExternalLogin((serviceName, serviceData, user) => { + // Check that we get the correct data + test.equal(serviceName, 'facebook'); + test.equal(serviceData, { id: facebookId }); + test.equal(user._id, uid1); + return false + }); + + test.throws(() => Accounts.updateOrCreateUserFromExternalService( + 'facebook', + { id: facebookId }, + { profile: { foo: 1 } }, + )); + + // Cleanup + Meteor.users.remove(uid1); + Accounts._beforeExternalLoginHook = null; + } +); diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index d0cae1538f..d5df2e69c5 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.6.0", + version: "1.7.0", }); Package.onUse(api => { diff --git a/packages/accounts-password/email_tests_setup.js b/packages/accounts-password/email_tests_setup.js index 32c080a4a5..346390e63e 100644 --- a/packages/accounts-password/email_tests_setup.js +++ b/packages/accounts-password/email_tests_setup.js @@ -20,7 +20,7 @@ Accounts.emailTemplates.headers = { 'My-Custom-Header' : 'Cool' }; -EmailTest.hookSend(options => { +Email.hookSend(options => { const { to } = options; if (!to || !to.toUpperCase().includes('INTERCEPT')) { return true; // go ahead and send diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index fb9bc6324c..245921ed2e 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -5,7 +5,7 @@ Package.describe({ // 2.2.x in the future. The version was also bumped to 2.0.0 temporarily // during the Meteor 1.5.1 release process, so versions 2.0.0-beta.2 // through -beta.5 and -rc.0 have already been published. - version: "1.6.1" + version: "1.6.2" }); Package.onUse(api => { diff --git a/packages/accounts-password/password_client.js b/packages/accounts-password/password_client.js index 022c1cdf65..871393127a 100644 --- a/packages/accounts-password/password_client.js +++ b/packages/accounts-password/password_client.js @@ -20,7 +20,7 @@ const reportError = (error, callback) => { /** * @summary Log the user in with a password. * @locus Client - * @param {Object | String} user + * @param {Object | String} selector * Either a string interpreted as a username or an email; or an object with a * single key: `email`, `username` or `id`. Username or email match in a case * insensitive manner. diff --git a/packages/boilerplate-generator/package.js b/packages/boilerplate-generator/package.js index d370abb27a..83fc175361 100644 --- a/packages/boilerplate-generator/package.js +++ b/packages/boilerplate-generator/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Generates the boilerplate html from program's manifest", - version: '1.7.0' + version: '1.7.1' }); Npm.depends({ diff --git a/packages/boilerplate-generator/template-web.cordova.js b/packages/boilerplate-generator/template-web.cordova.js index 236fb2e60f..591f3887de 100644 --- a/packages/boilerplate-generator/template-web.cordova.js +++ b/packages/boilerplate-generator/template-web.cordova.js @@ -29,7 +29,7 @@ export const headTemplate = ({ ' ', ' ', ' ', - ' ', + ' ', (headSections.length === 1) ? [cssBundle, headSections[0]].join('\n') diff --git a/packages/ddp-client/.npm/package/npm-shrinkwrap.json b/packages/ddp-client/.npm/package/npm-shrinkwrap.json index 83ff1746e4..5d2c645d18 100644 --- a/packages/ddp-client/.npm/package/npm-shrinkwrap.json +++ b/packages/ddp-client/.npm/package/npm-shrinkwrap.json @@ -2,9 +2,9 @@ "lockfileVersion": 1, "dependencies": { "lolex": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz", - "integrity": "sha512-mQuW55GhduF3ppo+ZRUTz1PRjEh1hS5BbqU7d8D0ez2OKxHDod7StPPeAVKisZR5aLkHZjdGWSL42LSONUJsZw==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==" } } } diff --git a/packages/ddp-rate-limiter/package.js b/packages/ddp-rate-limiter/package.js index 730cededb7..f96ca1cf3e 100644 --- a/packages/ddp-rate-limiter/package.js +++ b/packages/ddp-rate-limiter/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ddp-rate-limiter', - version: '1.0.7', + version: '1.0.9', // Brief, one-line summary of the package. summary: 'The DDPRateLimiter allows users to add rate limits to DDP' + ' methods and subscriptions.', diff --git a/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json index c5366d30b1..a69db9f9a5 100644 --- a/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json +++ b/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json @@ -2,9 +2,9 @@ "lockfileVersion": 1, "dependencies": { "core-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", - "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" } } } diff --git a/packages/ecmascript-runtime-client/package.js b/packages/ecmascript-runtime-client/package.js index 0d301514e8..80bcf3c191 100644 --- a/packages/ecmascript-runtime-client/package.js +++ b/packages/ecmascript-runtime-client/package.js @@ -1,13 +1,13 @@ Package.describe({ name: "ecmascript-runtime-client", - version: "0.10.0", + version: "0.11.0", summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client", documentation: "README.md" }); Npm.depends({ - "core-js": "3.2.1" + "core-js": "3.6.5" }); Package.onUse(function(api) { diff --git a/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json index c5366d30b1..a69db9f9a5 100644 --- a/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json +++ b/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json @@ -2,9 +2,9 @@ "lockfileVersion": 1, "dependencies": { "core-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", - "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" } } } diff --git a/packages/ecmascript-runtime-server/package.js b/packages/ecmascript-runtime-server/package.js index 12e5a683c0..2ebd26aded 100644 --- a/packages/ecmascript-runtime-server/package.js +++ b/packages/ecmascript-runtime-server/package.js @@ -1,13 +1,13 @@ Package.describe({ name: "ecmascript-runtime-server", - version: "0.9.0", + version: "0.10.0", summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set", git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client", documentation: "README.md" }); Npm.depends({ - "core-js": "3.2.1" + "core-js": "3.6.5" }); Package.onUse(function(api) { diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 38652fe742..e4ffb8f728 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -1,15 +1,15 @@ { "lockfileVersion": 1, "dependencies": { - "node4mailer": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/node4mailer/-/node4mailer-4.0.3.tgz", - "integrity": "sha1-jwx6ZzdSehKFMBhaFMLoeZiaiRA=" + "nodemailer": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz", + "integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA==" }, "stream-buffers": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.5.tgz", - "integrity": "sha1-+TBTnTzwjXSKNArWE5+Vss60jwU=" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", + "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==" } } } diff --git a/packages/email/email.js b/packages/email/email.js index 4809122f99..ed46eada8b 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -1,6 +1,6 @@ var Future = Npm.require('fibers/future'); var urlModule = Npm.require('url'); -var nodemailer = Npm.require('node4mailer'); +var nodemailer = Npm.require('nodemailer'); Email = {}; EmailTest = {}; @@ -8,12 +8,12 @@ EmailTest = {}; EmailInternals = { NpmModules: { mailcomposer: { - version: Npm.require('node4mailer/package.json').version, - module: Npm.require('node4mailer/lib/mail-composer') + version: Npm.require('nodemailer/package.json').version, + module: Npm.require('nodemailer/lib/mail-composer') }, nodemailer: { - version: Npm.require('node4mailer/package.json').version, - module: Npm.require('node4mailer') + version: Npm.require('nodemailer/package.json').version, + module: Npm.require('nodemailer') } } }; @@ -98,15 +98,17 @@ var smtpSend = function (transport, mail) { transport._syncSendMail(mail); }; +var sendHooks = []; + /** - * Mock out email sending (eg, during a test.) This is private for now. + * @summary Hook that runs before email is sent. + * @locus Server * - * f receives the arguments to Email.send and should return true to go + * @param f {function} receives the arguments to Email.send and should return true to go * ahead and send the email (or at least, try subsequent hooks), or * false to skip sending. */ -var sendHooks = []; -EmailTest.hookSend = function (f) { +Email.hookSend = function (f) { sendHooks.push(f); }; @@ -118,9 +120,9 @@ EmailTest.hookSend = function (f) { * If the `MAIL_URL` environment variable is set, actually sends the email. * Otherwise, prints the contents of the email to standard out. * - * Note that this package is based on **mailcomposer 4**, so make sure to refer to - * [the documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md) - * for that version when using the `attachments` or `mailComposer` options. + * Note that this package is based on **nodemailer**, so make sure to refer to + * [the documentation](http://nodemailer.com/) + * when using the `attachments` or `mailComposer` options. * * @locus Server * @param {Object} options @@ -136,7 +138,7 @@ EmailTest.hookSend = function (f) { * @param {String} [options.icalEvent] iCalendar event attachment * @param {Object} [options.headers] Dictionary of custom headers - e.g. `{ "header name": "header value" }`. To set an object under a header name, use `JSON.stringify` - e.g. `{ "header name": JSON.stringify({ tracking: { level: 'full' } }) }`. * @param {Object[]} [options.attachments] Array of attachment objects, as - * described in the [mailcomposer documentation](https://github.com/nodemailer/mailcomposer/blob/v4.0.1/README.md#attachments). + * described in the [nodemailer documentation](https://nodemailer.com/message/attachments/). * @param {MailComposer} [options.mailComposer] A [MailComposer](https://nodemailer.com/extras/mailcomposer/#e-mail-message-fields) * object representing the message to be sent. Overrides all other options. * You can create a `MailComposer` object via diff --git a/packages/email/package.js b/packages/email/package.js index 836e70f6f9..45054f813f 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,11 +1,11 @@ Package.describe({ summary: "Send email messages", - version: "1.2.3" + version: "2.0.0" }); Npm.depends({ - node4mailer: "4.0.3", - "stream-buffers": "0.2.5" + nodemailer: "6.4.6", + "stream-buffers": "3.0.2" }); Package.onUse(function (api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 651e2fe3c2..c00dc12696 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.10.2' + version: '1.11.0' }); Package.includeTool(); diff --git a/packages/minifier-css/.gitignore b/packages/minifier-css/.gitignore index 677a6fc263..c01644335c 100644 --- a/packages/minifier-css/.gitignore +++ b/packages/minifier-css/.gitignore @@ -1 +1,2 @@ .build* +.npm diff --git a/packages/minifier-css/.npm/package/npm-shrinkwrap.json b/packages/minifier-css/.npm/package/npm-shrinkwrap.json index 0cf06de439..4fee0a023f 100644 --- a/packages/minifier-css/.npm/package/npm-shrinkwrap.json +++ b/packages/minifier-css/.npm/package/npm-shrinkwrap.json @@ -27,9 +27,9 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "browserslist": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", - "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==" + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", + "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==" }, "caller-callsite": { "version": "2.0.0", @@ -52,9 +52,9 @@ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" }, "caniuse-lite": { - "version": "1.0.30001066", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001066.tgz", - "integrity": "sha512-Gfj/WAastBtfxLws0RCh2sDbTK/8rJuSeZMecrSkNGYxPcv7EzblmDGfWQCFEQcSqYE2BRgQiJh8HOD07N5hIw==" + "version": "1.0.30001125", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001125.tgz", + "integrity": "sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==" }, "chalk": { "version": "2.4.2", @@ -124,9 +124,9 @@ "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==" }, "css-what": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", - "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==" }, "cssesc": { "version": "3.0.0", @@ -208,19 +208,19 @@ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" }, "dot-prop": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", - "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" }, "electron-to-chromium": { - "version": "1.3.453", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.453.tgz", - "integrity": "sha512-IQbCfjJR0NDDn/+vojTlq7fPSREcALtF8M1n01gw7nQghCtfFYrJ2dfhsp8APr8bANoFC8vRTFVXMOGpT0eetw==" + "version": "1.3.564", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz", + "integrity": "sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==" }, "entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz", - "integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, "error-ex": { "version": "1.3.2", @@ -228,15 +228,20 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==" + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==" }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==" }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -247,11 +252,6 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -313,9 +313,9 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", + "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==" }, "is-color-stop": { "version": "1.1.0", @@ -338,9 +338,9 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==" }, "is-resolvable": { "version": "1.1.0", @@ -367,11 +367,6 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -398,9 +393,9 @@ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" }, "node-releases": { - "version": "1.1.57", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.57.tgz", - "integrity": "sha512-ZQmnWS7adi61A9JsllJ2gdj2PauElcjnOwTp2O011iGzoakTxUsDGSe+6vD7wXbKdqhSFymC0OSx35aAMhrSdw==" + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" }, "normalize-url": { "version": "3.3.0", @@ -413,9 +408,9 @@ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" }, "object-keys": { "version": "1.1.1", @@ -437,45 +432,20 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==" }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=" }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=" - }, "postcss": { - "version": "7.0.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.31.tgz", - "integrity": "sha512-a937VDHE1ftkjk+8/7nj/mrjtmkn69xxzJgRETXdAUU+IgOYPQNJF17haGWbeDxSyk++HA14UA98FurvPyBJOA==" + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==" }, "postcss-calc": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", - "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==" + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.4.tgz", + "integrity": "sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw==" }, "postcss-colormin": { "version": "4.0.3", @@ -807,16 +777,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==" }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==" - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==" - }, "string.prototype.trimstart": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", diff --git a/packages/minifier-css/package.js b/packages/minifier-css/package.js index 3cf0016536..eec87a69bc 100644 --- a/packages/minifier-css/package.js +++ b/packages/minifier-css/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: 'CSS minifier', - version: '1.5.2' + version: '1.5.3' }); Npm.depends({ - postcss: '7.0.31', + postcss: '7.0.32', cssnano: '4.1.10' }); diff --git a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json index a3c322dc3a..cb91a9ef22 100644 --- a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json +++ b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json @@ -2,14 +2,14 @@ "lockfileVersion": 1, "dependencies": { "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==" }, "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", + "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" }, "core-util-is": { "version": "1.0.2", @@ -37,9 +37,9 @@ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "mongodb": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.5.tgz", - "integrity": "sha512-GCjDxR3UOltDq00Zcpzql6dQo1sVry60OXJY3TDmFc2SWFY6c8Gn1Ardidc5jDirvJrx2GC3knGOImKphbSL3A==" + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", + "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==" }, "process-nextick-args": { "version": "2.0.1", diff --git a/packages/npm-mongo/package.js b/packages/npm-mongo/package.js index 1c31a69226..4b88f4acf0 100644 --- a/packages/npm-mongo/package.js +++ b/packages/npm-mongo/package.js @@ -3,12 +3,12 @@ Package.describe({ summary: "Wrapper around the mongo npm package", - version: "3.7.1", + version: "3.8.1", documentation: null }); Npm.depends({ - mongodb: "3.5.5" + mongodb: "3.6.2" }); Package.onUse(function (api) { diff --git a/packages/standard-minifier-css/package.js b/packages/standard-minifier-css/package.js index 5a58798bbd..bbf66e0a07 100644 --- a/packages/standard-minifier-css/package.js +++ b/packages/standard-minifier-css/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'standard-minifier-css', - version: '1.6.0', + version: '1.6.1', summary: 'Standard css minifier used with Meteor apps by default.', documentation: 'README.md' }); @@ -21,5 +21,6 @@ Package.registerBuildPlugin({ }); Package.onUse(function(api) { + api.use('minifier-css@1.5.3'); api.use('isobuild:minifier-plugin@1.0.0'); }); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index bb569315d0..e3450a1f5d 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.10.2-rc.0", + "version": "1.11-rc.0", "recommended": false, "official": false, "description": "Meteor" diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 49c3725fd8..339adb2cce 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.10.2", + "version": "1.11", "recommended": false, "official": true, "description": "The Official Meteor Distribution" diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 026a66f569..19fe60270c 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -5,10 +5,10 @@ set -u UNAME=$(uname) ARCH=$(uname -m) -NODE_VERSION=12.16.1 -MONGO_VERSION_64BIT=4.2.5 +NODE_VERSION=12.18.3 +MONGO_VERSION_64BIT=4.2.8 MONGO_VERSION_32BIT=3.2.22 -NPM_VERSION=6.14.0 +NPM_VERSION=6.14.6 # If we built Node from source on Jenkins, this is the build number. NODE_BUILD_NUMBER= diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 266f2d7fd8..570183b4be 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -10,7 +10,7 @@ var packageJson = { dependencies: { // Explicit dependency because we are replacing it with a bundled version // and we want to make sure there are no dependencies on a higher version - npm: "6.14.0", + npm: "6.14.6", pacote: "https://github.com/meteor/pacote/tarball/a81b0324686e85d22c7688c47629d4009000e8b8", "node-gyp": "6.0.1", "node-pre-gyp": "0.14.0", diff --git a/scripts/generate-dev-bundle.sh b/scripts/generate-dev-bundle.sh index 66eafb0c75..50a9dfc053 100755 --- a/scripts/generate-dev-bundle.sh +++ b/scripts/generate-dev-bundle.sh @@ -66,7 +66,7 @@ case $OS in linux) [ $ARCH = "i686" ] && MONGO_BASE_URL="https://fastdl.mongodb.org/linux" || - MONGO_BASE_URL="https://github.com/meteor/mongodb-builder/releases/download/${MONGO_VERSION}" + MONGO_BASE_URL="https://github.com/meteor/mongodb-builder/releases/download/v${MONGO_VERSION}" ;; esac diff --git a/tools/cli/commands.js b/tools/cli/commands.js index 95df9286d2..da9adc786d 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -517,7 +517,9 @@ main.registerCommand({ minimal: { type: Boolean }, full: { type: Boolean }, react: { type: Boolean }, + vue: { type: Boolean }, typescript: { type: Boolean }, + apollo: { type: Boolean }, }, catalogRefresh: new catalog.Refresh.Never() }, function (options) { @@ -770,8 +772,12 @@ main.registerCommand({ skelName += "-full"; } else if (options.react) { skelName += "-react"; + } else if (options.vue) { + skelName += "-vue"; } else if (options.typescript) { skelName += "-typescript"; + } else if (options.apollo) { + skelName += "-apollo"; } files.cp_r(files.pathJoin(__dirnameConverted, '..', 'static-assets', skelName), appPath, { @@ -886,8 +892,9 @@ main.registerCommand({ ! options.minimal && ! options.full && ! options.react && + ! options.vue && ! options.typescript) { - // Notify people about --bare, --minimal, --full, --react, and --typescript. + // Notify people about --bare, --minimal, --full, --react, --vue, --apollo and --typescript. Console.info([ "", "To start with a different app template, try one of the following:", @@ -898,6 +905,8 @@ main.registerCommand({ cmd("meteor create --minimal # to create an app with as few Meteor packages as possible"); cmd("meteor create --full # to create a more complete scaffolded app"); cmd("meteor create --react # to create a basic React-based app"); + cmd("meteor create --vue # to create a basic Vue-based app"); + cmd("meteor create --apollo # to create a basic Apollo + React app"); cmd("meteor create --typescript # to create an app using TypeScript and React"); } @@ -1259,7 +1268,6 @@ main.registerCommand({ projectContext.prepareProjectForBuild(); }); - const bundlePath = projectContext.getProjectLocalDirectory('build'); const bundler = require('../isobuild/bundler.js'); const bundle = bundler.bundle({ projectContext: projectContext, @@ -1428,6 +1436,7 @@ main.registerCommand({ 'allow-incompatible-update': { type: Boolean }, 'deploy-polling-timeout': { type: Number }, 'no-wait': { type: Boolean }, + 'cache-build': { type: Boolean }, }, allowUnrecognizedOptions: true, requiresApp: function (options) { @@ -1501,6 +1510,7 @@ function deployCommand(options, { rawOptions }) { deployPollingTimeoutMs = options['deploy-polling-timeout']; } + const isCacheBuildEnabled = !!options['cache-build']; const waitForDeploy = !options['no-wait']; var deployResult = deploy.bundleAndDeploy({ @@ -1511,6 +1521,7 @@ function deployCommand(options, { rawOptions }) { rawOptions, deployPollingTimeoutMs, waitForDeploy, + isCacheBuildEnabled, }); if (deployResult === 0) { diff --git a/tools/cli/help.txt b/tools/cli/help.txt index 4b37f5e89b..a0618387e0 100644 --- a/tools/cli/help.txt +++ b/tools/cli/help.txt @@ -518,6 +518,8 @@ Options: minified code; defaults to 15 minutes. --no-wait Exits when Meteor has uploaded the app's code instead of waiting for the deploy to conclude. + --cache-build Reuses the build already created if the git commit hash is the + same >>> authorized View or change authorized users and organizations for a site. @@ -809,7 +811,7 @@ Usage: meteor list-sites List the sites that you have deployed with 'meteor deploy', and sites for which other users have authorized you with the 'meteor authorized' command. To see sites in a region other than us-east-1, set the DEPLOY_HOSTNAME -environment variable. For example, +environment variable. For example, `DEPLOY_HOSTNAME=eu-west-1.galaxy-deploy.meteor.com meteor list-sites` diff --git a/tools/cordova/project.js b/tools/cordova/project.js index 75d263ae6f..828c565982 100644 --- a/tools/cordova/project.js +++ b/tools/cordova/project.js @@ -74,6 +74,34 @@ const pinnedPluginVersions = { "cordova-plugin-wkwebview-engine": "1.1.3" } +/** + * To fix Cordova error: Variable(s) missing we convert the cli_variables + * when removing plugins we want to convert for each plugin, for instance, + * cordova-plugin-facebook4: + * commandOptions { + * ... + * cli_variables: { + * 'cordova-plugin-googleplus': { + * REVERSED_CLIENT_ID: 'com.googleusercontent.apps.11111111-xxkodsuusaiusixuaix' + * }, + * 'cordova-plugin-facebook4': { APP_ID: '1111111111111111', APP_NAME: 'appname' } + * } + * } + * into this + * commandOptions { + * ... + * cli_variables: { APP_ID: '1111111111111111', APP_NAME: 'appname' } + * } + * + * @param plugin + * @param commandOptions + */ +const getCommandOptionsForPlugin = (plugin, commandOptions = {}) => { + const cli_variables = commandOptions && commandOptions.cli_variables + && commandOptions.cli_variables[plugin] || {}; + return {...commandOptions, cli_variables}; +} + export class CordovaProject { constructor(projectContext, options = {}) { @@ -521,7 +549,7 @@ from Cordova project`, async () => { buildmessage.assertInJob(); if (utils.isUrlWithSha(version)) { - return convertToGitUrl(version); + return `${id}@${convertToGitUrl(version)}`; } else if (utils.isUrlWithFileScheme(version)) { // Strip file:// and resolve the path relative to the cordova-build // directory @@ -560,18 +588,28 @@ from Cordova project`, async () => { { cli_variables: config, link: utils.isUrlWithFileScheme(version) }); this.runCommands(`adding plugin ${target} \ -to Cordova project`, cordova_lib.plugin.bind(undefined, 'add', [target], commandOptions)); +to Cordova project`, cordova_lib.plugin.bind(undefined, 'add', [target], + commandOptions)); } } // plugins is an array of plugin IDs. - removePlugins(plugins) { + removePlugins(plugins, config = {}) { if (_.isEmpty(plugins)) { return; } - this.runCommands(`removing plugins ${plugins} \ -from Cordova project`, cordova_lib.plugin.bind(undefined, 'rm', plugins, this.defaultOptions)); + const commandOptions = _.extend(this.defaultOptions, + { cli_variables: config }); + + plugins.forEach(plugin => { + const commandOptionsPlugin = getCommandOptionsForPlugin(plugin, + commandOptions); + + this.runCommands(`removing plugin ${plugin} \ + from Cordova project`, cordova_lib.plugin.bind(undefined, 'rm --force', [plugin], + commandOptionsPlugin)); + }); } // Ensures that the Cordova plugins are synchronized with the app-level @@ -699,7 +737,7 @@ perform cordova plugins reinstall`); Object.keys(installedPluginVersions)); } - this.removePlugins(pluginsToRemove); + this.removePlugins(pluginsToRemove, pluginsConfiguration); let pluginVersionsToInstall; @@ -735,7 +773,7 @@ perform cordova plugins reinstall`); // cordova-plugin-whitelist@1.3.2 => { 'cordova-plugin-whitelist': '1.3.2' } // com.cordova.plugin@file://.cordova-plugins/plugin => { 'com.cordova.plugin': 'file://.cordova-plugins/plugin' } // @scope/plugin@1.0.0 => { 'com.cordova.plugin': 'scope/plugin' } - const installed = this.listInstalledPluginVersions(true); + const installed = this.listInstalledPluginVersions(); const installedPluginsNames = Object.keys(installed); const installedPluginsVersions = Object.values(installed); const missingPlugins = {}; diff --git a/tools/fs/files.ts b/tools/fs/files.ts index d5538b0ba3..b5e37a1618 100644 --- a/tools/fs/files.ts +++ b/tools/fs/files.ts @@ -5,7 +5,7 @@ /// import assert from "assert"; -import fs, { PathLike, Stats } from "fs"; +import fs, { PathLike, Stats, Dirent } from "fs"; import path from "path"; import os from "os"; import { spawn, execFile } from "child_process"; @@ -727,9 +727,18 @@ export function freeTempDir(dir: string) { }); } +// Change the status of a dir +export function changeTempDirStatus(dir: string, status: boolean) { + if (! tempDirs[dir]) { + throw Error("not a tracked temp dir: " + dir); + } + + tempDirs[dir] = status; +} + if (! process.env.METEOR_SAVE_TMPDIRS) { cleanup.onExit(function () { - Object.keys(tempDirs).forEach(dir => { + Object.entries(tempDirs).filter(([_, isTmp]) => !!isTmp).map(([dir]) => dir).forEach(dir => { delete tempDirs[dir]; try { rm_recursive(dir); @@ -1538,13 +1547,13 @@ export function readBufferWithLengthAndOffset( if (length > 0) { const fd = open(filename, "r"); try { - var count = read(fd, data, 0, length, offset); + const count = read(fd, data, { position: 0, length, offset }); + if (count !== length) { + throw new Error("couldn't read entire resource"); + } } finally { close(fd); } - if (count !== length) { - throw new Error("couldn't read entire resource"); - } } return data; } @@ -1748,6 +1757,14 @@ wrapFsFunc<[string], string[]>("readdir", fs.readdirSync, [0], { }, }); +export const readdirWithTypes = wrapFsFunc<[string], Dirent[]>("readdirWithTypes", (dir) => { + return fs.readdirSync(dir, { + withFileTypes: true + }); + }, [0], { + cached: true +}); + export const appendFile = wrapDestructiveFsFunc("appendFile", fs.appendFileSync); export const chmod = wrapDestructiveFsFunc("chmod", fs.chmodSync); export const close = wrapFsFunc("close", fs.closeSync, []); diff --git a/tools/fs/safe-watcher.ts b/tools/fs/safe-watcher.ts index 2b548341ce..c90fa56c18 100644 --- a/tools/fs/safe-watcher.ts +++ b/tools/fs/safe-watcher.ts @@ -35,6 +35,14 @@ var NO_WATCHER_POLLING_INTERVAL = // file watchers, but it's to our advantage if they survive restarts. const WATCHER_CLEANUP_DELAY_MS = 30000; +// Pathwatcher complains (using console.error, ugh) if you try to watch +// two files with the same stat.ino number but different paths on linux, so we have +// to deduplicate files by ino. +const DEDUPLICATE_BY_INO = process.platform !== "win32"; + +const entriesByIno = new Map; + + export type SafeWatcher = { close: () => void; } @@ -49,11 +57,6 @@ interface Entry extends SafeWatcher { const entries: Record = Object.create(null); -// Pathwatcher complains (using console.error, ugh) if you try to watch -// two files with the same stat.ino number but different paths, so we have -// to deduplicate files by ino. -const entriesByIno = new Map; - // Set of paths for which a change event has been fired, watched with // watchLibrary.watch if available. This could be an LRU cache, but in // practice it should never grow large enough for that to matter. @@ -86,10 +89,19 @@ function acquireWatcher(absPath: string, callback: EntryCallback) { } function startNewWatcher(absPath: string): Entry { - const stat = statOrNull(absPath); - if (stat && stat.ino > 0 && entriesByIno.has(stat.ino)) { - const entry = entriesByIno.get(stat.ino); - if (entries[absPath] === entry) { + let stat: Stats | null = null; + + if (DEDUPLICATE_BY_INO) { + stat = statOrNull(absPath); + if (stat && stat.ino > 0 && entriesByIno.has(stat.ino)) { + const entry = entriesByIno.get(stat.ino); + if (entries[absPath] === entry) { + return entry; + } + } + } else { + let entry = entries[absPath]; + if (entry) { return entry; } } diff --git a/tools/fs/watch.ts b/tools/fs/watch.ts index 44afacdde1..f473840331 100644 --- a/tools/fs/watch.ts +++ b/tools/fs/watch.ts @@ -1,4 +1,4 @@ -import { Stats, FSWatcher } from "fs"; +import { Stats, FSWatcher, Dirent } from "fs"; import * as files from "./files"; import * as safeWatcher from "./safe-watcher"; import { createHash } from "crypto"; @@ -339,7 +339,7 @@ export const sha512 = Profile("sha512", function (...args: (string | Buffer)[]) function readAndStatDirectory(absPath: string) { // Read the directory. try { - var contents = files.readdir(absPath); + var contents = files.readdirWithTypes(absPath); } catch (e) { // If the path is not a directory, return null; let other errors through. if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) { @@ -351,9 +351,14 @@ function readAndStatDirectory(absPath: string) { // Add slashes to the end of directories. const contentsWithSlashes: string[] = []; contents.forEach(entry => { - // We do stat instead of lstat here, so that we treat symlinks to - // directories just like directories themselves. - const stat = optimisticStatOrNull(files.pathJoin(absPath, entry)); + let stat: Dirent | Stats | null = entry; + let name = entry.name; + + if (entry.isSymbolicLink()) { + // We do stat instead of lstat here, so that we treat symlinks to + // directories just like directories themselves. + stat = optimisticStatOrNull(files.pathJoin(absPath, entry.name)); + } if (! stat) { // Disappeared after the readdir (or a dangling symlink)? // Eh, pretend it was never there in the first place. @@ -361,10 +366,10 @@ function readAndStatDirectory(absPath: string) { } if (stat.isDirectory()) { - entry += '/'; + name += '/'; } - contentsWithSlashes.push(entry); + contentsWithSlashes.push(name); }); return contentsWithSlashes; diff --git a/tools/isobuild/builder.js b/tools/isobuild/builder.js index 04a23919ec..797dca477c 100644 --- a/tools/isobuild/builder.js +++ b/tools/isobuild/builder.js @@ -1,7 +1,7 @@ import assert from "assert"; import {WatchSet, readAndWatchFile, sha1} from '../fs/watch'; import files, { - symlinkWithOverwrite, + symlinkWithOverwrite, realpath, } from '../fs/files'; import NpmDiscards from './npm-discards.js'; import {Profile} from '../tool-env/profile'; @@ -540,7 +540,7 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` // as well as node_modules/meteor and the parent directories of any // scoped npm packages. this._ensureAllNonPackageDirectories( - files.realpath(options.from), + realpath(options.from), options.to ); } @@ -637,7 +637,7 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` }); } - const rootDir = files.realpath(from); + const rootDir = realpath(from); const walk = (absFrom, relTo) => { if (symlink && ! (relTo in this.usedAsFile)) { @@ -661,7 +661,7 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` return; } - // Returns files.realpath(thisAbsFrom), iff it is external to + // Returns files.realpath(thisAbsFrom), if it is external to // rootDir, using caching because this function might be called // more than once. let cachedExternalPath; @@ -671,7 +671,7 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}` } try { - var real = files.realpath(thisAbsFrom); + var real = realpath(thisAbsFrom); } catch (e) { if (e.code !== "ENOENT" && e.code !== "ELOOP") { diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index 5311ebbfd6..fc71b2ca59 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -173,6 +173,7 @@ import { loadIsopackage } from '../tool-env/isopackets.js'; import { CORDOVA_PLATFORM_VERSIONS } from '../cordova'; import { gzipSync } from "zlib"; import { PackageRegistry } from "../../packages/meteor/define-package.js"; +import { optimisticLStatOrNull } from '../fs/optimistic'; const SOURCE_URL_PREFIX = "meteor://\u{1f4bb}app"; @@ -486,12 +487,11 @@ export class NodeModulesDirectory { return true; } - const real = files.realpathOrNull(path); - if (typeof real === "string" && - real !== path) { + const fileStatus = optimisticLStatOrNull(path); + if (fileStatus && fileStatus.isSymbolicLink()) { // If node_modules/.bin/command is a symlink, determine the // answer by calling isWithinProdPackage(real). - return isWithinProdPackage(real); + return isWithinProdPackage(files.realpathOrNull(path)); } // If node_modules/.bin/command is not a symlink, then it's hard @@ -2844,20 +2844,18 @@ var writeTargetToPath = Profile( previousBuilder = null, buildMode, minifyMode, + forceInPlaceBuild }) { var builder = new Builder({ outputPath: files.pathJoin(outputPath, 'programs', name), previousBuilder, - // We do not force an in-place build for individual targets like - // .meteor/local/build/programs/web.browser.legacy, because they - // tend to be written atomically, and it's important on Windows to - // avoid overwriting files that might be open currently in the build - // or server process. - // Server builds do use an in-place build since the server is always stopped - // during the build. - // If client in-place builds were safer on Windows, they - // would be much quicker than from-scratch rebuilds. - forceInPlaceBuild: name === 'server', + // We do not force an in-place build for individual targets + // like .meteor/local/build/programs/web.browser.legacy, because they tend + // to be written atomically, and it's important on Windows to avoid + // overwriting files that might be open currently in the server + // process. There are some exceptions when we know the server process + // is not using the files, such as during a full build when it is stopped. + forceInPlaceBuild }); var targetBuild = target.write(builder, { @@ -2910,6 +2908,7 @@ var writeSiteArchive = Profile("bundler writeSiteArchive", function ( buildMode, minifyMode, sourceRoot, + forceInPlaceBuild, }) { const builders = {}; @@ -3004,7 +3003,8 @@ Find out more about Meteor at meteor.com. releaseName, previousBuilder: previousBuilders[name] || null, buildMode, - minifyMode + minifyMode, + forceInPlaceBuild }); builders[name] = targetBuilder; @@ -3083,6 +3083,10 @@ Find out more about Meteor at meteor.com. * - hasCachedBundle: true if we already have a cached bundle stored in * /build. When true, we only build the new client targets in the bundle. * + * - forceInPlaceBuild On Windows, in place builds are disabled by default + * since they are only safe when the output files from the previous build + * are not being used. This can be set to true when it is safe. + * * Returns an object with keys: * - errors: A buildmessage.MessageSet, or falsy if bundling succeeded. * - serverWatchSet: Information about server files and paths that were @@ -3117,6 +3121,7 @@ function bundle({ previousBuilders = Object.create(null), hasCachedBundle, allowDelayedClientBuilds = false, + forceInPlaceBuild, }) { buildOptions = buildOptions || {}; @@ -3271,6 +3276,7 @@ function bundle({ builtBy, releaseName, minifyMode, + forceInPlaceBuild, }; function writeClientTarget(target) { diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index 7a62748f5a..b8b476d9c4 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -1714,7 +1714,7 @@ export class PackageSourceBatch { if (cacheFilename) { let diskCached = null; try { - diskCached = optimisticReadJsonOrNull(cacheFilename); + diskCached = files.readJSONOrNull(cacheFilename); } catch (e) { // Ignore JSON parse errors; pretend there was no cache. if (!(e instanceof SyntaxError)) { diff --git a/tools/isobuild/import-scanner.ts b/tools/isobuild/import-scanner.ts index 355ad9d0d5..e6c09760e2 100644 --- a/tools/isobuild/import-scanner.ts +++ b/tools/isobuild/import-scanner.ts @@ -25,6 +25,7 @@ import { convertToPosixPath, realpathOrNull, writeFileAtomically, + readFile, } from "../fs/files"; const { SourceNode, SourceMapConsumer } = require("source-map"); @@ -74,9 +75,18 @@ const reifyCompileWithCache = Profile("reifyCompileWithCache", wrap(function ( source, _hash, bundleArch, + cacheFilePath, ) { + if (cacheFilePath) { + try { + return readFile(cacheFilePath, "utf8"); + } catch (e) { + if (e.code !== "ENOENT") throw e; + } + } + const isLegacy = isLegacyArch(bundleArch); - return reifyCompile(stripHashBang(source), { + let result = reifyCompile(stripHashBang(source), { parse: reifyBabelParse, generateLetDeclarations: !isLegacy, avoidModernSyntax: isLegacy, @@ -84,6 +94,14 @@ const reifyCompileWithCache = Profile("reifyCompileWithCache", wrap(function ( dynamicImport: true, ast: false, }).code; + + if (cacheFilePath) { + Promise.resolve().then( + () => writeFileAtomically(cacheFilePath, result), + ); + } + + return result; }, { makeCacheKey(_source, hash, bundleArch) { return JSON.stringify([hash, bundleArch]); @@ -132,29 +150,16 @@ class DefaultHandlers { } } - if (this.cacheDir) { - const cacheFileName = this.getCacheFileName(file)!; - try { - return optimisticReadFile(cacheFileName, "utf8"); - } catch (e) { - if (e.code !== "ENOENT") throw e; - const code = reifyCompileWithCache( - file.dataString, - file.hash, - this.bundleArch, - ); - Promise.resolve().then( - () => writeFileAtomically(cacheFileName, code), - ); - return code; - } - } else { - return reifyCompileWithCache( - file.dataString, - file.hash, - this.bundleArch, - ); - } + const cacheFileName = this.cacheDir ? + this.getCacheFileName(file) : + null; + + return reifyCompileWithCache( + file.dataString, + file.hash, + this.bundleArch, + cacheFileName + ) } // Files with an .mjs extension are just JavaScript plus module syntax. diff --git a/tools/isobuild/package-source.js b/tools/isobuild/package-source.js index 27c332c746..253c5fda18 100644 --- a/tools/isobuild/package-source.js +++ b/tools/isobuild/package-source.js @@ -79,6 +79,9 @@ var loadOrderSort = function (sourceProcessorSet, arch) { }); return function (a, b) { + const aBasename = files.pathBasename(a); + const bBasename = files.pathBasename(b); + // XXX MODERATELY SIZED HACK -- // push template files ahead of everything else. this is // important because the user wants to be able to say @@ -87,15 +90,15 @@ var loadOrderSort = function (sourceProcessorSet, arch) { // before the corresponding .html file. // // maybe all of the templates should go in one file? - var isTemplate_a = isTemplate(files.pathBasename(a)); - var isTemplate_b = isTemplate(files.pathBasename(b)); + var isTemplate_a = isTemplate(aBasename); + var isTemplate_b = isTemplate(bBasename); if (isTemplate_a !== isTemplate_b) { return (isTemplate_a ? -1 : 1); } // main.* loaded last - var ismain_a = (files.pathBasename(a).indexOf('main.') === 0); - var ismain_b = (files.pathBasename(b).indexOf('main.') === 0); + var ismain_a = (aBasename.indexOf('main.') === 0); + var ismain_b = (bBasename.indexOf('main.') === 0); if (ismain_a !== ismain_b) { return (ismain_a ? 1 : -1); } @@ -213,14 +216,44 @@ var getExcerptFromReadme = function (text) { class SymlinkLoopChecker { constructor(sourceRoot) { this.sourceRoot = sourceRoot; + this._realSourceRoot = files.realpath(sourceRoot); this._seenPaths = {}; + this._cache = new Map(); } + // Avoids running realpath unless necessary + // since it is relatively slow on windows + _realpath = Profile('_realpath', function (relDir) { + const absPath = files.pathJoin(this._realSourceRoot, relDir); + + if (files.lstat(absPath).isSymbolicLink()) { + const result = files.realpath(absPath); + this._cache.set(relDir, result); + + return result; + } + + let result; + const parentDir = files.pathDirname(relDir); + const parentEntry = this._cache.get(parentDir); + if (parentDir === '.') { + result = absPath; + } else if (parentEntry) { + result = files.pathJoin(parentEntry, files.pathBasename(relDir)); + } else { + // The parent dir was never checked, which prevents us from + // skipping realpath + result = files.realpath(absPath); + } + + this._cache.set(relDir, result); + return result; + }) + check(relDir, quietly = true) { - const absPath = files.pathJoin(this.sourceRoot, relDir); try { - var realPath = files.realpath(absPath); + var realPath = this._realpath(relDir); } catch (e) { if (!e || e.code !== 'ELOOP') { throw e; @@ -834,10 +867,21 @@ _.extend(PackageSource.prototype, { }), _readAndWatchDirectory(relDir, watchSet, {include, exclude, names}) { - return watch.readAndWatchDirectory(watchSet, { + const options = { absPath: files.pathJoin(this.sourceRoot, relDir), include, exclude, names - }).map(name => files.pathJoin(relDir, name)); + }; + + const contents = watch.readDirectory(options); + + if (watchSet) { + watchSet.addDirectory({ + contents, + ...options + }); + } + + return contents.map(name => files.pathJoin(relDir, name)); }, // Initialize a package from an application directory (has .meteor/packages). @@ -1099,7 +1143,7 @@ _.extend(PackageSource.prototype, { // complete list of source files for directories within node_modules. _findSourcesCache: Object.create(null), - _findSources: Profile("PackageSource#_findSources", function ({ + _findSources: Profile(({ sourceArch }) => `PackageSource#_findSources for ${sourceArch.arch}`, function ({ sourceProcessorSet, watchSet, isApp, @@ -1216,9 +1260,10 @@ _.extend(PackageSource.prototype, { const baseCacheKey = JSON.stringify({ isApp, - arch, sourceRoot: self.sourceRoot, excludes: anyLevelExcludes, + names: sourceReadOptions.names, + include: sourceReadOptions.include }, (key, value) => { if (_.isRegExp(value)) { return [value.source, value.flags]; @@ -1260,13 +1305,13 @@ _.extend(PackageSource.prototype, { return array; } - function find(dir, depth, inNodeModules) { + function find(dir, depth, { inNodeModules = false, cache = false } = {}) { // Remove trailing slash. dir = dir.replace(/\/$/, ""); // If we're in a node_modules directory, cache the results of the // find function for the duration of the process. - let cacheKey = inNodeModules && makeCacheKey(dir); + let cacheKey = inNodeModules && cache && makeCacheKey(dir); if (cacheKey && cacheKey in self._findSourcesCache) { return self._findSourcesCache[cacheKey]; @@ -1305,13 +1350,16 @@ _.extend(PackageSource.prototype, { } const sources = _.difference( - self._readAndWatchDirectory(dir, watchSet, readOptions), + self._readAndWatchDirectory(dir, inNodeModules ? null : watchSet, readOptions), depth > 0 ? [] : controlFiles ); - const subdirectories = self._readAndWatchDirectory(dir, watchSet, { - include: [/\/$/], - exclude: depth > 0 + const subdirectories = self._readAndWatchDirectory( + dir, + inNodeModules ? null : watchSet, + { + include: [/\/$/], + exclude: depth > 0 ? anyLevelExcludes : topLevelExcludes }); @@ -1342,7 +1390,7 @@ _.extend(PackageSource.prototype, { } } else { - sources.push(...find(subdir, depth + 1, inNodeModules)); + sources.push(...find(subdir, depth + 1, { inNodeModules, cache: !inNodeModules })); } }); @@ -1353,7 +1401,7 @@ _.extend(PackageSource.prototype, { // subdirectories, continue searching this node_modules directory, // so that any non-.js(on) files it contains can be imported by // the app (#6037). - sources.push(...find(nodeModulesDir, depth + 1, true)); + sources.push(...find(nodeModulesDir, depth + 1, { inNodeModules: true, cache: !inNodeModules})); } delete dotMeteorIgnoreFiles[dir]; diff --git a/tools/meteor-services/deploy.js b/tools/meteor-services/deploy.js index af4ed72b18..08881fa098 100644 --- a/tools/meteor-services/deploy.js +++ b/tools/meteor-services/deploy.js @@ -9,6 +9,9 @@ import { createTarGzStream, getSettings, mkdtemp, + changeTempDirStatus, + exists, + findGitCommitHash, } from '../fs/files'; import { request } from '../utils/http-helpers.js'; import buildmessage from '../utils/buildmessage.js'; @@ -469,6 +472,8 @@ async function pollForDeploy(pollingState, versionId, site) { // - buildOptions: the 'buildOptions' argument to the bundler // - rawOptions: any unknown options that were passed to the command line tool // - waitForDeploy: whether to poll Galaxy after upload for deploy status +// - isCacheBuildEnabled: Reuses the build already created if the git commit +// hash is the same // - deployPollingTimeoutMs: user overridden timeout for polling Galaxy // for deploy status export async function bundleAndDeploy(options) { @@ -517,10 +522,49 @@ export async function bundleAndDeploy(options) { return 1; } - var buildDir = mkdtemp('build_tar'); - var bundlePath = pathJoin(buildDir, 'bundle'); + const projectDir = options.projectContext.getProjectLocalDirectory(''); + const gitCommitHash = process.env.METEOR_GIT_COMMIT_HASH || findGitCommitHash(projectDir); - Console.info('Preparing to deploy your app...'); + const buildCache = options.projectContext.getBuildCache(); + let isCacheBuildValid = options.isCacheBuildEnabled; + if (options.isCacheBuildEnabled) { + if (!buildCache || + !exists(buildCache.buildDir) || + !exists(buildCache.bundlePath) || + !buildCache.gitCommitHash || + !gitCommitHash || + buildCache.gitCommitHash !== gitCommitHash) { + Console.warn(`We don't have a valid build cache so a new build will be performed.`); + isCacheBuildValid = false; + } + } + + function getBuildDirAndBundlePath() { + if (isCacheBuildValid) { + return buildCache; + } + + const buildDir = mkdtemp('build_tar'); + if (options.isCacheBuildEnabled) { + changeTempDirStatus(buildDir, false); + Console.info(`The --cache-build was used so the build folder (${buildDir}) will not be deleted on exit...`); + } + const bundlePath = pathJoin(buildDir, 'bundle'); + return { buildDir, bundlePath }; + } + + const {buildDir, bundlePath} = getBuildDirAndBundlePath(); + + if (options.isCacheBuildEnabled) { + Console.info('Saving build in cache (--cache-build)...'); + options.projectContext.saveBuildCache({ + buildDir, + bundlePath, + gitCommitHash + }); + } + + Console.info('Preparing to build your app...'); var settings = null; var messages = buildmessage.capture({ @@ -533,16 +577,21 @@ export async function bundleAndDeploy(options) { }); if (! messages.hasMessages()) { - var bundler = require('../isobuild/bundler.js'); - var bundleResult = bundler.bundle({ - projectContext: options.projectContext, - outputPath: bundlePath, - buildOptions: options.buildOptions, - }); + if(isCacheBuildValid) { + Console.info('Skipping build (--cache-build)...'); + } else { + const bundler = require('../isobuild/bundler.js'); - if (bundleResult.errors) { - messages = bundleResult.errors; + const bundleResult = bundler.bundle({ + projectContext: options.projectContext, + outputPath: bundlePath, + buildOptions: options.buildOptions, + }); + + if (bundleResult.errors) { + messages = bundleResult.errors; + } } } @@ -560,6 +609,7 @@ export async function bundleAndDeploy(options) { }); } + Console.info('Preparing to upload your app...'); const result = buildmessage.enterJob({ title: "uploading" }, Profile("upload bundle", function () { @@ -593,6 +643,7 @@ export async function bundleAndDeploy(options) { // build / deploy succeed. We indicate that Meteor should poll for version // status by including a newVersionId in the payload. if (options.waitForDeploy && result.payload.newVersionId) { + Console.info('Waiting for deployment updates from Galaxy...'); return await pollForDeploymentSuccess( result.payload.newVersionId, options.deployPollingTimeoutMs, diff --git a/tools/project-context.js b/tools/project-context.js index 756041362e..467c1e48bb 100644 --- a/tools/project-context.js +++ b/tools/project-context.js @@ -625,6 +625,27 @@ _.extend(ProjectContext.prototype, { ); }, + getBuildCache() { + try { + return JSON.parse(files.readFile(files.pathJoin( + this.projectLocalDir, + "build-cache.json" + ))); + } catch (e) { + return null; + } + }, + + saveBuildCache(buildCache) { + files.writeFileAtomically( + files.pathJoin( + this.projectLocalDir, + "build-cache.json" + ), + JSON.stringify(buildCache) + "\n" + ); + }, + // When running test-packages for an app with local packages, this // method will return the original app dir, as opposed to the temporary // testRunnerAppDir created for the tests. diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index 5354188cdb..c5aaf49ba3 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -579,6 +579,10 @@ _.extend(AppRunner.prototype, { // Permit delayed bundling of client architectures if the // console is interactive. allowDelayedClientBuilds: ! Console.isHeadless(), + + // None of the targets are used during full rebuilds + // so we can safely build in place on Windows + forceInPlaceBuild: !cachedServerWatchSet }); }); diff --git a/tools/runners/run-mongo.js b/tools/runners/run-mongo.js index 731b5863ee..ed4e7a3ff1 100644 --- a/tools/runners/run-mongo.js +++ b/tools/runners/run-mongo.js @@ -938,6 +938,10 @@ _.extend(MRp, { "Looks like you are out of free disk space under .meteor/local."; } else if (explanation) { message += "\n" + explanation.longText; + } else if (process.platform === 'win32') { + message += "\n\n" + + "Check how to troubleshoot here " + + "https://docs.meteor.com/windows.html#cant-start-mongo-server"; } if (explanation && explanation.symbol === 'EXIT_NET_ERROR') { diff --git a/tools/static-assets/skel-apollo/.gitignore b/tools/static-assets/skel-apollo/.gitignore new file mode 100644 index 0000000000..c2658d7d1b --- /dev/null +++ b/tools/static-assets/skel-apollo/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/tools/static-assets/skel-apollo/.meteor/.gitignore b/tools/static-assets/skel-apollo/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/static-assets/skel-apollo/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/static-assets/skel-apollo/.meteor/packages b/tools/static-assets/skel-apollo/.meteor/packages new file mode 100644 index 0000000000..ed6cce950a --- /dev/null +++ b/tools/static-assets/skel-apollo/.meteor/packages @@ -0,0 +1,21 @@ +# 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 +mobile-experience # Packages for a great mobile UX +mongo # The database Meteor supports right now +reactive-var # Reactive variable for tracker + +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 +typescript # Enable TypeScript syntax in .ts and .tsx modules +shell-server # Server-side component of the `meteor shell` command + +static-html # Define static page content in .html files +apollo # Basic Apollo integration for Meteor apps +swydo:graphql # Import .graphql files diff --git a/tools/static-assets/skel-apollo/.meteor/platforms b/tools/static-assets/skel-apollo/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/tools/static-assets/skel-apollo/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tools/static-assets/skel-apollo/client/main.css b/tools/static-assets/skel-apollo/client/main.css new file mode 100644 index 0000000000..7f354f0fa7 --- /dev/null +++ b/tools/static-assets/skel-apollo/client/main.css @@ -0,0 +1,4 @@ +body { + padding: 10px; + font-family: sans-serif; +} diff --git a/tools/static-assets/skel-apollo/client/main.html b/tools/static-assets/skel-apollo/client/main.html new file mode 100644 index 0000000000..b62c0b83d0 --- /dev/null +++ b/tools/static-assets/skel-apollo/client/main.html @@ -0,0 +1,7 @@ + + Apollo Skeleton + + + +
+ diff --git a/tools/static-assets/skel-apollo/client/main.jsx b/tools/static-assets/skel-apollo/client/main.jsx new file mode 100644 index 0000000000..a42cee8ff3 --- /dev/null +++ b/tools/static-assets/skel-apollo/client/main.jsx @@ -0,0 +1,8 @@ +import React from 'react'; +import { Meteor } from 'meteor/meteor'; +import { render } from 'react-dom'; +import { App } from '/imports/ui/App'; + +Meteor.startup(() => { + render(, document.getElementById('react-target')); +}); diff --git a/tools/static-assets/skel-apollo/imports/api/links.js b/tools/static-assets/skel-apollo/imports/api/links.js new file mode 100644 index 0000000000..050c508eae --- /dev/null +++ b/tools/static-assets/skel-apollo/imports/api/links.js @@ -0,0 +1,3 @@ +import { Mongo } from 'meteor/mongo'; + +export const LinksCollection = new Mongo.Collection('links'); diff --git a/tools/static-assets/skel-apollo/imports/apollo/schema.graphql b/tools/static-assets/skel-apollo/imports/apollo/schema.graphql new file mode 100644 index 0000000000..d081209cbc --- /dev/null +++ b/tools/static-assets/skel-apollo/imports/apollo/schema.graphql @@ -0,0 +1,10 @@ +type Link { + _id: ID! + title: String + url: String +} + +type Query { + getLink (id: ID!): Link + getLinks: [Link] +} diff --git a/tools/static-assets/skel-apollo/imports/ui/App.jsx b/tools/static-assets/skel-apollo/imports/ui/App.jsx new file mode 100644 index 0000000000..4b1621d576 --- /dev/null +++ b/tools/static-assets/skel-apollo/imports/ui/App.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client'; +import { Hello } from './Hello.jsx'; +import { Info } from './Info.jsx'; + +const client = new ApolloClient({ + uri: '/graphql', + cache: new InMemoryCache(), + /* Uncomment this for accounts use + request: operation => + operation.setContext(() => ({ + headers: { + authorization: Accounts._storedLoginToken() + } + })) + */ +}); + +export const App = () => ( + +
+

Welcome to Meteor! ☄

+ + +
+
+); diff --git a/tools/static-assets/skel-apollo/imports/ui/Hello.jsx b/tools/static-assets/skel-apollo/imports/ui/Hello.jsx new file mode 100644 index 0000000000..15e0f185ac --- /dev/null +++ b/tools/static-assets/skel-apollo/imports/ui/Hello.jsx @@ -0,0 +1,16 @@ +import React, { useState } from 'react'; + +export const Hello = () => { + const [counter, setCounter] = useState(0); + + const increment = () => { + setCounter(counter + 1); + }; + + return ( +
+ +

You've pressed the button {counter} times.

+
+ ); +}; diff --git a/tools/static-assets/skel-apollo/imports/ui/Info.jsx b/tools/static-assets/skel-apollo/imports/ui/Info.jsx new file mode 100644 index 0000000000..a7073c4839 --- /dev/null +++ b/tools/static-assets/skel-apollo/imports/ui/Info.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { useQuery } from '@apollo/client'; +import { gql } from 'apollo-boost'; + +const GET_LINKS = gql` + { + links: getLinks { + _id + title + url + } + } +`; + +export const Info = () => { + const { loading, error, data } = useQuery(GET_LINKS); + + if (loading) return

Loading...

; + if (error) return

Error ⁉️

; + + return ( +
+

Learn Meteor!

+ +
+ ); +}; diff --git a/tools/static-assets/skel-apollo/package.json b/tools/static-assets/skel-apollo/package.json new file mode 100644 index 0000000000..3954108e95 --- /dev/null +++ b/tools/static-assets/skel-apollo/package.json @@ -0,0 +1,27 @@ +{ + "name": "~name~", + "private": true, + "scripts": { + "start": "meteor run", + "test": "meteor test --once --driver-package meteortesting:mocha", + "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha", + "visualize": "meteor --production --extra-packages bundle-visualizer" + }, + "dependencies": { + "@apollo/client": "^3.1.1", + "@babel/runtime": "^7.10.5", + "apollo-boost": "^0.4.9", + "apollo-server-express": "^2.16.1", + "graphql": "^15.3.0", + "meteor-node-stubs": "^1.0.0", + "react": "^16.13.1", + "react-dom": "^16.13.1" + }, + "meteor": { + "mainModule": { + "client": "client/main.jsx", + "server": "server/main.js" + }, + "testModule": "tests/main.js" + } +} diff --git a/tools/static-assets/skel-apollo/server/apollo.js b/tools/static-assets/skel-apollo/server/apollo.js new file mode 100644 index 0000000000..fa40ecdaa2 --- /dev/null +++ b/tools/static-assets/skel-apollo/server/apollo.js @@ -0,0 +1,31 @@ +import { ApolloServer } from 'apollo-server-express'; +import { WebApp } from 'meteor/webapp'; +import { getUser } from 'meteor/apollo'; +import { LinksCollection } from '/imports/api/links'; +import typeDefs from '/imports/apollo/schema.graphql'; + +const resolvers = { + Query: { + getLink: (obj, { id }) => LinksCollection.findOne(id), + getLinks: () => LinksCollection.find().fetch() + } +}; + +const server = new ApolloServer({ + typeDefs, + resolvers, + context: async ({ req }) => ({ + user: await getUser(req.headers.authorization) + }) +}); + +server.applyMiddleware({ + app: WebApp.connectHandlers, + path: '/graphql' +}); + +WebApp.connectHandlers.use('/graphql', (req, res) => { + if (req.method === 'GET') { + res.end(); + } +}); diff --git a/tools/static-assets/skel-apollo/server/main.js b/tools/static-assets/skel-apollo/server/main.js new file mode 100644 index 0000000000..adc22c3c7b --- /dev/null +++ b/tools/static-assets/skel-apollo/server/main.js @@ -0,0 +1,32 @@ +import { Meteor } from 'meteor/meteor'; +import { LinksCollection } from '/imports/api/links'; +import './apollo' + +function insertLink({ title, url }) { + LinksCollection.insert({title, url, createdAt: new Date()}); +} + +Meteor.startup(() => { + // If the Links collection is empty, add some data. + if (LinksCollection.find().count() === 0) { + insertLink({ + title: 'Do the Tutorial', + url: 'https://www.meteor.com/tutorials/react/creating-an-app' + }); + + insertLink({ + title: 'Follow the Guide', + url: 'http://guide.meteor.com' + }); + + insertLink({ + title: 'Read the Docs', + url: 'https://docs.meteor.com' + }); + + insertLink({ + title: 'Discussions', + url: 'https://forums.meteor.com' + }); + } +}); diff --git a/tools/static-assets/skel-apollo/tests/main.js b/tools/static-assets/skel-apollo/tests/main.js new file mode 100644 index 0000000000..ea7a8da1e1 --- /dev/null +++ b/tools/static-assets/skel-apollo/tests/main.js @@ -0,0 +1,20 @@ +import assert from "assert"; + +describe("~name~", function () { + it("package.json has correct name", async function () { + const { name } = await import("../package.json"); + assert.strictEqual(name, "~name~"); + }); + + if (Meteor.isClient) { + it("client is not server", function () { + assert.strictEqual(Meteor.isServer, false); + }); + } + + if (Meteor.isServer) { + it("server is not client", function () { + assert.strictEqual(Meteor.isClient, false); + }); + } +}); diff --git a/tools/static-assets/skel-bare/package.json b/tools/static-assets/skel-bare/package.json index 16101651e8..5f95e477c6 100644 --- a/tools/static-assets/skel-bare/package.json +++ b/tools/static-assets/skel-bare/package.json @@ -5,7 +5,7 @@ "start": "meteor run" }, "dependencies": { - "@babel/runtime": "^7.8.3", - "meteor-node-stubs": "^1.0.0" + "@babel/runtime": "^7.10.5", + "meteor-node-stubs": "^1.0.1" } } diff --git a/tools/static-assets/skel-full/package.json b/tools/static-assets/skel-full/package.json index a1ee400861..b942252d79 100644 --- a/tools/static-assets/skel-full/package.json +++ b/tools/static-assets/skel-full/package.json @@ -6,11 +6,11 @@ "test": "meteor test --once --driver-package meteortesting:mocha" }, "dependencies": { - "@babel/runtime": "^7.8.3", - "jquery": "^3.4.1", - "meteor-node-stubs": "^1.0.0" + "@babel/runtime": "^7.10.5", + "jquery": "^3.5.1", + "meteor-node-stubs": "^1.0.1" }, "devDependencies": { - "chai": "^4.1.2" + "chai": "^4.2.0" } } diff --git a/tools/static-assets/skel-minimal/package.json b/tools/static-assets/skel-minimal/package.json index 06bae1e9b2..e4ab0c3f33 100644 --- a/tools/static-assets/skel-minimal/package.json +++ b/tools/static-assets/skel-minimal/package.json @@ -8,8 +8,8 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.8.3", - "meteor-node-stubs": "^1.0.0" + "@babel/runtime": "^7.10.5", + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/static-assets/skel-react/package.json b/tools/static-assets/skel-react/package.json index 9d5e743f5a..e5eb581cb5 100644 --- a/tools/static-assets/skel-react/package.json +++ b/tools/static-assets/skel-react/package.json @@ -8,10 +8,10 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.8.4", - "meteor-node-stubs": "^1.0.0", - "react": "^16.13.0", - "react-dom": "^16.13.0" + "@babel/runtime": "^7.10.5", + "meteor-node-stubs": "^1.0.1", + "react": "^16.13.1", + "react-dom": "^16.13.1" }, "meteor": { "mainModule": { diff --git a/tools/static-assets/skel-typescript/package.json b/tools/static-assets/skel-typescript/package.json index 321b1c766c..9fbd619ca3 100644 --- a/tools/static-assets/skel-typescript/package.json +++ b/tools/static-assets/skel-typescript/package.json @@ -8,17 +8,17 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.8.4", - "meteor-node-stubs": "^1.0.0", - "react": "^16.13.0", - "react-dom": "^16.13.0" + "@babel/runtime": "^7.10.5", + "meteor-node-stubs": "^1.0.1", + "react": "^16.13.1", + "react-dom": "^16.13.1" }, "devDependencies": { - "@types/meteor": "^1.4.40", - "@types/mocha": "^5.2.7", - "@types/react": "^16.9.23", - "@types/react-dom": "^16.9.5", - "typescript": "^3.8.2" + "@types/meteor": "^1.4.48", + "@types/mocha": "^8.0.0", + "@types/react": "^16.9.43", + "@types/react-dom": "^16.9.8", + "typescript": "^3.9.7" }, "meteor": { "mainModule": { diff --git a/tools/static-assets/skel-vue/.gitignore b/tools/static-assets/skel-vue/.gitignore new file mode 100644 index 0000000000..c2658d7d1b --- /dev/null +++ b/tools/static-assets/skel-vue/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/tools/static-assets/skel-vue/.meteor/.gitignore b/tools/static-assets/skel-vue/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/tools/static-assets/skel-vue/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tools/static-assets/skel-vue/.meteor/packages b/tools/static-assets/skel-vue/.meteor/packages new file mode 100644 index 0000000000..83be6b3a62 --- /dev/null +++ b/tools/static-assets/skel-vue/.meteor/packages @@ -0,0 +1,24 @@ +# 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 +mobile-experience # Packages for a great mobile UX +mongo # The database Meteor supports right now +reactive-var # Reactive variable for tracker + +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 +typescript # Enable TypeScript syntax in .ts and .tsx modules +shell-server # Server-side component of the `meteor shell` command + +tracker # Dependency tracker to allow reactive callbacks +static-html # Define static page content in .html files +akryum:vue-component # Vue-CLI template to publish components + +meteortesting:mocha # A package for writing and running your meteor app and package tests with mocha +johanbrook:publication-collector # Test a Meteor publication by collecting its output diff --git a/tools/static-assets/skel-vue/.meteor/platforms b/tools/static-assets/skel-vue/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/tools/static-assets/skel-vue/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tools/static-assets/skel-vue/package.json b/tools/static-assets/skel-vue/package.json new file mode 100644 index 0000000000..d7fee7c5a1 --- /dev/null +++ b/tools/static-assets/skel-vue/package.json @@ -0,0 +1,23 @@ +{ + "name": "skel", + "private": true, + "scripts": { + "start": "meteor run", + "test": "meteor test --once --driver-package meteortesting:mocha", + "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha", + "visualize": "meteor --production --extra-packages bundle-visualizer" + }, + "dependencies": { + "@babel/runtime": "^7.10.5", + "meteor-node-stubs": "^1.0.1", + "vue": "^2.6.11", + "vue-meteor-tracker": "^2.0.0-beta.5" + }, + "meteor": { + "mainModule": { + "client": "src/client.js", + "server": "src/server.js" + }, + "testModule": "tests/main.js" + } +} diff --git a/tools/static-assets/skel-vue/src/App.vue b/tools/static-assets/skel-vue/src/App.vue new file mode 100644 index 0000000000..e126098ccb --- /dev/null +++ b/tools/static-assets/skel-vue/src/App.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/tools/static-assets/skel-vue/src/client.js b/tools/static-assets/skel-vue/src/client.js new file mode 100644 index 0000000000..835acaec7b --- /dev/null +++ b/tools/static-assets/skel-vue/src/client.js @@ -0,0 +1,12 @@ +import Vue from 'vue' + +import './plugins' + +import App from './App.vue' + +Meteor.startup(() => { + new Vue({ + el: '#app', + ...App, + }) +}) diff --git a/tools/static-assets/skel-vue/src/collections/Links.js b/tools/static-assets/skel-vue/src/collections/Links.js new file mode 100644 index 0000000000..de6a43c4a4 --- /dev/null +++ b/tools/static-assets/skel-vue/src/collections/Links.js @@ -0,0 +1,3 @@ +import { Mongo } from 'meteor/mongo'; + +export default new Mongo.Collection('links'); diff --git a/tools/static-assets/skel-vue/src/collections/Links.tests.js b/tools/static-assets/skel-vue/src/collections/Links.tests.js new file mode 100644 index 0000000000..0bc5b437dd --- /dev/null +++ b/tools/static-assets/skel-vue/src/collections/Links.tests.js @@ -0,0 +1,24 @@ +// Tests for the behavior of the links collection +// +// https://guide.meteor.com/testing.html + +import { Meteor } from 'meteor/meteor'; +import { assert } from 'chai'; +import Links from './links.js'; + +if (Meteor.isServer) { + describe('links collection', function () { + it('insert correctly', function () { + const linkId = Links.insert({ + title: 'meteor homepage', + url: 'https://www.meteor.com', + }); + const added = Links.find({ _id: linkId }); + const collectionName = added._getCollectionName(); + const count = added.count(); + + assert.equal(collectionName, 'links'); + assert.equal(count, 1); + }); + }); +} diff --git a/tools/static-assets/skel-vue/src/components/Hello.vue b/tools/static-assets/skel-vue/src/components/Hello.vue new file mode 100644 index 0000000000..64947eb06a --- /dev/null +++ b/tools/static-assets/skel-vue/src/components/Hello.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/tools/static-assets/skel-vue/src/components/Info.vue b/tools/static-assets/skel-vue/src/components/Info.vue new file mode 100644 index 0000000000..f20fc4c800 --- /dev/null +++ b/tools/static-assets/skel-vue/src/components/Info.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/tools/static-assets/skel-vue/src/fixtures.js b/tools/static-assets/skel-vue/src/fixtures.js new file mode 100644 index 0000000000..f629f5ca0b --- /dev/null +++ b/tools/static-assets/skel-vue/src/fixtures.js @@ -0,0 +1,32 @@ +import { Meteor } from 'meteor/meteor'; +import Links from './collections/Links.js'; + +Meteor.startup(() => { + // if the Links collection is empty + if (Links.find().count() === 0) { + const data = [ + { + title: 'Do the Tutorial', + url: 'https://www.meteor.com/try', + createdAt: new Date(), + }, + { + title: 'Follow the Guide', + url: 'http://guide.meteor.com', + createdAt: new Date(), + }, + { + title: 'Read the Docs', + url: 'https://docs.meteor.com', + createdAt: new Date(), + }, + { + title: 'Discussions', + url: 'https://forums.meteor.com', + createdAt: new Date(), + }, + ]; + + data.forEach(link => Links.insert(link)); + } +}); diff --git a/tools/static-assets/skel-vue/src/main.html b/tools/static-assets/skel-vue/src/main.html new file mode 100644 index 0000000000..99c3dfb74c --- /dev/null +++ b/tools/static-assets/skel-vue/src/main.html @@ -0,0 +1,7 @@ + + ~name~ + + + +
+ diff --git a/tools/static-assets/skel-vue/src/methods/createLink.js b/tools/static-assets/skel-vue/src/methods/createLink.js new file mode 100644 index 0000000000..876f710978 --- /dev/null +++ b/tools/static-assets/skel-vue/src/methods/createLink.js @@ -0,0 +1,16 @@ +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; +import Links from '../collections/Links.js'; + +Meteor.methods({ + 'createLink'(title, url) { + check(url, String); + check(title, String); + + return Links.insert({ + url, + title, + createdAt: new Date(), + }); + }, +}); diff --git a/tools/static-assets/skel-vue/src/methods/createLink.tests.js b/tools/static-assets/skel-vue/src/methods/createLink.tests.js new file mode 100644 index 0000000000..d899a7338f --- /dev/null +++ b/tools/static-assets/skel-vue/src/methods/createLink.tests.js @@ -0,0 +1,20 @@ +import { Meteor } from 'meteor/meteor'; +import { assert } from 'chai'; +import Links from '../collections/Links.js'; +import './methods.js'; + +if (Meteor.isServer) { + describe('method: createLink', function () { + beforeEach(function () { + Links.remove({}); + }); + + it('can add a new link', function () { + const addLink = Meteor.server.method_handlers['createLink']; + + addLink.apply({}, ['meteor.com', 'https://www.meteor.com']); + + assert.equal(Links.find().count(), 1); + }); + }); +} diff --git a/tools/static-assets/skel-vue/src/methods/index.js b/tools/static-assets/skel-vue/src/methods/index.js new file mode 100644 index 0000000000..c52403a2e8 --- /dev/null +++ b/tools/static-assets/skel-vue/src/methods/index.js @@ -0,0 +1 @@ +import './createLink' diff --git a/tools/static-assets/skel-vue/src/plugins.js b/tools/static-assets/skel-vue/src/plugins.js new file mode 100644 index 0000000000..eb976c92e5 --- /dev/null +++ b/tools/static-assets/skel-vue/src/plugins.js @@ -0,0 +1,4 @@ +import Vue from 'vue' +import VueMeteorTracker from 'vue-meteor-tracker' + +Vue.use(VueMeteorTracker) diff --git a/tools/static-assets/skel-vue/src/publications/index.js b/tools/static-assets/skel-vue/src/publications/index.js new file mode 100644 index 0000000000..d161b580e7 --- /dev/null +++ b/tools/static-assets/skel-vue/src/publications/index.js @@ -0,0 +1 @@ +import './links' diff --git a/tools/static-assets/skel-vue/src/publications/links.js b/tools/static-assets/skel-vue/src/publications/links.js new file mode 100644 index 0000000000..f085d75045 --- /dev/null +++ b/tools/static-assets/skel-vue/src/publications/links.js @@ -0,0 +1,6 @@ +import { Meteor } from 'meteor/meteor'; +import Links from '../collections/Links.js'; + +Meteor.publish('links', function () { + return Links.find(); +}); diff --git a/tools/static-assets/skel-vue/src/publications/links.tests.js b/tools/static-assets/skel-vue/src/publications/links.tests.js new file mode 100644 index 0000000000..37f337c869 --- /dev/null +++ b/tools/static-assets/skel-vue/src/publications/links.tests.js @@ -0,0 +1,22 @@ +import { assert } from 'chai' +import { PublicationCollector } from 'meteor/johanbrook:publication-collector' +import Links from '../collections/Links.js' +import './publications.js' + +describe('Publish links', function () { + beforeEach(function () { + Links.remove({}) + Links.insert({ + title: 'meteor homepage', + url: 'https://www.meteor.com' + }) + }) + + it('sends all links', function (done) { + const collector = new PublicationCollector() + collector.collect('links', (collections) => { + assert.equal(collections.links.length, 1) + done() + }) + }) +}) diff --git a/tools/static-assets/skel-vue/src/server.js b/tools/static-assets/skel-vue/src/server.js new file mode 100644 index 0000000000..c48a837760 --- /dev/null +++ b/tools/static-assets/skel-vue/src/server.js @@ -0,0 +1,3 @@ +import './fixtures' +import './methods' +import './publications' diff --git a/tools/static-assets/skel-vue/tests/main.js b/tools/static-assets/skel-vue/tests/main.js new file mode 100644 index 0000000000..6d2a32e09d --- /dev/null +++ b/tools/static-assets/skel-vue/tests/main.js @@ -0,0 +1,20 @@ +import assert from "assert"; + +describe("skel", function () { + it("package.json has correct name", async function () { + const { name } = await import("../package.json"); + assert.strictEqual(name, "skel"); + }); + + if (Meteor.isClient) { + it("client is not server", function () { + assert.strictEqual(Meteor.isServer, false); + }); + } + + if (Meteor.isServer) { + it("server is not client", function () { + assert.strictEqual(Meteor.isClient, false); + }); + } +}); diff --git a/tools/static-assets/skel/package.json b/tools/static-assets/skel/package.json index 5c204b6488..f8f2793e57 100644 --- a/tools/static-assets/skel/package.json +++ b/tools/static-assets/skel/package.json @@ -8,9 +8,9 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.8.3", - "jquery": "^3.4.1", - "meteor-node-stubs": "^1.0.0" + "@babel/runtime": "^7.10.4", + "jquery": "^3.5.1", + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/tests/apps/app-config/package.json b/tools/tests/apps/app-config/package.json index 08a92217d0..496fed2b9d 100644 --- a/tools/tests/apps/app-config/package.json +++ b/tools/tests/apps/app-config/package.json @@ -6,7 +6,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0", + "meteor-node-stubs": "^1.0.1", "puppeteer": "^1.6.2" }, "meteor": { diff --git a/tools/tests/apps/app-prints-pid/package.json b/tools/tests/apps/app-prints-pid/package.json index 0342ba8008..7213252a4a 100644 --- a/tools/tests/apps/app-prints-pid/package.json +++ b/tools/tests/apps/app-prints-pid/package.json @@ -3,7 +3,7 @@ "private": true, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/tests/apps/client-refresh/package.json b/tools/tests/apps/client-refresh/package.json index 480a02abdf..deb708bb19 100644 --- a/tools/tests/apps/client-refresh/package.json +++ b/tools/tests/apps/client-refresh/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.5", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/tests/apps/custom-minifier/package.json b/tools/tests/apps/custom-minifier/package.json index 82b7bda564..fb6dc51905 100644 --- a/tools/tests/apps/custom-minifier/package.json +++ b/tools/tests/apps/custom-minifier/package.json @@ -10,7 +10,7 @@ "dependencies": { "@babel/runtime": "^7.7.4", "jquery": "^3.4.1", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": "code.js" diff --git a/tools/tests/apps/dev-bundle-bin-commands/package.json b/tools/tests/apps/dev-bundle-bin-commands/package.json index 0243e5b4e4..80f3d838d1 100644 --- a/tools/tests/apps/dev-bundle-bin-commands/package.json +++ b/tools/tests/apps/dev-bundle-bin-commands/package.json @@ -8,6 +8,6 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" } } diff --git a/tools/tests/apps/dynamic-import/package.json b/tools/tests/apps/dynamic-import/package.json index 95244ef029..e4219cab81 100644 --- a/tools/tests/apps/dynamic-import/package.json +++ b/tools/tests/apps/dynamic-import/package.json @@ -10,7 +10,7 @@ "acorn": "^7.1.1", "arson": "^0.2.6", "jquery": "^3.4.1", - "meteor-node-stubs": "^1.0.0", + "meteor-node-stubs": "^1.0.1", "moment": "^2.24.0", "optimism": "^0.11.5", "private": "^0.1.8", diff --git a/tools/tests/apps/git-commit-hash/package.json b/tools/tests/apps/git-commit-hash/package.json index e6db0202b5..6cdf07806d 100644 --- a/tools/tests/apps/git-commit-hash/package.json +++ b/tools/tests/apps/git-commit-hash/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0", + "meteor-node-stubs": "^1.0.1", "puppeteer": "^1.6.2" }, "meteor": { diff --git a/tools/tests/apps/link-config-npm-package/package.json b/tools/tests/apps/link-config-npm-package/package.json index cd7573338d..8edcc43842 100644 --- a/tools/tests/apps/link-config-npm-package/package.json +++ b/tools/tests/apps/link-config-npm-package/package.json @@ -10,7 +10,7 @@ "dependencies": { "@babel/runtime": "^7.5.0", "config": "file:../config-package", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/tests/apps/linked-external-npm-package/package.json b/tools/tests/apps/linked-external-npm-package/package.json index cbc7a546f4..c1c79161f8 100644 --- a/tools/tests/apps/linked-external-npm-package/package.json +++ b/tools/tests/apps/linked-external-npm-package/package.json @@ -10,7 +10,7 @@ "dependencies": { "@babel/runtime": "^7.5.0", "external-package": "file:../external-package", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": { diff --git a/tools/tests/apps/meteor-ignore/package.json b/tools/tests/apps/meteor-ignore/package.json index 527ebe065f..4216ec2e1c 100644 --- a/tools/tests/apps/meteor-ignore/package.json +++ b/tools/tests/apps/meteor-ignore/package.json @@ -6,6 +6,6 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" } } diff --git a/tools/tests/apps/modules/package.json b/tools/tests/apps/modules/package.json index c7e2597040..0852a5fca0 100644 --- a/tools/tests/apps/modules/package.json +++ b/tools/tests/apps/modules/package.json @@ -19,7 +19,7 @@ "jsx-import-test": "file:imports/links/jsx-import-test", "lodash-es": "^4.17.7", "markdown-to-jsx": "4.0.3", - "meteor-node-stubs": "^1.0.0", + "meteor-node-stubs": "^1.0.1", "mobx": "5.8.0", "moment": "^2.22.2", "mssql": "^3.1.1", diff --git a/tools/tests/apps/shell/package.json b/tools/tests/apps/shell/package.json index 3867260eb7..e541d2cf70 100644 --- a/tools/tests/apps/shell/package.json +++ b/tools/tests/apps/shell/package.json @@ -6,6 +6,6 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" } } diff --git a/tools/tests/apps/standard-app/package.json b/tools/tests/apps/standard-app/package.json index bede729806..f815cead34 100644 --- a/tools/tests/apps/standard-app/package.json +++ b/tools/tests/apps/standard-app/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.0", - "meteor-node-stubs": "^1.0.0" + "meteor-node-stubs": "^1.0.1" }, "meteor": { "mainModule": false,