Merge branch 'devel' into meteor-3-vue-3-tutorial

This commit is contained in:
Frederico Maia
2024-08-16 13:17:10 -03:00
committed by GitHub
66 changed files with 1372 additions and 727 deletions

4
.envrc
View File

@@ -32,6 +32,10 @@ function @generate-dev-bundle {
"$ROOT_DIR/scripts/generate-dev-bundle.sh"
}
function @init-submodule {
git submodule update --init --recursive
}
#################
# Documentation #
#################

View File

@@ -10,7 +10,7 @@
[![Travis CI Status](https://api.travis-ci.com/meteor/meteor.svg?branch=devel)](https://app.travis-ci.com/github/meteor/meteor)
[![CircleCI Status](https://circleci.com/gh/meteor/meteor.svg?style=svg)](https://app.circleci.com/pipelines/github/meteor/meteor?branch=devel)
[![built with Meteor](https://img.shields.io/badge/Meteor-3.0.1-green?logo=meteor&logoColor=white)](https://meteor.com)
[![built with Meteor](https://img.shields.io/badge/Meteor-3.0.2-green?logo=meteor&logoColor=white)](https://meteor.com)
![node-current](https://img.shields.io/node/v/meteor)
![Discord](https://img.shields.io/discord/1247973371040239676)
![Twitter Follow](https://img.shields.io/twitter/follow/meteorjs?style=social)

View File

@@ -837,6 +837,7 @@ const handle = cursor.observeChanges({
setTimeout(() => handle.stop(), 5000);
```
{% apibox "Mongo.getCollection" %}
{% apibox "Mongo.ObjectID" %}
`Mongo.ObjectID` follows the same API as the [Node MongoDB driver

View File

@@ -1,19 +1,62 @@
## Meteor Installer
Node.js <=14.x and npm <=6.x is recommended.
### Recommended Versions
Install Meteor by running:
- For Meteor 2 (Legacy)
- Use Node.js 14.x
- Use npm 6.x
- For Meteor 3
- Use Node.js 20.x or higher
- Use npm 9.x or higher
### Installation
To install Meteor, run the following command:
```bash
npm install -g meteor
npx meteor
```
[Read more](https://www.meteor.com/developers/install)
It will install Meteor's latest version, alternatively you can install a specific version by running:
### Meteor version relationship
```bash
npx meteor@<version>
```
This command will execute the Meteor installer without adding it permanently to your global npm packages.
For more information, visit:
- [Meteor 2 Installation Guide (Legacy)](https://v2-docs.meteor.com/install.html)
- [**Meteor 3 Installation Guide**](https://v3-docs.meteor.com/about/install.html)
### Important Note
This npm package is not the Meteor framework itself; it is just an installer. Do not include it as a dependency in your project, as doing so may break your deployment.
### Path Management
By default, the Meteor installer adds its install path (by default, `~/.meteor/`) to your PATH by updating either your `.bashrc`, `.bash_profile`, or `.zshrc` as appropriate. To disable this behavior, install Meteor by running:
```bash
npm install -g meteor --ignore-meteor-setup-exec-path
```
(or by setting the environment variable `npm_config_ignore_meteor_setup_exec_path=true`)
### Proxy Configuration
Set the `https_proxy` or `HTTPS_PROXY` environment variable to a valid proxy URL to download Meteor files through the configured proxy.
### Meteor Version Compatibility
| NPM Package | Meteor Official Release |
|-------------|-------------------------|
| 3.0.2 | 3.0.2 |
| 3.0.1 | 3.0.1 |
| 3.0.0 | 3.0 |
| 2.16.0 | 2.16.0 |
@@ -59,22 +102,3 @@ npm install -g meteor
| 2.3.3 | 2.3.2 |
| 2.3.2 | 2.3.1 |
| 2.3.1 | 2.2.1 |
### Important note
This npm package is not Meteor itself, it is just an installer. You should not include it as a dependency in your project. If you do, your deployment is going to be broken.
### Path management
By default, the Meteor installer adds its install path (by default, `~/.meteor/`) to your PATH by updating either your `.bashrc`, `.bash_profile`, or `.zshrc` as appropriate. To disable this behavior, install Meteor by running:
```bash
npm install -g meteor --ignore-meteor-setup-exec-path
```
(or by setting the environment variable `npm_config_ignore_meteor_setup_exec_path=true`)
### Proxy configuration
Setting the `https_proxy` or `HTTPS_PROXY` environment variable to a valid proxy URL will cause the
downloader to use the configured proxy to retrieve the Meteor files.

View File

@@ -1,7 +1,7 @@
const os = require('os');
const path = require('path');
const METEOR_LATEST_VERSION = '3.0.1';
const METEOR_LATEST_VERSION = '3.0.2';
const sudoUser = process.env.SUDO_USER || '';
function isRoot() {
return process.getuid && process.getuid() === 0;

View File

@@ -302,7 +302,9 @@ async function setup() {
async function setupExecPath() {
if (isWindows()) {
// set for the current session and beyond
child_process.execSync(`setx path "${meteorPath}/;%path%`);
child_process.execSync(
`powershell -c "$path = (Get-Item 'HKCU:\\Environment').GetValue('Path', '', 'DoNotExpandEnvironmentNames'); [Environment]::SetEnvironmentVariable('PATH', \\"${meteorPath};$path\\", 'User');"`,
);
return;
}
const exportCommand = `export PATH=${meteorPath}:$PATH`;

View File

@@ -1,12 +1,12 @@
{
"name": "meteor",
"version": "3.0.1",
"version": "3.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "meteor",
"version": "3.0.1",
"version": "3.0.2",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -15,7 +15,7 @@
"https-proxy-agent": "^5.0.1",
"node-7z": "^2.1.2",
"node-downloader-helper": "^2.1.9",
"rimraf": "^3.0.2",
"rimraf": "^6.0.1",
"semver": "^7.3.7",
"tar": "^6.1.11",
"tmp": "^0.2.1"
@@ -28,6 +28,83 @@
"npm": ">=10.x"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"license": "MIT"
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/7zip-bin": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz",
@@ -52,18 +129,31 @@
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
"balanced-match": "^1.0.0"
}
},
"node_modules/chownr": {
@@ -85,10 +175,23 @@
"node": ">=4"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.3",
@@ -119,11 +222,33 @@
}
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/foreground-child": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@@ -146,31 +271,38 @@
"node": ">=8"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "*"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
@@ -183,21 +315,6 @@
"node": ">= 6"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -211,6 +328,24 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/jackspeak": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
"integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/lodash.defaultsdeep": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
@@ -248,14 +383,18 @@
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "*"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
@@ -342,21 +481,11 @@
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"license": "BlueOak-1.0.0"
},
"node_modules/path-key": {
"version": "3.1.1",
@@ -366,16 +495,54 @@
"node": ">=8"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"glob": "^7.1.3"
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
"integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/path-scurry/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/rimraf": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
"integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==",
"license": "ISC",
"dependencies": {
"glob": "^11.0.0",
"package-json-from-dist": "^1.0.0"
},
"bin": {
"rimraf": "bin.js"
"rimraf": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -414,6 +581,18 @@
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -427,6 +606,21 @@
"node": ">=8"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -438,6 +632,19 @@
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@@ -476,10 +683,105 @@
"node": ">= 8"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"license": "MIT"
},
"node_modules/wrap-ansi/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/wrap-ansi/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/yallist": {
"version": "4.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "meteor",
"version": "3.0.1",
"version": "3.0.2",
"description": "Install Meteor",
"main": "install.js",
"scripts": {
@@ -15,7 +15,7 @@
"https-proxy-agent": "^5.0.1",
"node-7z": "^2.1.2",
"node-downloader-helper": "^2.1.9",
"rimraf": "^3.0.2",
"rimraf": "^6.0.1",
"semver": "^7.3.7",
"tar": "^6.1.11",
"tmp": "^0.2.1"

View File

@@ -2,9 +2,9 @@
"lockfileVersion": 4,
"dependencies": {
"@types/node": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
"integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw=="
"version": "22.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g=="
},
"@types/notp": {
"version": "2.0.5",
@@ -37,9 +37,9 @@
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
},
"undici-types": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg=="
"version": "6.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ=="
}
}
}

View File

@@ -14,7 +14,7 @@ Accounts._check2faEnabled = user => {
};
Accounts._is2faEnabledForUser = async () => {
const user = await Meteor.user();
const user = await Meteor.userAsync();
if (!user) {
throw new Meteor.Error('no-logged-user', 'No user logged in.');
}
@@ -36,7 +36,7 @@ Accounts._isTokenValid = (secret, code) => {
Meteor.methods({
async generate2faActivationQrCode(appName) {
check(appName, String);
const user = await Meteor.user();
const user = await Meteor.userAsync();
if (!user) {
throw new Meteor.Error(
@@ -74,7 +74,7 @@ Meteor.methods({
},
async enableUser2fa(code) {
check(code, String);
const user = await Meteor.user();
const user = await Meteor.userAsync();
if (!user) {
throw new Meteor.Error(400, 'No user logged in.');

View File

@@ -1,37 +1,37 @@
Package.describe({
version: '3.0.0',
version: "3.0.1",
summary:
'Package used to enable two factor authentication through OTP protocol',
"Package used to enable two factor authentication through OTP protocol",
});
Npm.depends({
'node-2fa': '2.0.3',
'qrcode-svg': '1.1.0',
"node-2fa": "2.0.3",
"qrcode-svg": "1.1.0",
});
Package.onUse(function(api) {
api.use(['accounts-base'], ['client', 'server']);
Package.onUse(function (api) {
api.use(["accounts-base"], ["client", "server"]);
// Export Accounts (etc.) to packages using this one.
api.imply('accounts-base', ['client', 'server']);
api.imply("accounts-base", ["client", "server"]);
api.use('ecmascript');
api.use('check', 'server');
api.use("ecmascript");
api.use("check", "server");
api.addFiles(['2fa-client.js'], 'client');
api.addFiles(['2fa-server.js'], 'server');
api.addFiles(["2fa-client.js"], "client");
api.addFiles(["2fa-server.js"], "server");
});
Package.onTest(function(api) {
Package.onTest(function (api) {
api.use([
'accounts-base',
'accounts-password',
'ecmascript',
'tinytest',
'random',
'accounts-2fa',
"accounts-base",
"accounts-password",
"ecmascript",
"tinytest",
"random",
"accounts-2fa",
]);
api.mainModule('server_tests.js', 'server');
api.mainModule('client_tests.js', 'client');
api.mainModule("server_tests.js", "server");
api.mainModule("client_tests.js", "client");
});

View File

@@ -1,4 +1,5 @@
import {Accounts} from "meteor/accounts-base";
import { AccountsClient } from './accounts_client';
const username = 'jsmith';
const password = 'password';
@@ -343,3 +344,25 @@ Tinytest.addAsync('accounts - storage',
});
}
});
Tinytest.addAsync('accounts - should only start subscription when connected', async function (test) {
const { conn, messages, cleanup } = await captureConnectionMessagesClient(test);
const acc = new AccountsClient({
connection: conn,
})
acc.callLoginMethod()
await Meteor._sleepForMs(100);
// The sub call needs to come right after `connect` since this is when `status().connected` gets to be true and
// not after `connected` as it is based on the socket connection status.
const expectedMessages = ['connect', 'method', 'sub', 'connected', 'updated', 'result', 'ready']
const parsedMessages = messages.map(m => m.msg).filter(Boolean).filter(m => m !== 'added')
test.equal(parsedMessages, expectedMessages)
cleanup()
});

View File

@@ -19,6 +19,8 @@ const VALID_CONFIG_KEYS = [
'loginTokenExpirationHours',
'tokenSequenceLength',
'clientStorage',
'ddpUrl',
'connection',
];
/**
@@ -37,8 +39,7 @@ export class AccountsCommon {
// Validate config options keys
for (const key of Object.keys(options)) {
if (!VALID_CONFIG_KEYS.includes(key)) {
// TODO Consider just logging a debug message instead to allow for additional keys in the settings here?
throw new Meteor.Error(`Accounts.config: Invalid key: ${key}`);
console.error(`Accounts.config: Invalid key: ${key}`);
}
}
@@ -163,6 +164,14 @@ export class AccountsCommon {
* @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.
*/
user(options) {
if (Meteor.isServer) {
console.warn([
"`Meteor.user()` is deprecated on the server side.",
" To fetch the current user record on the server,",
" use `Meteor.userAsync()` instead.",
].join("\n"));
}
const self = this;
const userId = self.userId();
const findOne = (...args) => Meteor.isClient
@@ -284,8 +293,7 @@ export class AccountsCommon {
// Validate config options keys
for (const key of Object.keys(options)) {
if (!VALID_CONFIG_KEYS.includes(key)) {
// TODO Consider just logging a debug message instead to allow for additional keys in the settings here?
throw new Meteor.Error(`Accounts.config: Invalid key: ${key}`);
console.error(`Accounts.config: Invalid key: ${key}`);
}
}

View File

@@ -154,7 +154,7 @@ if (Meteor.isClient) {
.then((id) => {
// 4. the server should still return an id after connection
test.isTrue(Meteor.status().connected);
test.isTrue(id);
test.isTrue(id, 'userId exists in the server after reconnect');
})
.finally(done);

View File

@@ -422,7 +422,7 @@ export class AccountsServer extends AccountsCommon {
)
);
methodInvocation.setUserId(userId);
await methodInvocation.setUserId(userId);
return {
id: userId,
@@ -664,7 +664,7 @@ export class AccountsServer extends AccountsCommon {
await accounts.destroyToken(this.userId, token);
}
await accounts._successfulLogout(this.connection, this.userId);
this.setUserId(null);
await this.setUserId(null);
};
// Generates a new login token with the same expiration as the

View File

@@ -10,14 +10,6 @@ Meteor.methods({
}
});
// XXX it'd be cool to also test that the right thing happens if options
// *are* validated, but Accounts._options is global state which makes this hard
// (impossible?)
Tinytest.add(
'accounts - config - validates keys',
test => test.throws(() => Accounts.config({ foo: "bar" }))
);
Tinytest.addAsync('accounts - config - token lifetime', async test => {
const { loginExpirationInDays } = Accounts._options;
Accounts._options.loginExpirationInDays = 2;
@@ -487,28 +479,28 @@ Tinytest.addAsync(
Accounts._options = {};
// test the field is included by default
let user = await Meteor.user();
let user = await Meteor.userAsync();
test.isNotUndefined(user[ignoreFieldName], 'included by default');
// test the field is excluded
Accounts.config({ defaultFieldSelector: { [ignoreFieldName]: 0 } });
user = await Meteor.user();
user = await Meteor.userAsync();
test.isUndefined(user[ignoreFieldName], 'excluded');
user = await Meteor.user({});
user = await Meteor.userAsync({});
test.isUndefined(user[ignoreFieldName], 'excluded {}');
// test the field can still be retrieved if required
user = await Meteor.user({ fields: { [ignoreFieldName]: 1 } });
user = await Meteor.userAsync({ fields: { [ignoreFieldName]: 1 } });
test.isNotUndefined(user[ignoreFieldName], 'field can be retrieved');
test.isUndefined(user.username, 'field can be retrieved username');
// test a combined negative field specifier
user = await Meteor.user({ fields: { username: 0 } });
user = await Meteor.userAsync({ fields: { username: 0 } });
test.isUndefined(user[ignoreFieldName], 'combined field selector');
test.isUndefined(user.username, 'combined field selector username');
// test an explicit request for the full user object
user = await Meteor.user({ fields: {} });
user = await Meteor.userAsync({ fields: {} });
test.isNotUndefined(user[ignoreFieldName], 'full selector');
test.isNotUndefined(user.username, 'full selector username');
@@ -516,7 +508,7 @@ Tinytest.addAsync(
// Test that a custom field gets retrieved properly
Accounts.config({ defaultFieldSelector: { [customField]: 1 } });
user = await Meteor.user()
user = await Meteor.userAsync()
test.isNotUndefined(user[customField]);
test.isUndefined(user.username);
test.isUndefined(user[ignoreFieldName]);
@@ -922,4 +914,3 @@ Tinytest.addAsync('accounts - updateOrCreateUserFromExternalService - Twitter',
// cleanup
await Meteor.users.removeAsync(u1.id);
});

View File

@@ -1,67 +1,67 @@
Package.describe({
summary: 'A user account system',
version: '3.0.0',
summary: "A user account system",
version: "3.0.1",
});
Package.onUse(api => {
api.use('ecmascript', ['client', 'server']);
api.use('ddp-rate-limiter');
api.use('localstorage', 'client');
api.use('tracker', 'client');
api.use('check', 'server');
api.use('random', ['client', 'server']);
api.use('ejson', 'server');
api.use('callback-hook', ['client', 'server']);
api.use('reactive-var', 'client');
api.use('url', ['client', 'server']);
Package.onUse((api) => {
api.use("ecmascript", ["client", "server"]);
api.use("ddp-rate-limiter");
api.use("localstorage", "client");
api.use("tracker", "client");
api.use("check", "server");
api.use("random", ["client", "server"]);
api.use("ejson", "server");
api.use("callback-hook", ["client", "server"]);
api.use("reactive-var", "client");
api.use("url", ["client", "server"]);
// needed for getting the currently logged-in user and handling reconnects
api.use('ddp', ['client', 'server']);
api.use("ddp", ["client", "server"]);
// need this because of the Meteor.users collection but in the future
// we'd probably want to abstract this away
api.use('mongo', ['client', 'server']);
api.use("mongo", ["client", "server"]);
// If the 'blaze' package is loaded, we'll define some helpers like
// {{currentUser}}. If not, no biggie.
api.use('blaze', 'client', { weak: true });
api.use("blaze", "client", { weak: true });
// Allow us to detect 'autopublish', and publish some Meteor.users fields if
// it's loaded.
api.use('autopublish', 'server', { weak: true });
api.use("autopublish", "server", { weak: true });
api.use('oauth-encryption', 'server', { weak: true });
api.use("oauth-encryption", "server", { weak: true });
// Though this "Accounts" symbol is the only official Package export for
// the accounts-base package, modules that import accounts-base will
// have access to anything added to the exports object of the main
// module, including AccountsClient and AccountsServer (those symbols
// just won't be automatically imported as "global" variables).
api.export('Accounts');
api.export("Accounts");
// These main modules import all the other modules that comprise the
// accounts-base package, and define exports that will be accessible to
// modules that import the accounts-base package.
api.mainModule('server_main.js', 'server');
api.mainModule('client_main.js', 'client');
api.mainModule("server_main.js", "server");
api.mainModule("client_main.js", "client");
api.addAssets('accounts-base.d.ts', 'server');
api.addAssets("accounts-base.d.ts", "server");
});
Package.onTest(api => {
Package.onTest((api) => {
api.use([
'accounts-base',
'ecmascript',
'tinytest',
'random',
'test-helpers',
'oauth-encryption',
'ddp',
'accounts-password',
'accounts-2fa',
"accounts-base",
"ecmascript",
"tinytest",
"random",
"test-helpers",
"oauth-encryption",
"ddp",
"accounts-password",
"accounts-2fa",
]);
api.addFiles('accounts_tests_setup.js', 'server');
api.mainModule('server_tests.js', 'server');
api.mainModule('client_tests.js', 'client');
api.addFiles("accounts_tests_setup.js", "server");
api.mainModule("server_tests.js", "server");
api.mainModule("client_tests.js", "client");
});

View File

@@ -150,10 +150,12 @@ const getVerifyEmailToken = (email, test, expect) => {
}));
};
const loggedIn = (test, expect) => expect((error) => {
const loggedIn = (test, expect) => {
return expect(async (error) => {
test.equal(error, undefined);
test.isTrue(Meteor.user());
test.isTrue(await Meteor.user());
});
};
testAsyncMulti("accounts emails - verify email flow", [
function (test, expect) {
@@ -169,7 +171,7 @@ testAsyncMulti("accounts emails - verify email flow", [
loggedIn(test, expect));
},
async function (test, expect) {
const u = await Meteor.user();
const u = await Meteor.userAsync();
test.equal(u.emails.length, 1);
test.equal(u.emails[0].address, this.email);
test.isFalse(u.emails[0].verified);
@@ -187,11 +189,10 @@ testAsyncMulti("accounts emails - verify email flow", [
}));
},
function (test, expect) {
Accounts.verifyEmail(verifyEmailToken,
loggedIn(test, expect));
Accounts.verifyEmail(verifyEmailToken, loggedIn(test, expect));
},
async function (test, expect) {
const u = await Meteor.user();
async function (test) {
const u = await Meteor.userAsync();
test.equal(u.emails.length, 1);
test.equal(u.emails[0].address, this.email);
@@ -201,7 +202,7 @@ testAsyncMulti("accounts emails - verify email flow", [
Accounts.connection.call(
"addEmailForTestAndVerify", this.anotherEmail,
expect(async (error, result) => {
const u = await Meteor.user();
const u = await Meteor.userAsync();
test.isFalse(error);
test.equal(u.emails.length, 2);
@@ -232,7 +233,7 @@ testAsyncMulti("accounts emails - verify email flow", [
Accounts.connection.call(
"addEmailForTestAndVerify", this.anotherEmailCaps,
expect(async (error, result) => {
const u = await Meteor.user();
const u = await Meteor.userAsync();
test.isFalse(error);
test.equal(u.emails.length, 3);
test.equal(u.emails[2].address, this.anotherEmailCaps);
@@ -255,7 +256,7 @@ testAsyncMulti("accounts emails - verify email flow", [
loggedIn(test, expect));
},
async function (test, expect) {
const u = await Meteor.user();
const u = await Meteor.userAsync();
test.equal(u.emails[2].address, this.anotherEmailCaps);
test.isTrue(u.emails[2].verified);

View File

@@ -1,49 +1,49 @@
Package.describe({
summary: 'Password support for accounts',
summary: "Password support for accounts",
// Note: 2.2.0-beta.3 was published during the Meteor 1.6 prerelease
// process, so it might be best to skip to 2.3.x instead of reusing
// 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: '3.0.0',
version: "3.0.1",
});
Npm.depends({
bcrypt: '5.0.1',
bcrypt: "5.0.1",
});
Package.onUse(api => {
api.use(['accounts-base', 'sha', 'ejson', 'ddp'], ['client', 'server']);
Package.onUse((api) => {
api.use(["accounts-base", "sha", "ejson", "ddp"], ["client", "server"]);
// Export Accounts (etc) to packages using this one.
api.imply('accounts-base', ['client', 'server']);
api.imply("accounts-base", ["client", "server"]);
api.use('email', 'server');
api.use('random', 'server');
api.use('check', 'server');
api.use('ecmascript');
api.use("email", "server");
api.use("random", "server");
api.use("check", "server");
api.use("ecmascript");
api.addFiles('email_templates.js', 'server');
api.addFiles('password_server.js', 'server');
api.addFiles('password_client.js', 'client');
api.addFiles("email_templates.js", "server");
api.addFiles("password_server.js", "server");
api.addFiles("password_client.js", "client");
});
Package.onTest(api => {
Package.onTest((api) => {
api.use([
'accounts-password',
'sha',
'tinytest',
'test-helpers',
'tracker',
'accounts-base',
'random',
'email',
'check',
'ddp',
'ecmascript',
"accounts-password",
"sha",
"tinytest",
"test-helpers",
"tracker",
"accounts-base",
"random",
"email",
"check",
"ddp",
"ecmascript",
]);
api.addFiles('password_tests_setup.js', 'server');
api.addFiles('password_tests.js', ['client', 'server']);
api.addFiles('email_tests_setup.js', 'server');
api.addFiles('email_tests.js', 'client');
api.addFiles("password_tests_setup.js", "server");
api.addFiles("password_tests.js", ["client", "server"]);
api.addFiles("email_tests_setup.js", "server");
api.addFiles("email_tests.js", "client");
});

View File

@@ -701,7 +701,7 @@ if (Meteor.isClient) (() => {
// accounts-base/accounts_tests.js, but this is where the tests that
// actually log in are.
async function (test, expect) {
const clientUser = await Meteor.user();
const clientUser = await Meteor.userAsync();
Accounts.connection.call('testMeteorUser', expect((err, result) => {
test.equal(result._id, clientUser._id);
test.equal(result.username, clientUser.username);

View File

@@ -1,20 +1,20 @@
Package.describe({
summary: "Login service for Twitter accounts",
version: '1.5.1',
version: "1.5.2",
});
Package.onUse(api => {
api.use('ecmascript');
api.use('accounts-base', ['client', 'server']);
Package.onUse((api) => {
api.use("ecmascript");
api.use("accounts-base", ["client", "server"]);
// Export Accounts (etc) to packages using this one.
api.imply('accounts-base', ['client', 'server']);
api.use('accounts-oauth', ['client', 'server']);
api.use('twitter-oauth');
api.imply('twitter-oauth');
api.imply("accounts-base", ["client", "server"]);
api.use("accounts-oauth", ["client", "server"]);
api.use("twitter-oauth");
api.imply("twitter-oauth");
api.use('http@1.0.1', ['client', 'server']);
api.use(['accounts-ui', 'twitter-config-ui'], ['client', 'server'], { weak: true });
api.use(["accounts-ui", "twitter-config-ui"], ["client", "server"], {
weak: true,
});
api.addFiles("notice.js");
api.addFiles("twitter.js");

View File

@@ -1035,6 +1035,9 @@ export class Connection {
// Always queues the call before sending the message
// Used, for example, on subscription.[id].stop() to make sure a "sub" message is always called before an "unsub" message
// https://github.com/meteor/meteor/issues/13212
//
// This is part of the actual fix for the rest check:
// https://github.com/meteor/meteor/pull/13236
_sendQueued(obj) {
this._send(obj, true);
}
@@ -1996,7 +1999,7 @@ export class Connection {
// add new subscriptions at the end. this way they take effect after
// the handlers and we don't see flicker.
Object.entries(this._subscriptions).forEach(([id, sub]) => {
this._send({
this._sendQueued({
msg: 'sub',
id: id,
name: sub.name,

View File

@@ -1,66 +1,69 @@
Package.describe({
summary: "Meteor's latency-compensated distributed data client",
version: '3.0.0',
documentation: null
version: "3.0.1",
documentation: null,
});
Npm.depends({
'@sinonjs/fake-timers': '7.0.5'
"@sinonjs/fake-timers": "7.0.5",
});
Package.onUse((api) => {
api.use([
'check',
'random',
'ejson',
'tracker',
'retry',
'id-map',
'ecmascript',
'callback-hook',
'ddp-common',
'reload',
'socket-stream-client',
api.use(
[
"check",
"random",
"ejson",
"tracker",
"retry",
"id-map",
"ecmascript",
"callback-hook",
"ddp-common",
"reload",
"socket-stream-client",
// we depend on _diffObjects, _applyChanges,
'diff-sequence',
// we depend on _diffObjects, _applyChanges,
"diff-sequence",
// _idParse, _idStringify.
'mongo-id'
], ['client', 'server']);
// _idParse, _idStringify.
"mongo-id",
],
["client", "server"]
);
api.use('reload', 'client', { weak: true });
api.use("reload", "client", { weak: true });
// For backcompat where things use Package.ddp.DDP, etc
api.export('DDP');
api.mainModule('client/client.js', 'client');
api.mainModule('server/server.js', 'server');
api.export("DDP");
api.mainModule("client/client.js", "client");
api.mainModule("server/server.js", "server");
});
Package.onTest((api) => {
api.use([
'livedata',
'mongo',
'test-helpers',
'ecmascript',
'underscore',
'tinytest',
'random',
'tracker',
'reactive-var',
'mongo-id',
'diff-sequence',
'ejson',
'ddp-common',
'check'
"livedata",
"mongo",
"test-helpers",
"ecmascript",
"underscore",
"tinytest",
"random",
"tracker",
"reactive-var",
"mongo-id",
"diff-sequence",
"ejson",
"ddp-common",
"check",
]);
api.addFiles('test/stub_stream.js');
api.addFiles('test/livedata_connection_tests.js');
api.addFiles('test/livedata_tests.js');
api.addFiles('test/livedata_test_service.js');
api.addFiles('test/random_stream_tests.js');
api.addFiles('test/async_stubs/client.js', 'client');
api.addFiles('test/async_stubs/server_setup.js', 'server');
api.addFiles('test/livedata_callAsync_tests.js');
api.addFiles("test/stub_stream.js");
api.addFiles("test/livedata_connection_tests.js");
api.addFiles("test/livedata_tests.js");
api.addFiles("test/livedata_test_service.js");
api.addFiles("test/random_stream_tests.js");
api.addFiles("test/async_stubs/client.js", "client");
api.addFiles("test/async_stubs/server_setup.js", "server");
api.addFiles("test/livedata_callAsync_tests.js");
});

View File

@@ -34,9 +34,9 @@ Meteor.methods({
throw e;
}
},
setUserId: function(userId) {
async setUserId(userId) {
check(userId, Match.OneOf(String, null));
this.setUserId(userId);
await this.setUserId(userId);
}
});
@@ -218,14 +218,14 @@ if (Meteor.isServer) {
if (Meteor.isServer) {
Meteor.methods({
setUserIdAfterUnblock: function() {
async setUserIdAfterUnblock() {
this.unblock();
let threw = false;
const originalUserId = this.userId;
try {
// Calling setUserId after unblock should throw an error (and not mutate
// userId).
this.setUserId(originalUserId + 'bla');
await this.setUserId(originalUserId + 'bla');
} catch (e) {
threw = true;
}

View File

@@ -1,8 +1,6 @@
import { DDP } from '../common/namespace.js';
import { Connection } from '../common/livedata_connection.js';
const _sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const callWhenSubReady = async (subName, handle, cb = () => {}) => {
let control = 0;
@@ -12,7 +10,7 @@ const callWhenSubReady = async (subName, handle, cb = () => {}) => {
if (control++ === 1000) {
throw new Error(`Subscribe to ${subName} is taking too long!`);
}
await _sleep(0);
await Meteor._sleepForMs(0);
return;
}
await cb();

View File

@@ -99,11 +99,11 @@ DDPCommon.MethodInvocation = class MethodInvocation {
* @instance
* @param {String | null} userId The value that should be returned by `userId` on this connection.
*/
setUserId(userId) {
async setUserId(userId) {
if (this._calledUnblock) {
throw new Error("Can't call setUserId in a method after calling unblock");
}
this.userId = userId;
this._setUserId(userId);
await this._setUserId(userId);
}
};

View File

@@ -1,27 +1,23 @@
Package.describe({
summary: "Code shared beween ddp-client and ddp-server",
version: '1.4.3',
documentation: null
version: "1.4.4",
documentation: null,
});
Package.onUse(function (api) {
api.use([
'check',
'random',
'ecmascript',
'ejson',
'tracker',
'retry',
], ['client', 'server']);
api.use(
["check", "random", "ecmascript", "ejson", "tracker", "retry"],
["client", "server"]
);
api.addFiles('namespace.js');
api.addFiles("namespace.js");
api.addFiles('heartbeat.js', ['client', 'server']);
api.addFiles('utils.js', ['client', 'server']);
api.addFiles('method_invocation.js', ['client', 'server']);
api.addFiles('random_stream.js', ['client', 'server']);
api.addFiles("heartbeat.js", ["client", "server"]);
api.addFiles("utils.js", ["client", "server"]);
api.addFiles("method_invocation.js", ["client", "server"]);
api.addFiles("random_stream.js", ["client", "server"]);
api.export('DDPCommon');
api.export("DDPCommon");
});
Package.onTest(function (api) {

View File

@@ -396,13 +396,6 @@ var Session = function (server, version, socket, options) {
};
Object.assign(Session.prototype, {
_checkPublishPromiseBeforeSend(f) {
if (!this._publishCursorPromise) {
f();
return;
}
this._publishCursorPromise.finally(() => f());
},
sendReady: function (subscriptionIds) {
var self = this;
if (self._isSending) {
@@ -556,13 +549,11 @@ Object.assign(Session.prototype, {
// It should be a JSON object (it will be stringified).
send: function (msg) {
const self = this;
this._checkPublishPromiseBeforeSend(() => {
if (self.socket) {
if (Meteor._printSentDDP)
Meteor._debug('Sent DDP', DDPCommon.stringifyDDP(msg));
self.socket.send(DDPCommon.stringifyDDP(msg));
}
});
if (self.socket) {
if (Meteor._printSentDDP)
Meteor._debug("Sent DDP", DDPCommon.stringifyDDP(msg));
self.socket.send(DDPCommon.stringifyDDP(msg));
}
},
// Send a connection error.
@@ -627,6 +618,7 @@ Object.assign(Session.prototype, {
var processNext = function () {
var msg = self.inQueue && self.inQueue.shift();
if (!msg) {
self.workerRunning = false;
return;
@@ -653,6 +645,7 @@ Object.assign(Session.prototype, {
msg,
unblock
);
if (Meteor._isPromise(result)) {
result.finally(() => unblock());
} else {
@@ -782,15 +775,13 @@ Object.assign(Session.prototype, {
return;
}
var setUserId = function(userId) {
self._setUserId(userId);
};
var invocation = new DDPCommon.MethodInvocation({
name: msg.method,
isSimulation: false,
userId: self.userId,
setUserId: setUserId,
setUserId(userId) {
return self._setUserId(userId);
},
unblock: unblock,
connection: self.connectionHandle,
randomSeed: randomSeed,
@@ -823,6 +814,8 @@ Object.assign(Session.prototype, {
}
}
const getCurrentMethodInvocationResult = () =>
DDP._CurrentMethodInvocation.withValue(
invocation,
@@ -838,6 +831,7 @@ Object.assign(Session.prototype, {
keyName: 'getCurrentMethodInvocationResult',
}
);
resolve(
DDPServer._CurrentWriteFence.withValue(
fence,
@@ -903,7 +897,7 @@ Object.assign(Session.prototype, {
// Sets the current user id in all appropriate contexts and reruns
// all subscriptions
_setUserId: function(userId) {
async _setUserId(userId) {
var self = this;
if (userId !== null && typeof userId !== "string")
@@ -938,19 +932,21 @@ Object.assign(Session.prototype, {
// DDP._CurrentMethodInvocation set. But DDP._CurrentMethodInvocation is not
// expected to be set inside a publish function, so we temporary unset it.
// Inside a publish function DDP._CurrentPublicationInvocation is set.
DDP._CurrentMethodInvocation.withValue(undefined, function () {
await DDP._CurrentMethodInvocation.withValue(undefined, async function () {
// Save the old named subs, and reset to having no subscriptions.
var oldNamedSubs = self._namedSubs;
self._namedSubs = new Map();
self._universalSubs = [];
oldNamedSubs.forEach(function (sub, subscriptionId) {
var newSub = sub._recreate();
await Promise.all([...oldNamedSubs].map(async ([subscriptionId, sub]) => {
const newSub = sub._recreate();
self._namedSubs.set(subscriptionId, newSub);
// nb: if the handler throws or calls this.error(), it will in fact
// immediately send its 'nosub'. This is OK, though.
newSub._runHandler();
});
await newSub._runHandler();
}));
// Allow newly-created universal subs to be started on our connection in
// parallel with the ones we're spinning up here, and spin up universal
@@ -1207,16 +1203,16 @@ Object.assign(Subscription.prototype, {
resultOrThenable && typeof resultOrThenable.then === 'function';
if (isThenable) {
try {
self._publishHandlerResult(await resultOrThenable);
await self._publishHandlerResult(await resultOrThenable);
} catch(e) {
self.error(e)
}
} else {
self._publishHandlerResult(resultOrThenable);
await self._publishHandlerResult(resultOrThenable);
}
},
_publishHandlerResult: function (res) {
async _publishHandlerResult (res) {
// SPECIAL CASE: Instead of writing their own callbacks that invoke
// this.added/changed/ready/etc, the user can just return a collection
// cursor or array of cursors from the publish function; we call their
@@ -1239,11 +1235,15 @@ Object.assign(Subscription.prototype, {
return c && c._publishCursor;
};
if (isCursor(res)) {
this._publishCursorPromise = res._publishCursor(self).then(() => {
// _publishCursor only returns after the initial added callbacks have run.
// mark subscription as ready.
self.ready();
}).catch((e) => self.error(e));
try {
await res._publishCursor(self);
} catch (e) {
self.error(e);
return;
}
// _publishCursor only returns after the initial added callbacks have run.
// mark subscription as ready.
self.ready();
} else if (_.isArray(res)) {
// Check all the elements are cursors
if (! _.all(res, isCursor)) {
@@ -1254,6 +1254,7 @@ Object.assign(Subscription.prototype, {
// XXX we should support overlapping cursors, but that would require the
// merge box to allow overlap within a subscription
var collectionNames = {};
for (var i = 0; i < res.length; ++i) {
var collectionName = res[i]._getCollectionName();
if (_.has(collectionNames, collectionName)) {
@@ -1263,15 +1264,15 @@ Object.assign(Subscription.prototype, {
return;
}
collectionNames[collectionName] = true;
};
}
this._publishCursorPromise = Promise.all(
res.map(c => c._publishCursor(self))
)
.then(() => {
self.ready();
})
.catch((e) => self.error(e));
try {
await Promise.all(res.map(cur => cur._publishCursor(self)));
} catch (e) {
self.error(e);
return;
}
self.ready();
} else if (res) {
// Truthy values other than cursors or arrays are probably a
// user mistake (possible returning a Mongo document via, say,
@@ -1409,7 +1410,6 @@ Object.assign(Subscription.prototype, {
ids.add(id);
}
this._session._publishCursorPromise = this._publishCursorPromise;
this._session.added(this._subscriptionHandle, collectionName, id, fields);
},
@@ -1863,25 +1863,22 @@ Object.assign(Server.prototype, {
// get the user state from the outer method or publish function, otherwise
// don't allow setUserId to be called
var userId = null;
var setUserId = function() {
let setUserId = () => {
throw new Error("Can't call setUserId on a server initiated method call");
};
var connection = null;
var currentMethodInvocation = DDP._CurrentMethodInvocation.get();
var currentPublicationInvocation = DDP._CurrentPublicationInvocation.get();
var randomSeed = null;
if (currentMethodInvocation) {
userId = currentMethodInvocation.userId;
setUserId = function(userId) {
currentMethodInvocation.setUserId(userId);
};
setUserId = (userId) => currentMethodInvocation.setUserId(userId);
connection = currentMethodInvocation.connection;
randomSeed = DDPCommon.makeRpcSeed(currentMethodInvocation, name);
} else if (currentPublicationInvocation) {
userId = currentPublicationInvocation.userId;
setUserId = function(userId) {
currentPublicationInvocation._session._setUserId(userId);
};
setUserId = (userId) => currentPublicationInvocation._session._setUserId(userId);
connection = currentPublicationInvocation.connection;
}

View File

@@ -7,7 +7,7 @@ function sleep(ms) {
var onSubscription = {};
Meteor.publish('livedata_server_test_sub_async', async function(connectionId) {
await sleep(50);
await Meteor._sleepForMs(50);
var callback = onSubscription[connectionId];
if (callback) callback(this);
this.stop();
@@ -17,7 +17,7 @@ Meteor.publish('livedata_server_test_sub_context_async', async function(
connectionId,
userId
) {
await sleep(50);
await Meteor._sleepForMs(50);
var callback = onSubscription[connectionId];
var methodInvocation = DDP._CurrentMethodInvocation.get();
var publicationInvocation = DDP._CurrentPublicationInvocation.get();
@@ -99,7 +99,7 @@ let onSubscriptions = {};
Meteor.publish({
async publicationObjectAsync() {
await sleep(50);
await Meteor._sleepForMs(50);
let callback = onSubscriptions;
if (callback) callback("publicationObjectAsync");
this.stop();
@@ -108,7 +108,7 @@ Meteor.publish({
Meteor.publish({
publication_object_async: async function() {
await sleep(50);
await Meteor._sleepForMs(50);
let callback = onSubscriptions;
if (callback) callback("publication_object_async");
this.stop();
@@ -116,7 +116,7 @@ Meteor.publish({
});
Meteor.publish('publication_compatibility_async', async function() {
await sleep(50);
await Meteor._sleepForMs(50);
let callback = onSubscriptions;
if (callback) callback("publication_compatibility_async");
this.stop();

View File

@@ -442,3 +442,66 @@ Tinytest.addAsync("livedata server - waiting for Promise", (test, onComplete) =>
.then(onComplete);
})
);
/**
* https://github.com/meteor/meteor/issues/13212
*/
Tinytest.addAsync('livedata server - publish cursor is properly awaited', async function (test) {
let sub = null;
const { conn, messages, cleanup } = await captureConnectionMessages(test);
const coll = new Mongo.Collection('items', {
defineMutationMethods: false,
});
for (let i = 0; i < 10; i++) {
await coll.removeAsync({ _id: `item_${i}` })
await coll.insertAsync({ _id: `item_${i}`, title: `Item #${i}` });
}
const publicationName = `publication_${Random.id()}`
delete Meteor.server.publish_handlers[publicationName];
Meteor.publish(publicationName, async function (count) {
return coll.find({}, { limit: count });
});
const reactiveVar = new ReactiveVar(1);
const computation = Tracker.autorun(() => {
sub = conn.subscribe(publicationName, reactiveVar.get());
});
await Meteor._sleepForMs(100);
reactiveVar.set(2);
await Meteor._sleepForMs(100);
const expectedMessages = ['sub', 'added', 'ready', 'sub', 'unsub', 'added', 'ready', 'nosub']
/**
* There shouldn't ever be `removed` messages here, otherwise the UI will glitch
*/
const parsedMessages = messages.map(m => m.msg)
test.equal(parsedMessages, expectedMessages)
computation.stop();
cleanup()
});
function getTestConnections(test) {
return new Promise((resolve, reject) => {
makeTestConnection(test, (clientConn, serverConn) => {
resolve({ clientConn, serverConn });
}, reject);
})
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

View File

@@ -1,61 +1,77 @@
Package.describe({
summary: "Meteor's latency-compensated distributed data server",
version: '3.0.0',
documentation: null
version: "3.0.1",
documentation: null,
});
Npm.depends({
"permessage-deflate": "0.1.7",
sockjs: "0.3.24"
sockjs: "0.3.24",
});
Package.onUse(function (api) {
api.use(['check', 'random', 'ejson', 'underscore',
'retry', 'mongo-id', 'diff-sequence', 'ecmascript'],
'server');
api.use(
[
"check",
"random",
"ejson",
"underscore",
"retry",
"mongo-id",
"diff-sequence",
"ecmascript",
],
"server"
);
// common functionality
api.use('ddp-common', 'server'); // heartbeat
api.use('ddp-rate-limiter', 'server', {weak: true});
api.use("ddp-common", "server"); // heartbeat
api.use("ddp-rate-limiter", "server", { weak: true });
// Transport
api.use('ddp-client', 'server');
api.imply('ddp-client');
api.use("ddp-client", "server");
api.imply("ddp-client");
api.use(['webapp', 'routepolicy'], 'server');
api.use(["webapp", "routepolicy"], "server");
// Detect whether or not the user wants us to audit argument checks.
api.use(['audit-argument-checks'], 'server', {weak: true});
api.use(["audit-argument-checks"], "server", { weak: true });
// Allow us to detect 'autopublish', so we can print a warning if the user
// runs Meteor.publish while it's loaded.
api.use('autopublish', 'server', {weak: true});
api.use("autopublish", "server", { weak: true });
// If the facts package is loaded, publish some statistics.
api.use('facts-base', 'server', {unordered: true});
api.use("facts-base", "server", { unordered: true });
api.use('callback-hook', 'server');
api.export('DDPServer', 'server');
api.use("callback-hook", "server");
api.export("DDPServer", "server");
api.addFiles('stream_server.js', 'server');
api.addFiles("stream_server.js", "server");
api.addFiles('livedata_server.js', 'server');
api.addFiles('writefence.js', 'server');
api.addFiles('crossbar.js', 'server');
api.addFiles("livedata_server.js", "server");
api.addFiles("writefence.js", "server");
api.addFiles("crossbar.js", "server");
api.addFiles('server_convenience.js', 'server');
api.addFiles("server_convenience.js", "server");
});
Package.onTest(function (api) {
api.use('ecmascript', ['client', 'server']);
api.use('livedata', ['client', 'server']);
api.use('mongo', ['client', 'server']);
api.use('test-helpers', ['client', 'server']);
api.use(['underscore', 'tinytest', 'random', 'tracker', 'minimongo', 'reactive-var']);
api.use("ecmascript", ["client", "server"]);
api.use("ejson", ["client", "server"]);
api.use("livedata", ["client", "server"]);
api.use("mongo", ["client", "server"]);
api.use("test-helpers", ["client", "server"]);
api.use([
"underscore",
"tinytest",
"random",
"tracker",
"minimongo",
"reactive-var",
]);
api.addFiles('livedata_server_tests.js', 'server');
api.addFiles('livedata_server_async_tests.js', 'server');
api.addFiles('session_view_tests.js', ['server']);
api.addFiles('crossbar_tests.js', ['server']);
api.addFiles("livedata_server_tests.js", "server");
api.addFiles("livedata_server_async_tests.js", "server");
api.addFiles("session_view_tests.js", ["server"]);
api.addFiles("crossbar_tests.js", ["server"]);
});

View File

@@ -2,9 +2,9 @@
"lockfileVersion": 4,
"dependencies": {
"@types/node": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
"integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw=="
"version": "22.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g=="
},
"@types/nodemailer": {
"version": "6.4.14",
@@ -57,9 +57,9 @@
"integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ=="
},
"undici-types": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg=="
"version": "6.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ=="
}
}
}

View File

@@ -6,10 +6,6 @@ const CUSTOM_TRANSPORT_SETTINGS = {
email: { service: '1on1', user: 'test', password: 'pwd' },
};
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
// Create dynamic async tests
TEST_CASES.forEach(({ title, options, testCalls }) => {
Tinytest.addAsync(`${title}`, async function (test, onComplete) {
@@ -222,7 +218,7 @@ Tinytest.addAsync(
async function (test) {
Meteor.settings.packages = CUSTOM_TRANSPORT_SETTINGS;
Email.customTransport = async (options) => {
await sleep(3000);
await Meteor._sleepForMs(3000);
test.equal(options.from, 'foo@example.com');
test.equal(options.packageSettings?.service, '1on1');
};

View File

@@ -1,25 +1,25 @@
Package.describe({
summary: 'Send email messages',
version: '3.0.0',
summary: "Send email messages",
version: "3.0.100",
});
Npm.depends({
nodemailer: '6.9.10',
'stream-buffers': '3.0.2',
'@types/nodemailer': '6.4.14',
'nodemailer-openpgp' : '2.2.0'
nodemailer: "6.9.10",
"stream-buffers": "3.0.2",
"@types/nodemailer": "6.4.14",
"nodemailer-openpgp": "2.2.0",
});
Package.onUse(function(api) {
api.use(['ecmascript', 'logging', 'callback-hook'], 'server');
api.addAssets('email.d.ts', 'server');
api.mainModule('email.js', 'server');
api.export(['Email', 'EmailInternals'], 'server');
api.export('EmailTest', 'server', { testOnly: true });
Package.onUse(function (api) {
api.use(["ecmascript", "logging", "callback-hook"], "server");
api.addAssets("email.d.ts", "server");
api.mainModule("email.js", "server");
api.export(["Email", "EmailInternals"], "server");
api.export("EmailTest", "server", { testOnly: true });
});
Package.onTest(function(api) {
api.use('email', 'server');
api.use(['tinytest', 'ecmascript']);
api.addFiles('email_tests.js', 'server');
Package.onTest(function (api) {
api.use("email", "server");
api.use(["tinytest", "ecmascript"]);
api.addFiles("email_tests.js", "server");
});

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: 'The Meteor command-line tool',
version: '3.0.1',
version: '3.0.2',
});
Package.includeTool();

View File

@@ -85,6 +85,10 @@ Meteor.promisify = function (fn, context, errorFirst) {
}
return function () {
var self = this;
var filteredArgs = Array.prototype.slice.call(arguments)
.filter(function (i) { return i !== undefined; });
return new Promise(function (resolve, reject) {
var callback = Meteor.bindEnvironment(function (error, result) {
var _error = error, _result = result;
@@ -100,11 +104,9 @@ Meteor.promisify = function (fn, context, errorFirst) {
resolve(_result);
});
var filteredArgs = Array.prototype.slice.call(arguments)
.filter(function (i) { return i !== undefined; });
filteredArgs.push(callback);
return fn.apply(context || this, filteredArgs);
return fn.apply(context || self, filteredArgs);
});
};
};

View File

@@ -100,3 +100,24 @@ Tinytest.add("environment - startup", function (test) {
});
test.isTrue(called);
});
Tinytest.addAsync("environment - promisify", async function (test) {
function TestClass(value) {
this.value = value;
}
TestClass.prototype.method = function (arg1, arg2, callback) {
var value = this.value;
setTimeout(function () {
callback(null, arg1 + arg2 + value);
}, 0);
};
TestClass.prototype.methodAsync = Meteor.promisify(TestClass.prototype.method);
var instance = new TestClass(5);
test.equal(await instance.methodAsync(1, 2), 8);
var asyncMethodWithContext = Meteor.promisify(instance.method, instance);
test.equal(await asyncMethodWithContext(2, 3), 10);
});

View File

@@ -2,7 +2,7 @@
Package.describe({
summary: "Core Meteor environment",
version: '2.0.0',
version: '2.0.1',
});
Package.registerBuildPlugin({

View File

@@ -3301,9 +3301,7 @@ Tinytest.addAsync('minimongo - observe ordered', async test => {
handle = c
.find({ tags: "flower" }, { reactive: false })
.observe(makecb("c"));
// TODO: think about this one below.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
await sleep(10);
await Meteor._sleepForMs(10);
expect("ac4_ac5_");
// This insert shouldn't trigger a callback because it's not reactive.
await c.insertAsync({ _id: 6, name: "river", tags: ["flower"] });

View File

@@ -1,52 +1,52 @@
Package.describe({
summary: "Meteor's client-side datastore: a port of MongoDB to Javascript",
version: '2.0.0',
version: "2.0.1",
});
Package.onUse(api => {
api.export('LocalCollection');
api.export('Minimongo');
Package.onUse((api) => {
api.export("LocalCollection");
api.export("Minimongo");
api.export('MinimongoTest', { testOnly: true });
api.export('MinimongoError', { testOnly: true });
api.export("MinimongoTest", { testOnly: true });
api.export("MinimongoError", { testOnly: true });
api.use([
// This package is used to get diff results on arrays and objects
'diff-sequence',
'ecmascript',
'ejson',
"diff-sequence",
"ecmascript",
"ejson",
// This package is used for geo-location queries such as $near
'geojson-utils',
'id-map',
'mongo-id',
'ordered-dict',
'random',
'tracker'
"geojson-utils",
"id-map",
"mongo-id",
"ordered-dict",
"random",
"tracker",
]);
// Make weak use of Decimal type on client
api.use('mongo-decimal', 'client', {weak: true});
api.use('mongo-decimal', 'server');
api.use("mongo-decimal", "client", { weak: true });
api.use("mongo-decimal", "server");
api.mainModule('minimongo_client.js', 'client');
api.mainModule('minimongo_server.js', 'server');
api.mainModule("minimongo_client.js", "client");
api.mainModule("minimongo_server.js", "server");
});
Package.onTest(api => {
api.use('minimongo');
Package.onTest((api) => {
api.use("minimongo");
api.use([
'ecmascript',
'ejson',
'mongo-id',
'ordered-dict',
'random',
'reactive-var',
'test-helpers',
'tinytest',
'tracker'
"ecmascript",
"ejson",
"mongo-id",
"ordered-dict",
"random",
"reactive-var",
"test-helpers",
"tinytest",
"tracker",
]);
api.addFiles('minimongo_tests.js');
api.addFiles('minimongo_tests_client.js', 'client');
api.addFiles('minimongo_tests_server.js', 'server');
api.addFiles("minimongo_tests.js");
api.addFiles("minimongo_tests_client.js", "client");
api.addFiles("minimongo_tests_server.js", "server");
});

View File

@@ -153,6 +153,8 @@ Mongo.Collection = function Collection(name, options) {
is_auto: true,
});
}
Mongo._collections.set(this._name, this);
};
Object.assign(Mongo.Collection.prototype, {
@@ -1208,6 +1210,28 @@ Object.assign(Mongo.Collection.prototype, {
},
});
Object.assign(Mongo, {
/**
* @summary Retrieve a Meteor collection instance by name. Only collections defined with [`new Mongo.Collection(...)`](#collections) are available with this method. For plain MongoDB collections, you'll want to look at [`rawDatabase()`](#Mongo-Collection-rawDatabase).
* @locus Anywhere
* @memberof Mongo
* @static
* @param {string} name Name of your collection as it was defined with `new Mongo.Collection()`.
* @returns {Mongo.Collection | undefined}
*/
getCollection(name) {
return this._collections.get(name);
},
/**
* @summary A record of all defined Mongo.Collection instances, indexed by collection name.
* @type {Map<string, Mongo.Collection>}
* @memberof Mongo
* @protected
*/
_collections: new Map(),
})
// Convert the callback to not return a result if there is an error
function wrapCallback(callback, convertResult) {
return (

View File

@@ -464,6 +464,15 @@ Tinytest.addAsync('collection - should not block on cursor mismatch (#12516)',
}
);
Tinytest.add('collection - get collection by name',
function (test) {
const collectionName = 'get' + test.id;
const collection = new Mongo.Collection(collectionName);
test.ok(Mongo.getCollection(collectionName) instanceof Mongo.Collection);
test.equal(Mongo.getCollection(collectionName), collection);
}
);
Meteor.isServer && Tinytest.addAsync('collection - simple add', async function(test){

View File

@@ -83,6 +83,15 @@ export namespace Mongo {
defineMutationMethods?: boolean | undefined;
}
): Collection<T, U>;
/**
* Retrieve a previously defined Mongo.Collection instance by its name. The collection must already have been defined with `new Mongo.Collection(name, ...)`.
* Plain MongoDB collections are not available by this method.
* @param name The name of the collection instance.
*/
getCollection<
TCollection extends Collection<any, any> | undefined = Collection<NpmModuleMongodb.Document> | undefined
>(name: string): TCollection;
}
interface Collection<T extends NpmModuleMongodb.Document, U = T> {
allow<Fn extends Transform<T> = undefined>(options: {

View File

@@ -9,100 +9,115 @@
Package.describe({
summary: "Adaptor for using MongoDB and Minimongo over DDP",
version: '2.0.0',
version: "2.0.1",
});
Npm.depends({
"mongodb-uri": "0.9.7"
"mongodb-uri": "0.9.7",
});
Npm.strip({
mongodb: ["test/"]
mongodb: ["test/"],
});
Package.onUse(function (api) {
api.use('npm-mongo', 'server');
api.use('allow-deny');
api.use("npm-mongo", "server");
api.use("allow-deny");
api.use([
'random',
'ejson',
'minimongo',
'ddp',
'tracker',
'diff-sequence',
'mongo-id',
'check',
'ecmascript',
'mongo-dev-server',
'logging'
"random",
"ejson",
"minimongo",
"ddp",
"tracker",
"diff-sequence",
"mongo-id",
"check",
"ecmascript",
"mongo-dev-server",
"logging",
]);
// Make weak use of Decimal type on client
api.use('mongo-decimal', 'client', {weak: true});
api.use('mongo-decimal', 'server');
api.use("mongo-decimal", "client", { weak: true });
api.use("mongo-decimal", "server");
//api.use('emitter-promise', 'server');
api.use('underscore', 'server');
api.use("underscore", "server");
// Binary Heap data structure is used to optimize oplog observe driver
// performance.
api.use('binary-heap', 'server');
api.use("binary-heap", "server");
// Allow us to detect 'insecure'.
api.use('insecure', {weak: true});
api.use("insecure", { weak: true });
// Allow us to detect 'autopublish', and publish collections if it's loaded.
api.use('autopublish', 'server', {weak: true});
api.use("autopublish", "server", { weak: true });
// Allow us to detect 'disable-oplog', which turns off oplog tailing for your
// app even if it's configured in the environment. (This package will be
// probably be removed before 1.0.)
api.use('disable-oplog', 'server', {weak: true});
api.use("disable-oplog", "server", { weak: true });
// defaultRemoteCollectionDriver gets its deployConfig from something that is
// (for questionable reasons) initialized by the webapp package.
api.use('webapp', 'server', {weak: true});
api.use("webapp", "server", { weak: true });
// If the facts package is loaded, publish some statistics.
api.use('facts-base', 'server', {weak: true});
api.use("facts-base", "server", { weak: true });
api.use('callback-hook', 'server');
api.use("callback-hook", "server");
// Stuff that should be exposed via a real API, but we haven't yet.
api.export('MongoInternals', 'server');
api.export("MongoInternals", "server");
api.export("Mongo");
api.export('ObserveMultiplexer', 'server', {testOnly: true});
api.export("ObserveMultiplexer", "server", { testOnly: true });
api.addFiles(['mongo_driver.js', 'oplog_tailing.js',
'observe_multiplex.js', 'doc_fetcher.js',
'polling_observe_driver.js','oplog_observe_driver.js', 'oplog_v2_converter.js'],
'server');
api.addFiles('local_collection_driver.js', ['client', 'server']);
api.addFiles('remote_collection_driver.js', 'server');
api.addFiles('collection.js', ['client', 'server']);
api.addFiles('connection_options.js', 'server');
api.addAssets('mongo.d.ts', 'server');
api.addFiles(
[
"mongo_driver.js",
"oplog_tailing.js",
"observe_multiplex.js",
"doc_fetcher.js",
"polling_observe_driver.js",
"oplog_observe_driver.js",
"oplog_v2_converter.js",
],
"server"
);
api.addFiles("local_collection_driver.js", ["client", "server"]);
api.addFiles("remote_collection_driver.js", "server");
api.addFiles("collection.js", ["client", "server"]);
api.addFiles("connection_options.js", "server");
api.addAssets("mongo.d.ts", "server");
});
Package.onTest(function (api) {
api.use('mongo');
api.use('check');
api.use('ecmascript');
api.use('npm-mongo', 'server');
api.use("mongo");
api.use("check");
api.use("ecmascript");
api.use("npm-mongo", "server");
//api.use('emitter-promise', 'server');
api.use(['tinytest', 'underscore', 'test-helpers', 'ejson', 'random',
'ddp', 'base64']);
api.use([
"tinytest",
"underscore",
"test-helpers",
"ejson",
"random",
"ddp",
"base64",
]);
// XXX test order dependency: the allow_tests "partial allow" test
// fails if it is run before mongo_livedata_tests.
api.addFiles('mongo_livedata_tests.js', ['client', 'server']);
api.addFiles('upsert_compatibility_test.js', 'server');
api.addFiles('allow_tests.js', ['client', 'server']);
api.addFiles('collection_tests.js', ['client', 'server']);
api.addFiles('collection_async_tests.js', ['client', 'server']);
api.addFiles('observe_changes_tests.js', ['client', 'server']);
api.addFiles('oplog_tests.js', 'server');
api.addFiles('oplog_v2_converter_tests.js', 'server');
api.addFiles('doc_fetcher_tests.js', 'server');
api.addFiles("mongo_livedata_tests.js", ["client", "server"]);
api.addFiles("upsert_compatibility_test.js", "server");
api.addFiles("allow_tests.js", ["client", "server"]);
api.addFiles("collection_tests.js", ["client", "server"]);
api.addFiles("collection_async_tests.js", ["client", "server"]);
api.addFiles("observe_changes_tests.js", ["client", "server"]);
api.addFiles("oplog_tests.js", "server");
api.addFiles("oplog_v2_converter_tests.js", "server");
api.addFiles("doc_fetcher_tests.js", "server");
});

View File

@@ -1,58 +1,58 @@
allow-deny@2.0.0-beta300.6
babel-compiler@7.11.0-beta300.6
babel-runtime@1.5.2-beta300.6
base64@1.0.13-beta300.6
binary-heap@1.0.12-beta300.6
blaze@3.0.0-alpha300.17
boilerplate-generator@2.0.0-beta300.6
caching-compiler@2.0.0-beta300.6
callback-hook@1.6.0-beta300.6
check@1.3.3-beta300.6
core-runtime@1.0.0-beta300.6
ddp@1.4.2-beta300.6
ddp-client@3.0.0-beta300.6
ddp-common@1.4.1-beta300.6
ddp-server@3.0.0-beta300.6
diff-sequence@1.1.3-beta300.6
dynamic-import@0.7.4-beta300.6
ecmascript@0.16.8-beta300.6
ecmascript-runtime@0.8.2-beta300.6
ecmascript-runtime-client@0.12.2-beta300.6
ecmascript-runtime-server@0.11.1-beta300.6
ejson@1.1.4-beta300.6
facts-base@1.0.2-beta300.6
fetch@0.1.4-beta300.6
geojson-utils@1.0.12-beta300.6
htmljs@2.0.0-alpha300.17
id-map@1.2.0-beta300.6
inter-process-messaging@0.1.2-beta300.6
less@4.1.1-beta300.6
local-test:less@4.1.1-beta300.6
logging@1.3.3-beta300.6
meteor@2.0.0-beta300.6
minimongo@2.0.0-beta300.6
modern-browsers@0.1.10-beta300.6
modules@0.19.1-beta300.6
modules-runtime@0.13.2-beta300.6
mongo@2.0.0-beta300.6
mongo-decimal@0.1.4-beta300.6
mongo-dev-server@1.1.1-beta300.6
mongo-id@1.0.9-beta300.6
npm-mongo@4.16.1-beta300.6
observe-sequence@2.0.0-alpha300.17
ordered-dict@1.2.0-beta300.6
promise@1.0.0-beta300.6
random@1.2.2-beta300.6
react-fast-refresh@0.2.8-beta300.6
reactive-var@1.0.13-beta300.6
reload@1.3.2-beta300.6
retry@1.1.1-beta300.6
routepolicy@1.1.2-beta300.6
socket-stream-client@0.5.2-beta300.6
test-helpers@2.0.0-beta300.6
tinytest@2.0.0-beta300.6
tracker@1.3.3-beta300.6
typescript@5.3.3-beta300.6
underscore@1.0.14-beta300.6
webapp@2.0.0-beta300.6
webapp-hashing@1.1.2-beta300.6
allow-deny@2.0.0
babel-compiler@7.11.0
babel-runtime@1.5.2
base64@1.0.13
binary-heap@1.0.12
blaze@3.0.0
boilerplate-generator@2.0.0
caching-compiler@2.0.0
callback-hook@1.6.0
check@1.4.2
core-runtime@1.0.0
ddp@1.4.2
ddp-client@3.0.0
ddp-common@1.4.3
ddp-server@3.0.0
diff-sequence@1.1.3
dynamic-import@0.7.4
ecmascript@0.16.9
ecmascript-runtime@0.8.2
ecmascript-runtime-client@0.12.2
ecmascript-runtime-server@0.11.1
ejson@1.1.4
facts-base@1.0.2
fetch@0.1.5
geojson-utils@1.0.12
htmljs@2.0.1
id-map@1.2.0
inter-process-messaging@0.1.2
less@4.1.1
local-test:less@4.1.1
logging@1.3.5
meteor@2.0.0
minimongo@2.0.0
modern-browsers@0.1.11
modules@0.20.1
modules-runtime@0.13.2
mongo@2.0.0
mongo-decimal@0.1.4-beta300.7
mongo-dev-server@1.1.1
mongo-id@1.0.9
npm-mongo@4.17.3
observe-sequence@2.0.0
ordered-dict@1.2.0
promise@1.0.0
random@1.2.2
react-fast-refresh@0.2.9
reactive-var@1.0.13
reload@1.3.2
retry@1.1.1
routepolicy@1.1.2
socket-stream-client@0.5.3
test-helpers@2.0.0
tinytest@1.3.0
tracker@1.3.4
typescript@5.4.3
underscore@1.6.4
webapp@2.0.0
webapp-hashing@1.1.2

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'less',
version: '4.1.1-beta300.6',
version: '4.1.1',
summary: 'Leaner CSS language',
documentation: 'README.md'
});
@@ -8,8 +8,8 @@ Package.describe({
Package.registerBuildPlugin({
name: "compileLessBatch",
use: [
"caching-compiler@2.0.0-beta300.6",
"ecmascript@0.16.8-beta300.6",
"caching-compiler@2.0.0",
"ecmascript@0.16.9",
],
sources: [
'plugin/compile-less.js'

View File

@@ -56,34 +56,34 @@
}
},
"@aws-sdk/client-cognito-identity": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.624.0.tgz",
"integrity": "sha512-imw3bNptHdhcogU3lwSVlQJsRpTxnkT4bQbchS/qX6+fF0Pk6ERZ+Q0YjzitPqTjkeyAWecUT4riyqv2djo+5w=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.631.0.tgz",
"integrity": "sha512-TXRkgwiLmNpwbiQShtUtSSE4DDHblhjHvtgxtzonzvdlDvYmCmaOwAQgi3HWuHztJtZ9ghf3jKB3N3jxAuKBbA=="
},
"@aws-sdk/client-sso": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.624.0.tgz",
"integrity": "sha512-EX6EF+rJzMPC5dcdsu40xSi2To7GSvdGQNIpe97pD9WvZwM9tRNQnNM4T6HA4gjV1L6Jwk8rBlG/CnveXtLEMw=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.631.0.tgz",
"integrity": "sha512-tpXRQMbbTsKED6GGF0rZbg9Nr0DRCWImopX2lVh4deIeHQfNxeOtq2brqDWiPD593I190xeL/HMChSOmvDXNAw=="
},
"@aws-sdk/client-sso-oidc": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.624.0.tgz",
"integrity": "sha512-Ki2uKYJKKtfHxxZsiMTOvJoVRP6b2pZ1u3rcUb2m/nVgBPUfLdl8ZkGpqE29I+t5/QaS/sEdbn6cgMUZwl+3Dg=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.631.0.tgz",
"integrity": "sha512-afJAssIvsHibVq65qO3Q31NCfSTsPEnyr+PT80uGVAkKev1PJI1AjsxBGUTLtPMV8lrzDzDx5CG9ax1AZ3LG6w=="
},
"@aws-sdk/client-sts": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.624.0.tgz",
"integrity": "sha512-k36fLZCb2nfoV/DKK3jbRgO/Yf7/R80pgYfMiotkGjnZwDmRvNN08z4l06L9C+CieazzkgRxNUzyppsYcYsQaw=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.631.0.tgz",
"integrity": "sha512-Zo/2XDrmNpnSRlQLL8XOCJxuN7UIrGKf4itdjHqtEmD2PqstnYe6IMeEVOELpZ8iktjvsIrVr+qxlIX1QlmgCQ=="
},
"@aws-sdk/core": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.624.0.tgz",
"integrity": "sha512-WyFmPbhRIvtWi7hBp8uSFy+iPpj8ccNV/eX86hwF4irMjfc/FtsGVIAeBXxXM/vGCjkdfEzOnl+tJ2XACD4OXg=="
"version": "3.629.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.629.0.tgz",
"integrity": "sha512-+/ShPU/tyIBM3oY1cnjgNA/tFyHtlWq+wXF9xEKRv19NOpYbWQ+xzNwVjGq8vR07cCRqy/sDQLWPhxjtuV/FiQ=="
},
"@aws-sdk/credential-provider-cognito-identity": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.624.0.tgz",
"integrity": "sha512-gbXaxZP29yzMmEUzsGqUrHpKBnfMBtemvrlufJbaz/MGJNIa5qtJQp7n1LMI5R49DBVUN9s/e9Rf5liyMvlHiw=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.631.0.tgz",
"integrity": "sha512-HU6K7m9R95Hu/oQlLgP77h6NmoT6ABEGAUTDZydPV2G9G5LW3ytOjzLNJT9zO99UGb6L3mIn2IB5LtHOzjthGw=="
},
"@aws-sdk/credential-provider-env": {
"version": "3.620.1",
@@ -96,14 +96,14 @@
"integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg=="
},
"@aws-sdk/credential-provider-ini": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.624.0.tgz",
"integrity": "sha512-mMoNIy7MO2WTBbdqMyLpbt6SZpthE6e0GkRYpsd0yozPt0RZopcBhEh+HG1U9Y1PVODo+jcMk353vAi61CfnhQ=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.631.0.tgz",
"integrity": "sha512-34NmRl6GYlyKTHwiA3C3MjCtmXfoaOXI8b2h7P9eAC8leuIb/51v482g0K6X5P5FqaGY8ZreUq5BMsGjBRr1uQ=="
},
"@aws-sdk/credential-provider-node": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.624.0.tgz",
"integrity": "sha512-vYyGK7oNpd81BdbH5IlmQ6zfaQqU+rPwsKTDDBeLRjshtrGXOEpfoahVpG9PX0ibu32IOWp4ZyXBNyVrnvcMOw=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.631.0.tgz",
"integrity": "sha512-MlYcFknrMQ8RUVe0DMPE09mX8+97s7MLwnVV8l+LFi7m+ZfBz+h6LrohhOXC5elJHf4G3T0r/9Rwct63+zHK/w=="
},
"@aws-sdk/credential-provider-process": {
"version": "3.620.1",
@@ -111,9 +111,9 @@
"integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg=="
},
"@aws-sdk/credential-provider-sso": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.624.0.tgz",
"integrity": "sha512-A02bayIjU9APEPKr3HudrFHEx0WfghoSPsPopckDkW7VBqO4wizzcxr75Q9A3vNX+cwg0wCN6UitTNe6pVlRaQ=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.631.0.tgz",
"integrity": "sha512-k3Mj1Fc7faVOGR+qrwROir/8No35G7gbVL5FuY467x3y0ELa/6w0j/0HM+5eqzGABW7pSL/OHONhWKlYwg7Gkw=="
},
"@aws-sdk/credential-provider-web-identity": {
"version": "3.621.0",
@@ -121,9 +121,9 @@
"integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w=="
},
"@aws-sdk/credential-providers": {
"version": "3.624.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.624.0.tgz",
"integrity": "sha512-SX+F5x/w8laQkhXLd1oww2lTuBDJSxzXWyxuOi25a9s4bMDs0V/wOj885Vr6h8QEGi3F8jZ8aWLwpsm2yuk9BA=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.631.0.tgz",
"integrity": "sha512-1yWtgVeEfOogMNLKMADA0f1+zBsKtG5uojU3krQXaq4VDxHgVs0DsFot6BM2/nH8QH49eME7+C2ME9yXGxKBfA=="
},
"@aws-sdk/middleware-host-header": {
"version": "3.620.0",
@@ -141,9 +141,9 @@
"integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w=="
},
"@aws-sdk/middleware-user-agent": {
"version": "3.620.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz",
"integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.631.0.tgz",
"integrity": "sha512-mpFRFaP9fjXhw8NiRTP+lBPKRKMSKzfCyTXQXrQCSo4fAUaz8LPCc8VdqyoNmx4CLBTRflbEHLx5PfInA0DsrA=="
},
"@aws-sdk/region-config-resolver": {
"version": "3.614.0",
@@ -161,9 +161,9 @@
"integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q=="
},
"@aws-sdk/util-endpoints": {
"version": "3.614.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz",
"integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw=="
"version": "3.631.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.631.0.tgz",
"integrity": "sha512-aavsyk17lK/r6rfVFYLh6/Y0eWvtbclWteJyW9PQLo5mpHPcTj6IbqMN4LHV27Y9IF7oOlbEAQ1CGTfpUlOvTg=="
},
"@aws-sdk/util-locate-window": {
"version": "3.568.0",
@@ -381,9 +381,9 @@
"integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA=="
},
"@types/node": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
"integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw=="
"version": "22.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g=="
},
"@types/webidl-conversions": {
"version": "7.0.3",
@@ -491,9 +491,9 @@
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
},
"undici-types": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg=="
"version": "6.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ=="
},
"uuid": {
"version": "9.0.1",

View File

@@ -3,8 +3,8 @@
Package.describe({
summary: "Wrapper around the mongo npm package",
version: '4.17.3',
documentation: null
version: "4.17.4",
documentation: null,
});
Npm.depends({
@@ -13,9 +13,6 @@ Npm.depends({
Package.onUse(function (api) {
api.addFiles("wrapper.js", "server");
api.export([
"NpmModuleMongodb",
"NpmModuleMongodbVersion",
], "server");
api.addAssets('index.d.ts', 'server');
api.export(["NpmModuleMongodb", "NpmModuleMongodbVersion"], "server");
api.addAssets("index.d.ts", "server");
});

View File

@@ -0,0 +1,29 @@
captureConnectionMessagesClient = async function () {
const messages = []
const conn = DDP.connect(Meteor.absoluteUrl());
const send = conn._stream.send;
conn._stream.send = function (...args) {
// Messages are not really sent when the socket is not connected, duh
if (conn._stream.currentStatus.connected) {
messages.push(EJSON.parse(args[0]));
}
send.apply(this, args);
}
conn._stream.on('message', message => {
return messages.push(EJSON.parse(message));
});
function cleanup() {
conn._stream.send = send
}
return {
conn,
messages,
cleanup
}
};

View File

@@ -52,3 +52,34 @@ makeTestConnection = function (test, succeeded, failed) {
}
);
};
createTestConnectionPromise = function (test) {
return new Promise((resolve, reject) => {
makeTestConnection(test, resolve, reject);
});
};
captureConnectionMessages = async function (test) {
const messages = []
const conn = await createTestConnectionPromise(test);
const send = conn._stream.send;
conn._stream.send = function (...args) {
send.apply(this, args);
messages.push(EJSON.parse(args[0]));
}
conn._stream.on('message', message => messages.push(EJSON.parse(message)));
function cleanup() {
conn._stream.send = send
}
return {
conn,
messages,
cleanup
}
};

View File

@@ -1,17 +1,17 @@
Package.describe({
summary: "Utility functions for tests",
version: '2.0.0',
version: "2.0.1",
});
Package.onUse(function (api) {
api.use([
'ecmascript',
'underscore',
'tracker',
'ejson',
'tinytest',
'random',
'blaze',
"ecmascript",
"underscore",
"tracker",
"ejson",
"tinytest",
"random",
"blaze",
]);
// XXX for connection.js. Not sure this really belongs in
@@ -20,35 +20,51 @@ Package.onUse(function (api) {
// other package tests and not included in the non-test bundle. One
// idea would be to make a new separate package 'ddp-test-helpers' or
// the like.
api.use('ddp');
api.use("ddp");
api.export([
'pollUntil', 'try_all_permutations',
'SeededRandom', 'clickElement', 'blurElement',
'focusElement', 'simulateEvent', 'getStyleProperty', 'canonicalizeHtml',
'renderToDiv', 'clickIt',
'withCallbackLogger', 'testAsyncMulti',
'simplePoll', 'runAndThrowIfNeeded',
'makeTestConnection', 'DomUtils', 'mockBehaviours', 'waitUntil']);
"pollUntil",
"try_all_permutations",
"SeededRandom",
"clickElement",
"blurElement",
"focusElement",
"simulateEvent",
"getStyleProperty",
"canonicalizeHtml",
"renderToDiv",
"clickIt",
"withCallbackLogger",
"testAsyncMulti",
"simplePoll",
"runAndThrowIfNeeded",
"DomUtils",
"mockBehaviours",
"waitUntil",
"makeTestConnection",
"createTestConnectionPromise",
"captureConnectionMessages",
"captureConnectionMessagesClient",
]);
api.addFiles('try_all_permutations.js');
api.addFiles('async_multi.js');
api.addFiles('event_simulation.js');
api.addFiles('seeded_random.js');
api.addFiles('canonicalize_html.js');
api.addFiles('render_div.js');
api.addFiles('current_style.js');
api.addFiles('callback_logger.js');
api.addFiles('mock.js');
api.addFiles('wait.js');
api.addFiles('domutils.js', 'client');
api.addFiles('connection.js', 'server');
api.addFiles("try_all_permutations.js");
api.addFiles("async_multi.js");
api.addFiles("event_simulation.js");
api.addFiles("seeded_random.js");
api.addFiles("canonicalize_html.js");
api.addFiles("render_div.js");
api.addFiles("current_style.js");
api.addFiles("callback_logger.js");
api.addFiles("mock.js");
api.addFiles("wait.js");
api.addFiles("domutils.js", "client");
api.addFiles("connection_server.js", "server");
api.addFiles("connection_client.js", "client");
});
Package.onTest(function (api) {
api.use('tinytest');
api.use(['test-helpers', 'underscore']);
api.addFiles('try_all_permutations_test.js', 'client');
api.addFiles('seeded_random_test.js');
api.use("tinytest");
api.use(["test-helpers", "underscore"]);
api.addFiles("try_all_permutations_test.js", "client");
api.addFiles("seeded_random_test.js");
});

View File

@@ -32,9 +32,9 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
},
"@types/node": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
"integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw=="
"version": "22.3.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g=="
},
"@types/qs": {
"version": "6.9.15",
@@ -469,9 +469,9 @@
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="
},
"undici-types": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg=="
"version": "6.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ=="
},
"unpipe": {
"version": "1.0.0",

View File

@@ -1,46 +1,46 @@
Package.describe({
summary: 'Serves a Meteor app over HTTP',
version: '2.0.0',
summary: "Serves a Meteor app over HTTP",
version: "2.0.1",
});
Npm.depends({
'cookie-parser': '1.4.6',
express: '4.18.2',
'@types/express': '4.17.15',
compression: '1.7.4',
errorhandler: '1.5.1',
parseurl: '1.3.3',
send: '0.18.0',
'stream-to-string': '1.2.1',
qs: '6.11.2',
useragent: '2.3.0',
'@types/connect': '3.4.38',
"cookie-parser": "1.4.6",
express: "4.18.2",
"@types/express": "4.17.15",
compression: "1.7.4",
errorhandler: "1.5.1",
parseurl: "1.3.3",
send: "0.18.0",
"stream-to-string": "1.2.1",
qs: "6.11.2",
useragent: "2.3.0",
"@types/connect": "3.4.38",
});
Npm.strip({
multiparty: ['test/'],
useragent: ['test/'],
multiparty: ["test/"],
useragent: ["test/"],
});
// whitelist plugin is now included in the core
Cordova.depends({
'cordova-plugin-meteor-webapp': '2.0.4',
"cordova-plugin-meteor-webapp": "2.0.4",
});
Package.onUse(function(api) {
api.use('ecmascript');
Package.onUse(function (api) {
api.use("ecmascript");
api.use(
[
'logging',
'underscore',
'routepolicy',
'modern-browsers',
'boilerplate-generator',
'webapp-hashing',
'inter-process-messaging',
'callback-hook',
"logging",
"underscore",
"routepolicy",
"modern-browsers",
"boilerplate-generator",
"webapp-hashing",
"inter-process-messaging",
"callback-hook",
],
'server'
"server"
);
// At response serving time, webapp uses browser-policy if it is loaded. If
@@ -48,24 +48,32 @@ Package.onUse(function(api) {
// (browser-policy depends on webapp). So we don't explicitly depend in any
// way on browser-policy here, but we use it when it is loaded, and it can be
// loaded after webapp.
api.mainModule('webapp_server.js', 'server');
api.export('WebApp', 'server');
api.export('WebAppInternals', 'server');
api.export('main', 'server');
api.mainModule("webapp_server.js", "server");
api.export("WebApp", "server");
api.export("WebAppInternals", "server");
api.export("main", "server");
api.mainModule('webapp_client.js', 'client');
api.export('WebApp', 'client');
api.mainModule("webapp_client.js", "client");
api.export("WebApp", "client");
api.mainModule('webapp_cordova.js', 'web.cordova');
api.addAssets('webapp.d.ts', 'server');
api.mainModule("webapp_cordova.js", "web.cordova");
api.addAssets("webapp.d.ts", "server");
});
Package.onTest(function(api) {
api.use(['tinytest', 'ecmascript', 'webapp', 'http', 'underscore','fetch', 'test-helpers']);
api.addFiles('webapp_tests.js', 'server');
api.addFiles('webapp_client_tests.js', 'client');
api.addFiles('socket_file_tests.js', 'server');
Package.onTest(function (api) {
api.use([
"tinytest",
"ecmascript",
"webapp",
"http",
"underscore",
"fetch",
"test-helpers",
]);
api.addFiles("webapp_tests.js", "server");
api.addFiles("webapp_client_tests.js", "client");
api.addFiles("socket_file_tests.js", "server");
api.addAssets('modern_test_asset.js', 'web.browser');
api.addAssets('legacy_test_asset.js', 'legacy');
api.addAssets("modern_test_asset.js", "web.browser");
api.addAssets("legacy_test_asset.js", "legacy");
});

View File

@@ -1,6 +1,6 @@
{
"track": "METEOR",
"version": "3.0-rc.10",
"version": "3.0.2-beta.4",
"recommended": false,
"official": false,
"description": "Meteor experimental release"

View File

@@ -1,6 +1,6 @@
{
"track": "METEOR",
"version": "3.0.1",
"version": "3.0.2",
"recommended": false,
"official": true,
"description": "The Official Meteor Distribution"

View File

@@ -19,4 +19,4 @@ hot-module-replacement # Update client in development without reloading the pag
~prototype~
static-html # Define static page content in .html files
react-meteor-data@3.0.0-beta300.1 # React higher-order component for reactively tracking Meteor data
react-meteor-data # React higher-order component for reactively tracking Meteor data

View File

@@ -19,4 +19,4 @@ hot-module-replacement # Update client in development without reloading the pag
~prototype~
static-html # Define static page content in .html files
react-meteor-data@3.0.0-beta300.1 # React higher-order component for reactively tracking Meteor data
react-meteor-data # React higher-order component for reactively tracking Meteor data

View File

@@ -19,4 +19,4 @@ hot-module-replacement # Update client in development without reloading the pag
~prototype~
static-html # Define static page content in .html files
react-meteor-data@3.0.0-beta300.1 # React higher-order component for reactively tracking Meteor data
react-meteor-data # React higher-order component for reactively tracking Meteor data

View File

@@ -19,5 +19,5 @@ hot-module-replacement # Update client in development without reloading the pag
~prototype~
static-html # Define static page content in .html files
react-meteor-data@3.0.0-beta300.1 # React higher-order component for reactively tracking Meteor data
react-meteor-data # React higher-order component for reactively tracking Meteor data
zodern:types # Pull in type declarations from other Meteor packages

View File

@@ -12,4 +12,4 @@ es5-shim # ECMAScript 5 compatibility for older browsers
ecmascript # Enable ECMAScript2015+ syntax in app code
shell-server # Server-side component of the `meteor shell` command
less # Support .less files for defining CSS styles
meteortesting:mocha@3.0.3-alpha300.11
meteortesting:mocha@3.0.0

View File

@@ -26,4 +26,4 @@ user:colon-name
underscore@1.0.14-alpha300.11
fetch@0.1.3
jquery
meteortesting:mocha@3.0.3-alpha300.11
meteortesting:mocha@3.0.0

View File

@@ -20,5 +20,5 @@ hot-module-replacement@0.5.4-alpha300.11 # Update client in development without
autopublish@1.0.7 # Publish all data to the clients (for prototyping)
insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
static-html@1.3.3-alpha300.11 # Define static page content in .html files
react-meteor-data@3.0.0-beta300.1 # React higher-order component for reactively tracking Meteor data
meteortesting:mocha@3.0.3-alpha300.11
react-meteor-data@3.0.1 # React higher-order component for reactively tracking Meteor data
meteortesting:mocha@3.0.0

View File

@@ -38,8 +38,8 @@ logging@1.3.1
meteor@1.10.0
meteor-base@1.5.1
meteortesting:browser-tests@1.3.4
meteortesting:mocha@3.0.3-alpha300.11
meteortesting:mocha-core@8.0.1
meteortesting:mocha@3.0.0
meteortesting:mocha-core@8.2.0
minifier-css@1.6.0
minifier-js@2.7.1
minimongo@1.7.0
@@ -58,7 +58,7 @@ ordered-dict@1.1.0
promise@0.12.0
random@1.2.1
react-fast-refresh@0.1.1
react-meteor-data@3.0.0-beta300.1
react-meteor-data@3.0.1
reactive-var@1.0.12
reload@1.3.1
retry@1.1.0

View File

@@ -27,5 +27,5 @@ underscore@1.0.14-beta300.6
import-local-json-module
dummy-compiler
typescript@5.3.3-beta300.6
meteortesting:mocha@3.1.0-beta300.0
meteortesting:mocha-core@8.3.1-beta300.0
meteortesting:mocha@3.0.0
meteortesting:mocha-core@8.2.0

View File

@@ -0,0 +1,58 @@
## v3.0.2, 2024-08-14
### Highlights
* Bump the patch for some packages, so we publish them using Meteor 3 tooling. [PR #13231]
* Fix subscription still resetting documents [PR #13236]
* Fix auth sub sending ready twice on load [PR #13247]
* Remove version constraints from http package in accounts-twitter [PR #13268]
* Deprecate Meteor.user() usage on server side [PR #13288]
#### Breaking Changes
N/A
#### Internal API changes
N/A
#### Migration Steps
Please run the following command to update your project:
```bash
meteor update --release 3.0.2
```
#### Meteor Version Release
* `Bumped packages`:
- accounts-2fa@3.0.1
- accounts-base@3.0.1
- accounts-password@3.0.1
- accounts-twitter@1.5.2
- ddp-client@3.0.1
- ddp-common@1.4.4
- ddp-server@3.0.1
- email@3.0.1
- meteor@2.0.1
- minimongo@2.0.1
- mongo@2.0.1
- npm-mongo@4.17.4
- test-helpers@2.0.1
- webapp@2.0.1
#### Special thanks to
- [@leonardoventurini](https://github.com/leonardoventurini).
- [@StorytellerCZ](https://github.com/StorytellerCZ).
For making this great framework even better!

View File

@@ -44,7 +44,7 @@ features:
- title: Built-in Accounts
icon: 👤
details: Login and Accounts package ready to use with your app. Never rebuilt an authentication system again.
details: Login and Accounts package ready to use with your app. Never rebuild an authentication system again.
- title: Pioneering and Reliable
icon: 🏆