mirror of
https://github.com/meteor/meteor.git
synced 2026-01-11 00:28:02 -05:00
Merge branch 'devel' into underscore/ddp-server
This commit is contained in:
@@ -32,6 +32,24 @@ run_env_change: &run_env_change
|
||||
# Reload sysctl so these are in effect.
|
||||
# sudo sysctl -p
|
||||
|
||||
log_env: &log_env
|
||||
name: Log Environment
|
||||
command: |
|
||||
echo "==> LBS Version"
|
||||
lsb_release -a
|
||||
echo "==> cat /etc/os-release"
|
||||
cat /etc/os-release
|
||||
echo "==> uname -srm"
|
||||
uname -srm
|
||||
echo "==> Node version: $(node --version)"
|
||||
echo "==> NPM version: $(npm --version)"
|
||||
echo "==> Meteor Node version: $(./meteor node --version)"
|
||||
echo "==> Meteor NPM version: $(./meteor npm --version)"
|
||||
echo "==> Dev bundle package.json:"
|
||||
cat ./dev_bundle/lib/package.json
|
||||
echo "==> Dev bundle node_modules:"
|
||||
ls -l ./dev_bundle/lib/node_modules
|
||||
|
||||
# A reusable "run" snippet which enables the continued logging of memoryusage
|
||||
# to a file on disk which can be saved to build artifacts for later analysis.
|
||||
run_log_mem_use: &run_log_mem_use
|
||||
@@ -61,7 +79,7 @@ run_save_node_bin: &run_save_node_bin
|
||||
build_machine_environment: &build_machine_environment
|
||||
# Specify that we want an actual machine (ala Circle 1.0), not a Docker image.
|
||||
docker:
|
||||
- image: meteor/circleci:20231116-android-33-node-14
|
||||
- image: meteor/circleci:2023.12.1-android-34-node-18
|
||||
resource_class: large
|
||||
environment:
|
||||
# This multiplier scales the waitSecs for selftests.
|
||||
@@ -97,36 +115,10 @@ build_machine_environment: &build_machine_environment
|
||||
NUM_GROUPS: 12
|
||||
RUNNING_AVG_LENGTH: 6
|
||||
|
||||
can_disable_fibers: &can_disable_fibers
|
||||
parameters:
|
||||
fibers:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
set_fibers_env: &set_fibers_env
|
||||
name: "Disable Fibers"
|
||||
command: |
|
||||
if [ "<< parameters.fibers >>" == "false" ]; then
|
||||
echo "Disabling Fibers"
|
||||
echo 'export DISABLE_FIBERS=1' >> "$BASH_ENV"
|
||||
source "$BASH_ENV"
|
||||
fi
|
||||
|
||||
|
||||
# Run tests with Fibers and then without.
|
||||
matrix_for_fibers: &matrix_for_fibers
|
||||
matrix:
|
||||
parameters:
|
||||
# If we want to run with Fibers and without, just append false here.
|
||||
fibers: [true]
|
||||
|
||||
|
||||
jobs:
|
||||
Get Ready:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
command: rm -fR /home/circleci/project/*
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
@@ -143,8 +135,16 @@ jobs:
|
||||
- run:
|
||||
name: Combine NPM Shrinkwrap Files
|
||||
command: |
|
||||
for d in packages/*/.npm/package; do cat $d/npm-shrinkwrap.json >> shrinkwraps.txt; done
|
||||
for d in packages/*/.npm/plugin/*; do cat $d/npm-shrinkwrap.json >> shrinkwraps.txt; done
|
||||
for d in packages/*/.npm/package; do
|
||||
if [ -f $d/npm-shrinkwrap.json ]; then
|
||||
cat $d/npm-shrinkwrap.json >> shrinkwraps.txt;
|
||||
fi
|
||||
done
|
||||
for d in packages/*/.npm/plugin/*; do
|
||||
if [ -f $d/npm-shrinkwrap.json ]; then
|
||||
cat $d/npm-shrinkwrap.json >> shrinkwraps.txt;
|
||||
fi
|
||||
done
|
||||
- restore_cache:
|
||||
keys:
|
||||
- package-npm-deps-cache-group1-v3-{{ checksum "shrinkwraps.txt" }}
|
||||
@@ -171,15 +171,19 @@ jobs:
|
||||
- run:
|
||||
name: Clear npm cache
|
||||
command: ./meteor npm cache clear --force
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: Get Ready
|
||||
command: |
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
pushd tools
|
||||
npm install @types/node@14.17.6 --save-dev
|
||||
cd dev_bundle/lib
|
||||
../../meteor npm install @types/node@20.10.5 --save-dev
|
||||
# Ensure that meteor/tools has no TypeScript errors.
|
||||
../meteor npx tsc --noEmit --skipLibCheck
|
||||
popd
|
||||
../../meteor npm install -g typescript
|
||||
cd ../../
|
||||
# tools/node_modules is a symlink, but starting on NPM 7, this symlinks are deleted https://github.com/npm/cli/issues/3669
|
||||
# so we are copying the node_modules to tools
|
||||
./meteor --get-ready
|
||||
# shouldn't take longer than 60 minutes
|
||||
no_output_timeout: 60m
|
||||
@@ -194,7 +198,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Isolated Tests:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -203,7 +206,6 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
@@ -216,6 +218,8 @@ jobs:
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--headless \
|
||||
no_output_timeout: 20m
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Custom Warehouse Tests)"
|
||||
command: |
|
||||
@@ -238,7 +242,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 0:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -247,10 +250,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 0)"
|
||||
command: |
|
||||
@@ -280,7 +284,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 1:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -289,10 +292,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 1)"
|
||||
command: |
|
||||
@@ -322,7 +326,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 2:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -331,7 +334,8 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
@@ -364,7 +368,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 3:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -373,7 +376,8 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
@@ -406,7 +410,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 4:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -415,10 +418,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 4)"
|
||||
command: |
|
||||
@@ -448,7 +452,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 5:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -457,10 +460,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 5)"
|
||||
command: |
|
||||
@@ -490,7 +494,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 6:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -499,10 +502,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 6)"
|
||||
command: |
|
||||
@@ -532,7 +536,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 7:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -541,10 +544,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 7)"
|
||||
command: |
|
||||
@@ -574,7 +578,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 8:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -583,10 +586,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 8)"
|
||||
command: |
|
||||
@@ -616,7 +620,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 9:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -625,10 +628,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 9)"
|
||||
command: |
|
||||
@@ -658,7 +662,6 @@ jobs:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Group 10:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
@@ -667,10 +670,11 @@ jobs:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *set_fibers_env
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 10)"
|
||||
command: |
|
||||
@@ -711,6 +715,8 @@ jobs:
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
<<: *log_env
|
||||
- run:
|
||||
name: "Running self-test (Test Group 11)"
|
||||
command: |
|
||||
@@ -724,7 +730,7 @@ jobs:
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/11.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 30m
|
||||
no_output_timeout: 35m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
@@ -739,47 +745,36 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
# Test the JSDoc declarations which live within this codebase against the
|
||||
# Meteor Docs (https://github.com/meteor/docs) repository, where they'll
|
||||
# eventually be consumed. This test aims to provide an early warning of
|
||||
# potentially breaking changes, so they aren't discovered when the docs are
|
||||
# next updated, which generally occurs during major Meteor version releases
|
||||
# (for example, 1.4 to 1.5, 1.5 to 1.6).
|
||||
# Test the JSDoc declarations which live within this codebase.
|
||||
# Now the docs live in this repo, we can test them here, every PR is tested.
|
||||
Docs:
|
||||
docker:
|
||||
# This Node version should match that in the meteor/docs CircleCI config.
|
||||
- image: meteor/circleci:android-28-node-12
|
||||
- image: meteor/circleci:2023.12.1-android-34-node-20
|
||||
resource_class: large
|
||||
environment:
|
||||
CHECKOUT_METEOR_DOCS: /home/circleci/test_docs
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
name: Cloning "meteor/docs" Repository's "update-to-meteor-1.9" branch
|
||||
name: Cloning "meteor" Repository's current branch
|
||||
command: |
|
||||
git clone --branch update-to-meteor-1.9 https://github.com/meteor/docs.git ${CHECKOUT_METEOR_DOCS}
|
||||
# The "docs" repository normally brings in the Meteor code as a Git
|
||||
# submodule checked out into the "code" directory. As the goal of this
|
||||
# test is to run it against the _current_ repository's code, we'll move
|
||||
# the "code" directory out of the way and move the checkout (of meteor)
|
||||
# into that directory, rather than the default $CIRCLE_WORKING_DIRECTORY.
|
||||
- checkout
|
||||
- run:
|
||||
name: Move Meteor checkout into docs repository's "code" directory
|
||||
command: |
|
||||
rmdir "${CHECKOUT_METEOR_DOCS}/code"
|
||||
# $CIRCLE_WORKING_DIRECTORY uses a tilde, so expand it to $HOME.
|
||||
mv "${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}" \
|
||||
"${CHECKOUT_METEOR_DOCS}/code"
|
||||
if [[ -n "$CIRCLE_PULL_REQUEST" ]]; then
|
||||
PR_NUMBER=$(echo $CIRCLE_PULL_REQUEST | sed 's|.*/pull/\([0-9]*\)|\1|')
|
||||
PR_BRANCH=$(curl -s https://api.github.com/repos/meteor/meteor/pulls/$PR_NUMBER | jq -r .head.ref)
|
||||
git clone --branch $PR_BRANCH https://github.com/meteor/meteor.git ${CHECKOUT_METEOR_DOCS}
|
||||
else
|
||||
git clone --branch $CIRCLE_BRANCH https://github.com/meteor/meteor.git ${CHECKOUT_METEOR_DOCS}
|
||||
fi
|
||||
# Run almost the same steps the meteor/docs repository runs, minus deploy.
|
||||
- run:
|
||||
name: Generating Meteor documentation for JSDoc testing
|
||||
command: |
|
||||
cd ${CHECKOUT_METEOR_DOCS}
|
||||
cd ${CHECKOUT_METEOR_DOCS}/docs
|
||||
npm install
|
||||
npm test
|
||||
|
||||
Clean Up:
|
||||
<<: *can_disable_fibers
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- attach_workspace:
|
||||
@@ -862,58 +857,45 @@ workflows:
|
||||
- Docs
|
||||
- Get Ready
|
||||
- Isolated Tests:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 0:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 1:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 2:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 3:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 4:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 5:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 6:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 7:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 8:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 9:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 10:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Group 11:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Clean Up:
|
||||
<<: *matrix_for_fibers
|
||||
requires:
|
||||
- Isolated Tests
|
||||
- Test Group 0
|
||||
|
||||
49
.envrc
Normal file
49
.envrc
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/bin/env zsh
|
||||
|
||||
#
|
||||
# Commands and shortcuts for Meteor core development, you can load these in your terminal by running `source .envrc`.
|
||||
# Or by adding `[[ -s .envrc ]] && source .envrc` to your `.zshrc` or `.bashrc`.
|
||||
#
|
||||
|
||||
export ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
|
||||
########
|
||||
# Core #
|
||||
########
|
||||
|
||||
function @meteor {
|
||||
"$ROOT_DIR/meteor" "$@"
|
||||
}
|
||||
|
||||
function @test-packages {
|
||||
TINYTEST_FILTER="$1" @meteor test-packages --exclude-archs=web.browser.legacy,web.cordova
|
||||
}
|
||||
|
||||
function @test-self {
|
||||
@meteor self-test "$@"
|
||||
}
|
||||
|
||||
function @check-syntax {
|
||||
node "$ROOT_DIR/scripts/admin/check-legacy-syntax/check-syntax.js"
|
||||
}
|
||||
|
||||
function @generate-dev-bundle {
|
||||
rm -rf $ROOT_DIR/dev_bundle*
|
||||
"$ROOT_DIR/scripts/generate-dev-bundle.sh"
|
||||
}
|
||||
|
||||
function @init-submodule {
|
||||
git submodule update --init --recursive
|
||||
}
|
||||
|
||||
#################
|
||||
# Documentation #
|
||||
#################
|
||||
|
||||
function @docs-start {
|
||||
npm run docs:dev --prefix "$ROOT_DIR/v3-docs/docs"
|
||||
}
|
||||
|
||||
function @docs-migration-start {
|
||||
npm run docs:dev --prefix "$ROOT_DIR/v3-docs/v3-migration-docs"
|
||||
}
|
||||
@@ -2,9 +2,7 @@ android_bundle/
|
||||
dev_bundle/
|
||||
docs/
|
||||
examples/
|
||||
packages/
|
||||
scripts/
|
||||
tools/
|
||||
!tools/*.js
|
||||
!tools/isobuild/*.js
|
||||
!tools/catalog/*.js
|
||||
|
||||
2
.github/workflows/check-code-style.yml
vendored
2
.github/workflows/check-code-style.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 14.x
|
||||
node-version: 20.x
|
||||
- run: npm ci
|
||||
- name: Run ESLint@8
|
||||
run: npx eslint@8 "./npm-packages/meteor-installer/**/*.js"
|
||||
|
||||
4
.github/workflows/check-syntax.yml
vendored
4
.github/workflows/check-syntax.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
- run: cd scripts/admin/check-legacy-syntax && npm ci
|
||||
- name: Check syntax
|
||||
run: cd scripts/admin/check-legacy-syntax && node check-syntax.js
|
||||
run: cd scripts/admin/check-legacy-syntax && node check-syntax.js
|
||||
|
||||
54
.github/workflows/meteor-selftest-windows.yml
vendored
Normal file
54
.github/workflows/meteor-selftest-windows.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Meteor Selftest Windows
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
push:
|
||||
branches:
|
||||
- devel
|
||||
- 2.x.x
|
||||
|
||||
env:
|
||||
METEOR_PRETTY_OUTPUT: 0
|
||||
SELF_TEST_TOOL_NODE_FLAGS: ' '
|
||||
TOOL_NODE_FLAGS: --expose-gc
|
||||
TIMEOUT_SCALE_FACTOR: 20
|
||||
METEOR_HEADLESS: true
|
||||
SELF_TEST_EXCLUDE: '^NULL-LEAVE-THIS-HERE-NULL$'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: windows-2019-meteor
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20.x
|
||||
|
||||
- name: Install dependencies
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = "C:\Program Files\7-Zip;$env:PATH"
|
||||
.\scripts\windows\ci\install.ps1
|
||||
|
||||
- name: Run tests
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = "C:\Program Files\7-Zip;$env:PATH"
|
||||
.\scripts\windows\ci\test.ps1
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.\dev_bundle
|
||||
.\.babel-cache
|
||||
.\.meteor
|
||||
key: ${{ runner.os }}-meteor-${{ hashFiles('**/package-lock.json') }}
|
||||
@@ -16,15 +16,12 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: npm-packages/eslint-plugin-meteor
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
5
.github/workflows/npm-meteor-babel.yml
vendored
5
.github/workflows/npm-meteor-babel.yml
vendored
@@ -16,15 +16,12 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: npm-packages/meteor-babel
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
node-version: 14.x
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run test
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -29,3 +29,9 @@ mongo-test-output
|
||||
|
||||
# core packages shouldn't have .versions files
|
||||
packages/*/.versions
|
||||
|
||||
# packages shouldn't have .npm on Git
|
||||
packages/**/.npm
|
||||
|
||||
# doc files should not be committed
|
||||
packages/**/*.docs.js
|
||||
|
||||
21
.travis.yml
21
.travis.yml
@@ -1,8 +1,10 @@
|
||||
language: node_js
|
||||
os: linux
|
||||
dist: jammy
|
||||
sudo: required
|
||||
services: xvfb
|
||||
node_js:
|
||||
- "14.21.3"
|
||||
- "20.15.1"
|
||||
cache:
|
||||
directories:
|
||||
- ".meteor"
|
||||
@@ -11,17 +13,20 @@ script:
|
||||
- travis_retry ./packages/test-in-console/run.sh
|
||||
env:
|
||||
global:
|
||||
- CXX=g++11
|
||||
- CXX=g++-12
|
||||
- phantom=false
|
||||
- PUPPETEER_DOWNLOAD_PATH=~/.npm/chromium
|
||||
jobs:
|
||||
# We don't want to run the tests without fibers anymore.
|
||||
# - DISABLE_FIBERS=1
|
||||
# Use a different flag, since node would use false as a string.
|
||||
- FIBERS_ENABLED=1
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-11
|
||||
- g++-12
|
||||
- libnss3
|
||||
|
||||
before_install:
|
||||
- cat /etc/apt/sources.list
|
||||
- python3 --version
|
||||
- echo "deb http://archive.ubuntu.com/ubuntu jammy main universe" | sudo tee -a /etc/apt/sources.list
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -y libnss3
|
||||
|
||||
@@ -43,13 +43,19 @@ can run Meteor directly from a Git checkout using these steps:
|
||||
$ /path/to/meteor-checkout/meteor run
|
||||
```
|
||||
|
||||
> _Tip:_ Consider making an easy-to-run alias for frequent use:
|
||||
> _Tip 1:_ Consider making an easy-to-run alias for frequent use:
|
||||
>
|
||||
> alias mymeteor=/path/to-meteor-checkout/meteor
|
||||
>
|
||||
> This allows the use of `mymeteor` in place of `meteor`. To persist this
|
||||
> across shell logouts, simply add it to `~/.bashrc` or `.zshrc`.
|
||||
|
||||
> _Tip 2:_ When working with meteor tool, it may be helpful to use the debugger to check what's happening. You can do this using the following flag:
|
||||
>
|
||||
> TOOL_NODE_FLAGS="--inspect-brk" mymeteor
|
||||
>
|
||||
> Then you can use the chrome debugger inside `chrome://inspect`.
|
||||
|
||||
### Notes when running from a checkout
|
||||
|
||||
The following are some distinct differences you must pay attention to when running Meteor from a checkout:
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
|
||||
[](https://app.travis-ci.com/github/meteor/meteor)
|
||||
[](https://app.circleci.com/pipelines/github/meteor/meteor?branch=devel)
|
||||
[](https://meteor.com)
|
||||
[](https://guide.meteor.com/3.0-migration)
|
||||
[](https://meteor.com)
|
||||

|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
47
appveyor.yml
47
appveyor.yml
@@ -1,47 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /^dev-bundle-/
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
clone_folder: C:\projects\meteor
|
||||
image: Visual Studio 2019
|
||||
|
||||
environment:
|
||||
METEOR_PRETTY_OUTPUT: 0
|
||||
SELF_TEST_TOOL_NODE_FLAGS: " "
|
||||
TOOL_NODE_FLAGS: --expose-gc
|
||||
TIMEOUT_SCALE_FACTOR: 8
|
||||
METEOR_HEADLESS: true
|
||||
SELF_TEST_EXCLUDE: "^NULL-LEAVE-THIS-HERE-NULL$"
|
||||
platform:
|
||||
- x64
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- platform: x64
|
||||
|
||||
# We don't need the actual "build", just the tests.
|
||||
build: off
|
||||
|
||||
install:
|
||||
- ps: C:\projects\meteor\scripts\windows\appveyor\install.ps1
|
||||
|
||||
test_script:
|
||||
- ps: C:\projects\meteor\scripts\windows\appveyor\test.ps1
|
||||
|
||||
on_failure:
|
||||
- ps: |
|
||||
$npmLogsDir = "$($Env:AppData)\npm-cache\_logs"
|
||||
If (Test-Path "$npmLogsDir") {
|
||||
Get-ChildItem "${npmLogsDir}\*.log" |
|
||||
% { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
}
|
||||
|
||||
cache:
|
||||
- dev_bundle -> meteor
|
||||
- .babel-cache -> meteor
|
||||
- .meteor
|
||||
@@ -64,6 +64,7 @@ sidebar_categories:
|
||||
- api/packagejs
|
||||
- api/mobile-config
|
||||
- api/environment
|
||||
- api/top-level-await
|
||||
Packages:
|
||||
- packages/accounts-ui
|
||||
- packages/accounts-passwordless
|
||||
|
||||
@@ -12,18 +12,37 @@ To get which branches were merged into release you can search in the GitHub
|
||||
repo by using this query:
|
||||
|
||||
```
|
||||
is:pr base:<release-branch-name> is:merged
|
||||
is:pr base:<release-branch-name> is:merged
|
||||
```
|
||||
|
||||
or in GH Cli:
|
||||
|
||||
```bash
|
||||
gh pr list --state merged --base <release-branch-name>
|
||||
```
|
||||
|
||||
note that it may not be as useful as the first one, since it will not show the
|
||||
Authors and other related information.
|
||||
|
||||
## Why?
|
||||
|
||||
Computers with lower memory/ IDEs with high memory usage can have problems with
|
||||
the changelog file(~10k lines). This is a way to reduce the memory usage of the changelog, also creating a more
|
||||
organized changelog, since all the files will be reflecting at least one version.
|
||||
|
||||
## Update ordering.
|
||||
|
||||
If you want to make sure that the changelog is correcly ordered, take a look at the `order-packages.js` file.
|
||||
to use it, run the command below:
|
||||
|
||||
```bash
|
||||
node order-packages.js versions/3.0.md
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
node order-packages.js versions/<your-version>.md
|
||||
```
|
||||
|
||||
it will update the file with the correct ordering(this will override the file).
|
||||
81
docs/generators/changelog/order-packages.js
Normal file
81
docs/generators/changelog/order-packages.js
Normal file
@@ -0,0 +1,81 @@
|
||||
const fs = require("fs").promises;
|
||||
|
||||
// we want to get the strings that are between #### Breaking Changes and #### New Public API
|
||||
// then we will create a map with the package name and the version for example:
|
||||
//
|
||||
// - `accounts-2fa@3.0.0`:
|
||||
|
||||
// - Some methods are now async. See below:
|
||||
// - `Accounts._is2faEnabledForUser`
|
||||
// - `(Meteor Method) - generate2faActivationQrCode`
|
||||
// - `(Meteor Method) - enableUser2fa`
|
||||
// - `(Meteor Method) - disableUser2fa`
|
||||
// - `(Meteor Method) - has2faEnabled`
|
||||
|
||||
// will be converted to:
|
||||
// {"accounts-2fa@3.0.0": ` - Some methods are now async. See below:
|
||||
// - `Accounts._is2faEnabledForUser`
|
||||
// - `(Meteor Method) - generate2faActivationQrCode`
|
||||
// - `(Meteor Method) - enableUser2fa`
|
||||
// - `(Meteor Method) - disableUser2fa`
|
||||
// - `(Meteor Method) - has2faEnabled``
|
||||
// }
|
||||
|
||||
// then we will iterate and order the packages in alphabetical order and write again to the file.
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} path
|
||||
* @returns {Promise<[string, null] | ["", Error]>}
|
||||
*/
|
||||
async function getFile(path) {
|
||||
try {
|
||||
const data = await fs.readFile(path, "utf8");
|
||||
return [data, null];
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return ["", new Error("could not read file")];
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [filePath] = process.argv.slice(2);
|
||||
const [code, error] = await getFile(filePath);
|
||||
if (error) throw error;
|
||||
|
||||
const regex = /#### Breaking Changes([\s\S]*?)#### New Public API/gm;
|
||||
const matches = code.match(regex).join("\n").split("\n");
|
||||
|
||||
let objectMap = {};
|
||||
let currentWorkingPackage = "";
|
||||
for (const line of matches) {
|
||||
if (line.startsWith("-")) {
|
||||
const packageName = line
|
||||
.replace("-", "")
|
||||
.replace("`:", "")
|
||||
.replace("`", "")
|
||||
.trim();
|
||||
objectMap[packageName] = "";
|
||||
currentWorkingPackage = packageName;
|
||||
continue;
|
||||
}
|
||||
objectMap[currentWorkingPackage] += line + "\n";
|
||||
}
|
||||
// sorting acc
|
||||
const result = Object.keys(objectMap)
|
||||
.reduce((acc, key) => {
|
||||
if (key === "") return acc;
|
||||
acc.push({ key, value: objectMap[key]});
|
||||
return acc;
|
||||
}, [])
|
||||
.sort((a, b) => a.key.localeCompare(b.key))
|
||||
.reduce((acc, { key, value }) => {
|
||||
return acc + `- \`${key}\`:\n${value}`;
|
||||
}, "")
|
||||
|
||||
const newCode = code.replace(regex, `#### Breaking Changes\n\n${result}`);
|
||||
|
||||
await fs.writeFile(filePath, newCode);
|
||||
}
|
||||
|
||||
main().then(() => console.log("done"));
|
||||
@@ -1,56 +1,49 @@
|
||||
const _fs = require('fs');
|
||||
const _fs = require("fs");
|
||||
const fs = _fs.promises;
|
||||
|
||||
function getPackageVersion(packageName) {
|
||||
function getFile(path) {
|
||||
try {
|
||||
const data = _fs.readFileSync(path, 'utf8');
|
||||
const data = _fs.readFileSync(path, "utf8");
|
||||
return [data, null];
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return ['', e];
|
||||
return ["", e];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const [code, error] = getFile(`../packages/${ packageName }/package.js`);
|
||||
if (error) return 'ERR_NO_VERSION';
|
||||
const [code, error] = getFile(`../packages/${packageName}/package.js`);
|
||||
if (error) return "";
|
||||
for (const line of code.split(/\n/)) {
|
||||
// verify if the line has a version
|
||||
if (!line.includes('version:')) continue;
|
||||
if (!line.includes("version:")) continue;
|
||||
|
||||
//Package.describe({
|
||||
// summary: 'some description.',
|
||||
// version: '1.2.3' <--- this is the line we want, we assure that it has a version in the previous if
|
||||
//});
|
||||
const [_, versionValue] = line.split(':');
|
||||
const [_, versionValue] = line.split(":");
|
||||
if (!versionValue) continue;
|
||||
const removeQuotes =
|
||||
(v) =>
|
||||
v
|
||||
.trim()
|
||||
.replace(',', '')
|
||||
.replace(/'/g, '')
|
||||
.replace(/"/g, '');
|
||||
|
||||
if (versionValue.includes('-')) return removeQuotes(versionValue.split('-')[0]);
|
||||
const removeQuotes = (v) =>
|
||||
v.trim().replace(",", "").replace(/'/g, "").replace(/"/g, "");
|
||||
if (versionValue.includes("-"))
|
||||
return removeQuotes(versionValue.split("-")[0]);
|
||||
return removeQuotes(versionValue);
|
||||
}
|
||||
}
|
||||
|
||||
const main = async () => {
|
||||
try {
|
||||
console.log('started concatenating files');
|
||||
const files = await fs.readdir('./generators/changelog/versions', 'utf8');
|
||||
console.log("started concatenating files");
|
||||
const files = await fs.readdir("./generators/changelog/versions", "utf8");
|
||||
const filesStream = files
|
||||
.map(file => {
|
||||
console.log(`reading file: ${ file }`);
|
||||
.map((file) => {
|
||||
console.log(`reading file: ${file}`);
|
||||
return {
|
||||
fileName: file,
|
||||
buf : fs.readFile(`./generators/changelog/versions/${ file }`, 'utf8')
|
||||
buf: fs.readFile(`./generators/changelog/versions/${file}`, "utf8"),
|
||||
};
|
||||
})
|
||||
.map(async ({buf, fileName}, index) => {
|
||||
.map(async ({ buf, fileName }, index) => {
|
||||
// first file we don't do anything
|
||||
// Big file and does not follow the new standard
|
||||
if (index === 0) return buf;
|
||||
@@ -58,53 +51,60 @@ const main = async () => {
|
||||
/**
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
const contribuitors = new Set()
|
||||
const contribuitors = new Set();
|
||||
|
||||
// DSL Replacers
|
||||
// [PR #123] -> [PR #123](https://github.com/meteor/meteor/pull/123)
|
||||
// [GH meteor/meteor] -> [meteor/meteor](https://github.com/meteor/meteor)
|
||||
// package-name@get-version -> package-name@1.3.3
|
||||
|
||||
const file = content
|
||||
.replace(/\[PR #(\d+)\]/g, (_, number) => `[PR](https://github.com/meteor/meteor/pull/${ number })`)
|
||||
const file = content
|
||||
.replace(
|
||||
/\[PR #(\d+)\]/g,
|
||||
(_, number) =>
|
||||
`[PR](https://github.com/meteor/meteor/pull/${number})`
|
||||
)
|
||||
.replace(/\[GH ([^\]]+)\]/g, (_, name) => {
|
||||
contribuitors.add(name);
|
||||
return `[${ name }](https://github.com/${ name })`
|
||||
return `[${name}](https://github.com/${name})`;
|
||||
})
|
||||
.replace(/([a-z0-9-]+)@get-version/g, (_, name) => `${ name }@${ getPackageVersion(name) }`);
|
||||
.replace(
|
||||
/([a-z0-9-]+)@get-version/g,
|
||||
(_, name) => `${name}@${getPackageVersion(name)}`
|
||||
);
|
||||
|
||||
// already have the contribuitors thanks in the file
|
||||
if (
|
||||
file.includes('## Contributors') ||
|
||||
file.includes('#### Special thanks to') || // this must stay here for legacy reasons
|
||||
file.includes('[//]: # (Do not edit this file by hand.)')
|
||||
) return file;
|
||||
file.includes('## Contributors') ||
|
||||
file.includes("#### Special thanks to") || // this must stay here for legacy reasons
|
||||
file.includes("[//]: # (Do not edit this file by hand.)")
|
||||
)
|
||||
return file;
|
||||
|
||||
// add the contribuitors
|
||||
const contribuitorsList =
|
||||
Array
|
||||
.from(contribuitors)
|
||||
.map(name => `- [@${ name }](https://github.com/${ name }).`)
|
||||
.join('\n');
|
||||
const contribuitorsList = Array.from(contribuitors)
|
||||
.map((name) => `- [@${name}](https://github.com/${name}).`)
|
||||
.join("\n");
|
||||
|
||||
const doneFile = `${ file }\n\n## Contributors\n\n${ contribuitorsList }\n\n`;
|
||||
const doneFile = `${file}\n\n## Contributors\n\n${contribuitorsList}\n\n`;
|
||||
|
||||
//SIDE EFFECTS
|
||||
// so that this is not ran every time, we will update the last file.
|
||||
// this is for the expensive part of the script
|
||||
if (index === files.length - 2) await fs.writeFile(`./generators/changelog/versions/${fileName}`, doneFile);
|
||||
|
||||
if (index === files.length - 2)
|
||||
await fs.writeFile(
|
||||
`./generators/changelog/versions/${fileName}`,
|
||||
doneFile
|
||||
);
|
||||
return doneFile;
|
||||
})
|
||||
.reverse();
|
||||
console.log('Giving some touches to the files');
|
||||
console.log("Giving some touches to the files");
|
||||
const filesContent = await Promise.all(filesStream);
|
||||
await fs.writeFile('./history.md', filesContent.join(''));
|
||||
console.log('Finished :)');
|
||||
|
||||
await fs.writeFile("./history.md", filesContent.join(""));
|
||||
console.log("Finished :)");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
}
|
||||
main().then(_ => _);
|
||||
};
|
||||
main().then((_) => _);
|
||||
|
||||
@@ -148,4 +148,3 @@ you can use ```WARN_WHEN_USING_OLD_API``` before starting your meteor process.
|
||||
- [@zodern](https://github.com/zodern).
|
||||
- [@dmromanov](https://github.com/dmromanov).
|
||||
- [@matheusccastroo](https://github.com/matheusccastroo).
|
||||
|
||||
|
||||
742
docs/generators/changelog/versions/3.0.0.md
Normal file
742
docs/generators/changelog/versions/3.0.0.md
Normal file
@@ -0,0 +1,742 @@
|
||||
## v3.0, 2024-07-15
|
||||
|
||||
### Highlights
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
- `accounts-2fa@3.0.0`:
|
||||
|
||||
- Some methods are now async. See below:
|
||||
- `Accounts._is2faEnabledForUser`
|
||||
- `(Meteor Method) - generate2faActivationQrCode`
|
||||
- `(Meteor Method) - enableUser2fa`
|
||||
- `(Meteor Method) - disableUser2fa`
|
||||
- `(Meteor Method) - has2faEnabled`
|
||||
|
||||
- `accounts-base@3.0.0`:
|
||||
|
||||
- `methods.removeOtherTokens` is now async
|
||||
- `Accounts.destroyToken` is now async
|
||||
- `Accounts.insertUserDoc` is now async
|
||||
- `Accounts.updateOrCreateUserFromExternalService` is now async
|
||||
- `Accounts.expirePasswordToken` is now async
|
||||
- `Accounts.setupUsersCollection` is now async
|
||||
- `Meteor.user` is now async in server
|
||||
|
||||
- `accounts-facebook@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-github@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-google@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-meetup@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-meteor-developer@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-password@3.0.0`:
|
||||
|
||||
- Some server methods are now async:
|
||||
- `Accounts.sendResetPasswordEmail`
|
||||
- `Accounts.sendEnrollmentEmail`
|
||||
- `Accounts.sendVerificationEmail`
|
||||
- `Accounts.addEmail`
|
||||
- `Accounts.removeEmail`
|
||||
- `Accounts.verifyEmail`
|
||||
- `Accounts.createUserVerifyingEmail`
|
||||
- `Accounts.createUser`
|
||||
- `Accounts.generateVerificationToken`
|
||||
- `Accounts.generateResetToken`
|
||||
- `Accounts.forgotPassword`
|
||||
- `Accounts.setPassword`
|
||||
- `Accounts.changePassword`
|
||||
- `Accounts.setUsername`
|
||||
- `Accounts.findUserByEmail`
|
||||
- `Accounts.findUserByUsername`
|
||||
|
||||
- `accounts-passwordless@3.0.0`:
|
||||
|
||||
- `Accounts.sendLoginTokenEmail` is now async.
|
||||
|
||||
- `accounts-twitter@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-ui-unstyled@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `accounts-weibo@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `allow-deny@2.0.0`:
|
||||
|
||||
- Updated to accept async functions.
|
||||
|
||||
- `appcache@2.0.0`:
|
||||
|
||||
- Updated internal api to use `handlers`
|
||||
|
||||
- `audit-argument-checks@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `autopublish@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `autoupdate@2.0.0`:
|
||||
|
||||
- Updated api to be async, with asyncronous queueing.
|
||||
|
||||
- `babel-compiler@8.0.0`:
|
||||
|
||||
- Add `Babel.compileForShell`
|
||||
- Removed `Promise.await` default transform.
|
||||
- Added top-level-await to packages.
|
||||
|
||||
- `babel-runtime@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `base64@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `binary-heap@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `blaze@3.0.0`:
|
||||
- Todo
|
||||
|
||||
- `boilerplate-generator-tests@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `boilerplate-generator@2.0.0`:
|
||||
|
||||
- `toHTML` is no longer available (it was already deprecated). Use `toHTMLStream` instead.
|
||||
- Updated to use `handlers`
|
||||
|
||||
- `browser-policy-common@2.0.0`:
|
||||
|
||||
- Updated to use `handlers`
|
||||
|
||||
- `browser-policy-content@2.0.0`:
|
||||
|
||||
- Some methods are now async. See below:
|
||||
- `BrowserPolicy.content.setPolicy`
|
||||
- `BrowserPolicy.content.allowInlineScripts`
|
||||
- `BrowserPolicy.content.disallowInlineScripts`
|
||||
- `BrowserPolicy.content.disallowAll`
|
||||
- `BrowserPolicy.setDefaultPolicy`
|
||||
|
||||
- `browser-policy-framing@2.0.0`:
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `browser-policy@2.0.0`:
|
||||
Updated to use async methods from `browser-policy-common` and `browser-policy-content`.
|
||||
|
||||
- `caching-compiler@2.0.0`:
|
||||
|
||||
- `afterLink` is now async.
|
||||
- Updated to use now async API.
|
||||
|
||||
- `callback-hook@2.0.0`:
|
||||
|
||||
- Added `forEachAsync` method.
|
||||
|
||||
- `check@2.0.0`:
|
||||
|
||||
- Removed `fibers` related tests.
|
||||
|
||||
- `constraint-solver@2.0.0`:
|
||||
|
||||
- Some methods are now async. See below:
|
||||
|
||||
- `ConstraintSolver.getVersionCostSteps`
|
||||
- `ConstraintSolver.analyze`
|
||||
- `ConstraintSolver.resolve`
|
||||
|
||||
- Updated tests to be async.
|
||||
- Removed a few underscore usage.
|
||||
- Added updated to use async methods
|
||||
|
||||
- `context@1.0.0`:
|
||||
|
||||
- Removed `fibers` from package.
|
||||
|
||||
- `core-runtime@2.0.0`:
|
||||
|
||||
- Created package to load packages and the app.
|
||||
- This is the pakcages that sets up the Runtime.
|
||||
|
||||
- `crosswalk@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ddp-client@3.0.0`:
|
||||
|
||||
- Added `isAsyncCall` method to know if call is being made by an async method.
|
||||
- Removed `fibers` from package.
|
||||
- Updated tests to use async methods.
|
||||
- Now `stubPromise` is returned when calling `callAsync` or `applyAsync`.
|
||||
|
||||
- `ddp-common@2.0.0`:
|
||||
|
||||
- Added `.fence` option.
|
||||
|
||||
- `ddp-rate-limiter@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ddp-server@3.0.0`:
|
||||
|
||||
- Updated to use async methods.
|
||||
- Removed `fibers` from package.
|
||||
- Updated tests to use async methods.
|
||||
- Turned server implementation to async.
|
||||
|
||||
- `ddp@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `diff-sequence@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `disable-oplog@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ecmascript-runtime-client@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ecmascript-runtime-server@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ecmascript-runtime@1.0.0`:
|
||||
|
||||
- Added dependency to `@babel/runtime`.
|
||||
|
||||
- `ecmascript@1.0.0`:
|
||||
|
||||
- `ECMAScript.compileForShell` was removed. Use `Babel.compileForShell` from
|
||||
`babel-compiler` instead. This change makes some build plugins and apps that do not use `babel-compiler` 90mb smaller.
|
||||
- Added dependency to `@babel/runtime`.
|
||||
- Moved runtime tests.
|
||||
|
||||
- `ejson@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `email@3.0.0`:
|
||||
|
||||
- `Email.send` is no longer available. Use `Email.sendAsync` instead.
|
||||
- Updated types to reflext async methods and `Email.send` depracation.
|
||||
|
||||
- `es5-shim@5.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `facebook-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `facebook-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `facts-base@2.0.0`:
|
||||
|
||||
- turned unorderd deps on `ddp` to false.
|
||||
|
||||
- `facts-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `fetch@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `force-ssl-common@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `force-ssl@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `geojson-utils@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `github-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `github-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `google-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `google-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `hot-code-push@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `http@`:
|
||||
- Updated handlers to use `handlers`
|
||||
- `id-map@2.0.0`:
|
||||
|
||||
- Added `forEachAsync` method.
|
||||
|
||||
- `insecure@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `inter-process-messaging@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `launch-screen@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `localstorage@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `logging@2.0.0`:
|
||||
|
||||
- Added dependency to `@babel/runtime`.
|
||||
|
||||
- `logic-solver@3.0.0`:
|
||||
`Logic.disablingAssertions` is now async.
|
||||
`minMaxWS` is now async.
|
||||
|
||||
- `meetup-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `meetup-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `meteor-base@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `meteor-developer-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `meteor-developer-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `meteor-tool@3.0.0`:
|
||||
|
||||
- Changes to how meteor apps are being created [PR](https://github.com/meteor/meteor/pull/12697)
|
||||
|
||||
- `meteor@2.0.0`:
|
||||
|
||||
- Async local storage was added to help deal with async methods.
|
||||
- Added `promiseEmmiter` to help with async methods.
|
||||
- Removed `fibers` from package.
|
||||
|
||||
- `minifier-css@2.0.0`:
|
||||
|
||||
- `minifyCss` is now async.
|
||||
- Removed `fibers` from package.
|
||||
|
||||
- `minifier-js@3.0.0`:
|
||||
|
||||
- `minifyJs` is now async.
|
||||
- `terserMinify` no longer takes callbacks
|
||||
- Removed `fibers` from package.
|
||||
|
||||
* `minimongo@2.0.0`:
|
||||
- `cursor.observe` now returns `isReady` and `isReadyPromise` wich indicates
|
||||
if the cursor is ready and if the callbacks are have been called.
|
||||
If you only use it in the `Client` or as a `LocalCollection` things have not
|
||||
changed.
|
||||
- `cursor.observeChangesAsync` and `cursor.observeAsync` are added and resolve as promises, returning results similar to their synchronous counterparts.
|
||||
|
||||
- `mobile-experience@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `mobile-status-bar@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `modern-browsers@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `modules-runtime@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `modules@1.0.0`:
|
||||
|
||||
- Updated `reify` version.
|
||||
|
||||
- `mongo-decimal@`:
|
||||
|
||||
- Updated to use `async` methods.
|
||||
|
||||
- `mongo-dev-server@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `mongo-id@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `mongo-livedata@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `mongo@2.0.0`:
|
||||
|
||||
- Updated to unify methods, `update`,`insert`,`remove`, `fetch` are now async, they are
|
||||
the same as their `*Async` counterpart.
|
||||
- `ensureIndex` and `createIndex` are now async.
|
||||
- `observeChangesAsync` and `observeAsync` are added and resolve as promises, returning results similar to their synchronous counterparts.
|
||||
|
||||
- `npm-mongo@5.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `oauth-encryption@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `oauth@`:
|
||||
|
||||
- `_endOfPopupResponseTemplate` and `_endOfRedirectResponseTemplate` are no longer a property but now a function that returns a promise of the same value as before
|
||||
- the following server methods are now async:
|
||||
- `OAuth._renderOauthResults`
|
||||
- `OAuth._endOfLoginResponse`
|
||||
- `OAuth.renderEndOfLoginResponse`
|
||||
- `OAuth._storePendingCredential`
|
||||
- `OAuth._retrievePendingCredential`
|
||||
- `ensureConfigured`
|
||||
- `_cleanStaleResults`
|
||||
|
||||
- `oauth@3.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `oauth1@`:
|
||||
|
||||
- the following server methods are now async:
|
||||
- `OAuth._storeRequestToken`
|
||||
- `OAuth._retrieveRequestToken`
|
||||
|
||||
- `oauth1@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `oauth2@`:
|
||||
|
||||
- `OAuth._requestHandlers['2']` is now async.
|
||||
|
||||
- `oauth2@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `ordered-dict@2.0.0`:
|
||||
|
||||
- Added `forEachAsync` method.
|
||||
|
||||
- `package-stats-opt-out@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `package-version-parser@4.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `promise@1.0.0`:
|
||||
|
||||
- Removed `fibers` usage
|
||||
|
||||
- `random@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `rate-limit@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `reactive-dict@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `reactive-var@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `reload-safetybelt@2.0.0`:
|
||||
|
||||
- Added `ecmascript` package to `package.js`
|
||||
|
||||
- `reload@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `retry@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `routepolicy@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `server-render@1.0.0`:
|
||||
|
||||
- Updated usage with `getBoilerplate` that are now `async`.
|
||||
|
||||
- `service-configuration@2.0.0`:
|
||||
|
||||
- Updated to use `createIndexAsync`.
|
||||
|
||||
- `session@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `sha@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `shell-server@1.0.0`:
|
||||
|
||||
- Updated to handle promises results.
|
||||
|
||||
- `socket-stream-client@1.0.0`:
|
||||
|
||||
- Updated tests to handle `async` code.
|
||||
|
||||
- `spiderable@`:
|
||||
|
||||
- Updated handlers to use `handlers` that are now using express
|
||||
- removed `fibers` usage if flag is set to `true`
|
||||
|
||||
- `standard-minifier-css@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `standard-minifier-js@3.0.0`:
|
||||
|
||||
- `processFilesForBundle` is now `async`.
|
||||
|
||||
- `standard-minifiers@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `static-html@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `test-helpers@2.0.0`:
|
||||
|
||||
- Updated to use `async` methods.
|
||||
- Removed `fibers` usage.
|
||||
- Added possibliy to use `async` tests.
|
||||
|
||||
- `test-in-browser@2.0.0`:
|
||||
|
||||
- Updated css to be in dark mode.
|
||||
|
||||
- `test-in-console@2.0.0`:
|
||||
|
||||
- Updated log identation.
|
||||
|
||||
- `test-server-tests-in-console-once@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `tinytest-harness@1.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `tinytest@2.0.0`:
|
||||
|
||||
- Added `test name` to logs.
|
||||
- Removed `fibers` usage.
|
||||
|
||||
- `twitter-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `twitter-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `typescript@5.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `underscore-tests@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `underscore@2.0.0`:
|
||||
|
||||
- Removed dependency in meteor package.
|
||||
|
||||
- `url@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `webapp-hashing@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `webapp@2.0.0`:
|
||||
|
||||
- These methods are now async:
|
||||
|
||||
- `WebAppInternals.reloadClientPrograms()`
|
||||
- `WebAppInternals.pauseClient()`
|
||||
- `WebAppInternals.generateClientProgram()`
|
||||
- `WebAppInternals.generateBoilerplate()`
|
||||
- `WebAppInternals.setInlineScriptsAllowed()`
|
||||
- `WebAppInternals.enableSubresourceIntegrity()`
|
||||
- `WebAppInternals.setBundledJsCssUrlRewriteHook()`
|
||||
- `WebAppInternals.setBundledJsCssPrefix()`
|
||||
- `WebAppInternals.getBoilerplate`
|
||||
|
||||
- Changed engine from connect to express and changed api naming to match express. See below:
|
||||
- `WebApp.connectHandlers.use(middleware)` is now `WebApp.handlers.use(middleware)`
|
||||
- `WebApp.rawConnectHandlers.use(middleware)` is now `WebApp.rawHandlers.use(middleware)`
|
||||
- `WebApp.connectApp` is now `WebApp.expressApp`
|
||||
|
||||
- `weibo-config-ui@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
- `weibo-oauth@2.0.0`:
|
||||
|
||||
- Package was bumped due to a dependency update. No code changes were made.
|
||||
|
||||
#### New Public API
|
||||
|
||||
|
||||
|
||||
- `accounts-base`: (2.9+)
|
||||
|
||||
- `Meteor.userAsync()`
|
||||
|
||||
- `callback-hook`:forEachAsync
|
||||
|
||||
- `forEachAsync`
|
||||
|
||||
- `ddp-server`: (2.8+)
|
||||
|
||||
- `Meteor.callAsync()`
|
||||
|
||||
- `meteor`:
|
||||
- Added `Meteor.isDebug` to execute code in debug builds, activated with the --inspect mode.
|
||||
|
||||
- `minifier-css`: (2.9+)
|
||||
|
||||
- `CssTools.minifyCssAsync()`
|
||||
|
||||
- `mongo`:
|
||||
|
||||
- `Mongo.Collection`: (2.8+)
|
||||
- `createCappedCollectionAsync`
|
||||
- `createIndexAsync`
|
||||
- `dropCollectionAsync`
|
||||
- `dropIndexAsync`
|
||||
- `findOneAsync`
|
||||
- `insertAsync`
|
||||
- `removeAsync`
|
||||
- `updateAsync`
|
||||
- `upsertAsync`
|
||||
- `Collection.Cursor`: (2.8+)
|
||||
- `countAsync`
|
||||
- `fetchAsync`
|
||||
- `forEachAsync`
|
||||
- `mapAsync`
|
||||
- `[Symbol.asyncIterator]` so this code should work:
|
||||
```js
|
||||
for await (const document of collection.find(query, options)) /* ... */
|
||||
```
|
||||
|
||||
#### Internal API changes
|
||||
|
||||
`accounts-base`:
|
||||
|
||||
- `_attemptLogin`
|
||||
- `_loginMethod`
|
||||
- `_runLoginHandlers`
|
||||
|
||||
* Upgraded `node-gyp` to v9.4.0
|
||||
* Upgraded `node-pre-gyp` to `@mapbox/node-pre-gyp` v1.0.11
|
||||
|
||||
#### New Internal API
|
||||
|
||||
`accounts-password`:
|
||||
|
||||
- `Accounts._checkPasswordAsync`
|
||||
|
||||
#### Special thanks to
|
||||
|
||||
- [@denihs](https://github.com/denihs)
|
||||
- [@Grubba27](https://github.com/Grubba27)
|
||||
- [@nachocodoner](https://github.com/nachocodoner)
|
||||
- [@fredmaiaarantes](https://github.com/fredmaiaarantes)
|
||||
- [@vit0rr](https://github.com/vit0rr)
|
||||
- [@filipenevola](https://github.com/filipenevola)
|
||||
- [@zodern](https://github.com/zodern)
|
||||
- [@radekmie](https://github.com/radekmie)
|
||||
- [@StorytellerCZ](https://github.com/StorytellerCZ)
|
||||
- [@gunnartorfis](https://github.com/gunnartorfis)
|
||||
- [@xet7](https://github.com/xet7)
|
||||
- [@harryadel](https://github.com/harryadel)
|
||||
- [@simonwebs](https://github.com/simonwebs)
|
||||
- [@TylerThompson](https://github.com/TylerThompson)
|
||||
- [@rodrigok](https://github.com/rodrigok)
|
||||
- [@zarvox](https://github.com/zarvox)
|
||||
- [@srsgores](https://github.com/srsgores)
|
||||
- [@tassoevan](https://github.com/tassoevan)
|
||||
- [@Torgen](https://github.com/Torgen)
|
||||
- [@MarcosSpessatto](https://github.com/MarcosSpessatto)
|
||||
- [@vincentcarpentier](https://github.com/vincentcarpentier)
|
||||
- [@ggazzo](https://github.com/ggazzo)
|
||||
- [@StevenMia](https://github.com/StevenMia)
|
||||
- [@acemtp](https://github.com/acemtp)
|
||||
|
||||
And so many more people, for making this great framework even better!
|
||||
45
docs/generators/changelog/versions/3.0.1.md
Normal file
45
docs/generators/changelog/versions/3.0.1.md
Normal file
@@ -0,0 +1,45 @@
|
||||
## v3.0.1, 2024-07-16
|
||||
|
||||
### Highlights
|
||||
|
||||
* Bump the patch for some packages, so we publish them using Meteor 3 tooling. [PR #13231]
|
||||
|
||||
#### 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.1
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Meteor Version Release
|
||||
|
||||
|
||||
* `Bumped packages`:
|
||||
- accounts-ui-unstyled@1.7.2
|
||||
- crosswalk@1.7.3
|
||||
- facebook-oauth@1.11.4
|
||||
- npm-mongo@4.17.3
|
||||
- package-version-parser@3.2.3
|
||||
- twitter-config-ui@1.0.2
|
||||
|
||||
|
||||
#### Special thanks to
|
||||
|
||||
- [@denihs](https://github.com/denihs).
|
||||
|
||||
|
||||
For making this great framework even better!
|
||||
|
||||
|
||||
932
docs/history.md
932
docs/history.md
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"plugins": ["plugins/markdown"],
|
||||
"markdown": {
|
||||
"parser": "gfm"
|
||||
},
|
||||
"source": {
|
||||
"exclude": [
|
||||
"packages/ddp/sockjs-0.3.4.js",
|
||||
@@ -18,5 +14,9 @@
|
||||
"**/node_modules",
|
||||
"npm-packages"
|
||||
]
|
||||
},
|
||||
"plugins": [ "plugins/markdown"],
|
||||
"markdown": {
|
||||
"parser": "gfm"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[build]
|
||||
publish = "public"
|
||||
command = "npm install && npm run build"
|
||||
command = "npm cache clear --force && npm install --legacy-peer-deps && npm run build"
|
||||
|
||||
207
docs/package-lock.json
generated
207
docs/package-lock.json
generated
@@ -4,6 +4,21 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz",
|
||||
"integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
|
||||
"dev": true
|
||||
},
|
||||
"@jsdoc/salty": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz",
|
||||
"integrity": "sha512-aA+awb5yoml8TQ3CzI5Ue7sM3VMRC4l1zJJW4fgZ8OCL1wshJZhNzaf0PL85DSnOUw6QuFgeHGD/eq/xwwAF2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"@meteorjs/meteor-hexo-config": {
|
||||
"version": "1.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@meteorjs/meteor-hexo-config/-/meteor-hexo-config-1.0.14.tgz",
|
||||
@@ -16,6 +31,28 @@
|
||||
"integrity": "sha512-LQIFN05wBMjX7SXgW5CFVTfolDWMuknoypwQ0czl/44LYRBR4/LYZUgX6c+1vLjloJb+5+2HTvMGlVN9Wo1MKA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/linkify-it": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz",
|
||||
"integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/markdown-it": {
|
||||
"version": "12.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
|
||||
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/linkify-it": "*",
|
||||
"@types/mdurl": "*"
|
||||
}
|
||||
},
|
||||
"@types/mdurl": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz",
|
||||
"integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==",
|
||||
"dev": true
|
||||
},
|
||||
"JSONStream": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
|
||||
@@ -543,12 +580,12 @@
|
||||
"optional": true
|
||||
},
|
||||
"catharsis": {
|
||||
"version": "0.8.11",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
|
||||
"integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
|
||||
"integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.14"
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"center-align": {
|
||||
@@ -2379,6 +2416,12 @@
|
||||
"striptags": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
|
||||
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
||||
@@ -2780,12 +2823,12 @@
|
||||
}
|
||||
},
|
||||
"js2xmlparser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
|
||||
"integrity": "sha512-CSOkdn0/GhRFwxnipmhXfqJ+FG6+wkWBi46kKSsPx6+j65176ZiQcrCYpg6K8x3iLbO4k3zScBnZ7I/L80dAtw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
|
||||
"integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"xmlcreate": "^1.0.1"
|
||||
"xmlcreate": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
@@ -2796,47 +2839,56 @@
|
||||
"optional": true
|
||||
},
|
||||
"jsdoc": {
|
||||
"version": "3.5.5",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
|
||||
"integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz",
|
||||
"integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babylon": "7.0.0-beta.19",
|
||||
"bluebird": "~3.5.0",
|
||||
"catharsis": "~0.8.9",
|
||||
"escape-string-regexp": "~1.0.5",
|
||||
"js2xmlparser": "~3.0.0",
|
||||
"klaw": "~2.0.0",
|
||||
"marked": "~0.3.6",
|
||||
"mkdirp": "~0.5.1",
|
||||
"requizzle": "~0.2.1",
|
||||
"strip-json-comments": "~2.0.1",
|
||||
"taffydb": "2.6.2",
|
||||
"underscore": "~1.8.3"
|
||||
"@babel/parser": "^7.20.15",
|
||||
"@jsdoc/salty": "^0.2.1",
|
||||
"@types/markdown-it": "^12.2.3",
|
||||
"bluebird": "^3.7.2",
|
||||
"catharsis": "^0.9.0",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"js2xmlparser": "^4.0.2",
|
||||
"klaw": "^3.0.0",
|
||||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-anchor": "^8.4.1",
|
||||
"marked": "^4.0.10",
|
||||
"mkdirp": "^1.0.4",
|
||||
"requizzle": "^0.2.3",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"underscore": "~1.13.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"babylon": {
|
||||
"version": "7.0.0-beta.19",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
|
||||
"integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.5",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
|
||||
"integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
|
||||
"escape-string-regexp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||
"dev": true
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
|
||||
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
|
||||
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
|
||||
"integrity": "sha512-5WsVTFcH1ut/kkhAaHf4PVgI8c7++GiVcpCGxPouI6ZVjsqPnSDf8h/8HtVqc0t4fzRXwnMK70EcZeAs3PIddg==",
|
||||
"version": "1.13.6",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
|
||||
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -2922,9 +2974,9 @@
|
||||
}
|
||||
},
|
||||
"klaw": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
|
||||
"integrity": "sha512-Hx5PvgJKTWpMkNJCYrBUNBLlxYIkxN4FVU/BnZP4CFh5BpiHOgujAPx7iFVz/phD0bP8rsqD48gtqcvNlUt0lQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
|
||||
"integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.9"
|
||||
@@ -2952,6 +3004,15 @@
|
||||
"source-map": "^0.5.3"
|
||||
}
|
||||
},
|
||||
"linkify-it": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
|
||||
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"uc.micro": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
@@ -3095,10 +3156,37 @@
|
||||
"nopt": "~2.1.1"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
|
||||
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
|
||||
"markdown-it": {
|
||||
"version": "12.3.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
|
||||
"integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "~2.1.0",
|
||||
"linkify-it": "^3.0.1",
|
||||
"mdurl": "^1.0.1",
|
||||
"uc.micro": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
|
||||
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown-it-anchor": {
|
||||
"version": "8.6.7",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz",
|
||||
"integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
|
||||
"dev": true
|
||||
},
|
||||
"math-random": {
|
||||
@@ -3107,6 +3195,12 @@
|
||||
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==",
|
||||
"dev": true
|
||||
},
|
||||
"mdurl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
|
||||
@@ -3196,6 +3290,7 @@
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
@@ -4529,9 +4624,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true
|
||||
},
|
||||
"striptags": {
|
||||
@@ -4585,12 +4680,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"taffydb": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
|
||||
"integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==",
|
||||
"dev": true
|
||||
},
|
||||
"text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
@@ -4699,6 +4788,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"uc.micro": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
||||
@@ -4951,9 +5046,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"xmlcreate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
|
||||
"integrity": "sha512-Mbe56Dvj00onbnSo9J0qj/XlY5bfN9KidsOnpd5tRCsR3ekB3hyyNU9fGrTdqNT5ZNvv4BsA2TcQlignsZyVcw==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz",
|
||||
"integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==",
|
||||
"dev": true
|
||||
},
|
||||
"y18n": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"hexo-renderer-marked": "2.0.0",
|
||||
"hexo-server": "1.0.0",
|
||||
"hexo-versioned-netlify-redirects": "1.1.0",
|
||||
"jsdoc": "3.5.5",
|
||||
"jsdoc": "^4.0.2",
|
||||
"@meteorjs/meteor-hexo-config": "1.0.14",
|
||||
"@meteorjs/meteor-theme-hexo": "2.0.8",
|
||||
"showdown": "1.9.1",
|
||||
|
||||
@@ -10,8 +10,8 @@ assets, which are located in the `private` subdirectory of an application's
|
||||
tree. Assets are not processed as source files and are copied directly
|
||||
into your application's bundle.
|
||||
|
||||
{% apibox "Assets.getText" %}
|
||||
{% apibox "Assets.getBinary" %}
|
||||
{% apibox "Assets.getTextAsync" %}
|
||||
{% apibox "Assets.getBinaryAsync" %}
|
||||
{% apibox "Assets.absoluteFilePath" %}
|
||||
|
||||
Static server assets are included by placing them in the application's `private`
|
||||
@@ -20,7 +20,7 @@ directory called `nested` with a file called `data.txt` inside it, then server
|
||||
code can read `data.txt` by running:
|
||||
|
||||
```js
|
||||
const data = Assets.getText('nested/data.txt');
|
||||
const data = await Assets.getTextAsync('nested/data.txt');
|
||||
```
|
||||
|
||||
Note: Packages can only access their own assets. If you need to read the assets of a different package, or of the enclosing app, you need to get a reference to that package's `Assets` object.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,7 +3,7 @@ title: Core
|
||||
description: Documentation of core Meteor functions.
|
||||
---
|
||||
|
||||
If you prefer to watch the video, click below.
|
||||
If you prefer to watch the video, click below.
|
||||
|
||||
{% youtube 6RRVU0-Vvm8 %}
|
||||
|
||||
@@ -64,3 +64,5 @@ if (Meteor.isServer) {
|
||||
{% apibox "Meteor.isAppTest" %}
|
||||
|
||||
{% apibox "Meteor.isPackageTest" %}
|
||||
|
||||
{% apibox "Meteor.isFibersDisabled" %}
|
||||
|
||||
@@ -80,6 +80,12 @@ with this ID has already been made. Alternatively, you can use
|
||||
|
||||
Read more about methods and how to use them in the [Methods](http://guide.meteor.com/methods.html) article in the Meteor Guide.
|
||||
|
||||
{% apibox "Meteor.isAsyncCall" %}
|
||||
|
||||
This method can be used to determine if the current method invocation is
|
||||
asynchronous. It returns true if the method is running on the server and came from
|
||||
an async call(`Meteor.callAsync`)
|
||||
|
||||
{% apibox "DDPCommon.MethodInvocation#userId" %}
|
||||
|
||||
The user id is an arbitrary string — typically the id of the user record
|
||||
|
||||
@@ -80,7 +80,7 @@ package) so that Meteor will pick up the local dependency.
|
||||
> In a lifecycle of a package there might come time to end the development for various reasons, or
|
||||
it gets superseded. In either case Meteor allows you to easily notify the users of the package by
|
||||
setting the deprecated flag to true: `deprecated: true` in the package description. In addition, you
|
||||
replace it with a string that tells the users where to find replacement or what to do.
|
||||
replace it with a string that tells the users where to find replacement or what to do.
|
||||
|
||||
Provide basic package information with `Package.describe(options)`. To publish a
|
||||
package, you must define `summary` and `version`.
|
||||
@@ -97,7 +97,7 @@ package is exported to.
|
||||
{% apibox "PackageAPI#versionsFrom" %}
|
||||
|
||||
> Choose Meteor versions carefully. First determine the minimum version of Meteor you need for the API you use in your package.
|
||||
This should be based on specific needs of your package like needed the *Async calls, which would require minimum version to be
|
||||
This should be based on specific needs of your package like needed the *Async calls, which would require minimum version to be
|
||||
at least 2.8. Another example are where packages had a major version bump, for example this has happened with the accounts packages
|
||||
in Meteor 2.3. If you want to be backward and forward compatible it is good to include Meteor version before 2.3 and then 2.3.6 in the array.
|
||||
A general recommendation for most compatibility for accounts packages (unless you need API that was affected in Meteor 2.3) is to have the following
|
||||
@@ -315,7 +315,7 @@ methods are available:
|
||||
- `addAsset` - Add a file to serve as-is to the browser or to include on the
|
||||
browser, depending on the target. On the web, it will be served at the exact
|
||||
path requested. For server targets, it can be retrieved using
|
||||
`Assets.getText` or `Assets.getBinary`.
|
||||
`Assets.getTextAsync` or `Assets.getBinaryAsync`.
|
||||
- `addHtml` - Works in web targets only. Add markup to the `head` or `body`
|
||||
section of the document.
|
||||
- `hmrAvailable` - Returns true if the file can be updated with HMR. Among other things,
|
||||
|
||||
@@ -37,7 +37,7 @@ id.
|
||||
|
||||
On the client, you must pass `password` and at least one of `username` or `email` — enough information for the user to be able to log in again later. If there are existing users with a username or email only differing in case, `createUser` will fail. The callback's `error.reason` will be `'Username already exists.'` or `'Email already exists.'` In the latter case, the user can then either [login](accounts.html#Meteor-loginWithPassword) or [reset their password](#Accounts-resetPassword).
|
||||
|
||||
On the server, you do not need to specify `password`, but the user will not be able to log in until it has a password (eg, set with [`Accounts.setPassword`](#accounts_setpassword)). To create an account without a password on the server and still let the user pick their own password, call `createUser` with the `email` option and then call [`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail). This will send the user an email with a link to set their initial password.
|
||||
On the server, you do not need to specify `password`, but the user will not be able to log in until it has a password (eg, set with [`Accounts.setPasswordAsync`](#accounts_setpasswordasync)). To create an account without a password on the server and still let the user pick their own password, call `createUser` with the `email` option and then call [`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail). This will send the user an email with a link to set their initial password.
|
||||
|
||||
By default the `profile` option is added directly to the new user document. To
|
||||
override this behavior, use [`Accounts.onCreateUser`](#accounts_oncreateuser).
|
||||
@@ -53,7 +53,7 @@ insensitive duplicates before updates.
|
||||
|
||||
{% apibox "Accounts.setUsername" %}
|
||||
|
||||
{% apibox "Accounts.addEmail" %}
|
||||
{% apibox "Accounts.addEmailAsync" %}
|
||||
|
||||
By default, an email address is added with `{ verified: false }`. Use
|
||||
[`Accounts.sendVerificationEmail`](#Accounts-sendVerificationEmail) to send an
|
||||
@@ -100,7 +100,7 @@ This function accepts tokens passed into the callbacks registered with
|
||||
If the user trying to reset the password has 2FA enabled, this error will be thrown:
|
||||
* "Changed password, but user not logged in because 2FA is enabled [2fa-enabled]": No longer signing in the user automatically if the user has 2FA enabled.
|
||||
|
||||
{% apibox "Accounts.setPassword" %}
|
||||
{% apibox "Accounts.setPasswordAsync" %}
|
||||
|
||||
{% apibox "Accounts.sendResetPasswordEmail" %}
|
||||
|
||||
|
||||
122
docs/source/api/top-level-await.md
Normal file
122
docs/source/api/top-level-await.md
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: Top Level Await
|
||||
description: Documentation of how to use top level await in Meteor
|
||||
---
|
||||
|
||||
[Top level await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await) (TLA) allows you to use `await` in the top level of a module or file instead of only in async functions. One way to view it as every file runs inside an `async` function.
|
||||
|
||||
Here is an example of using top level await on the server. When this file is loaded, the `await` will cause the module to wait for the count before the code in the rest of the module is run.
|
||||
|
||||
```js
|
||||
const Links = new Mongo.Collection('links');
|
||||
|
||||
// Async code using top level await.
|
||||
// The module waits for this to finish before continuing
|
||||
const count = await Links.find().countAsync();
|
||||
|
||||
if (count === 0) {
|
||||
await Links.insertAsync({ url: 'https://meteor.com' });
|
||||
}
|
||||
```
|
||||
|
||||
In previous versions of Meteor, async code using fibers could be run in the top level of a module. Top level await allows writing similar code that works without fibers. There are a few differences that this article will cover.
|
||||
|
||||
Meteor's implementation of top level await tries to closely follow the specification. There currently are some differences with how Meteor handles circular dependencies.
|
||||
|
||||
## Using Top Level Await
|
||||
|
||||
Top level await can be used in any app or package that uses the `ecmascript`, `typescript`, or `coffeescript` packages, or that uses any other build plugin that compiles top level await using reify.
|
||||
Generally, if you can use ECMAScript modules, then you can also use top level await.
|
||||
|
||||
There are some extra considerations when using top level await in packages. They are covered later in this article.
|
||||
|
||||
Top level await is only enabled by default on the server. You can enable it for the client by setting the env var `METEOR_ENABLE_CLIENT_TOP_LEVEL_AWAIT` to `true`. There are a couple known issues with using TLA on the client:
|
||||
|
||||
1. It breaks any files in `/client/compatibility` since it now wraps those files in a function
|
||||
2. Hot module replacement has not been updated to work with TLA
|
||||
|
||||
## Async Modules
|
||||
|
||||
With top level await, some modules are considered async, which affects how they behave. There are two ways a module can become an async module:
|
||||
1. It uses top level await
|
||||
2. It imports a module that is async
|
||||
|
||||
For example, this module (`setup.js`) would be async because it uses top level await:
|
||||
|
||||
```js
|
||||
await setupLanguages();
|
||||
```
|
||||
|
||||
This module (`main.js`) would be sync:
|
||||
|
||||
```js
|
||||
console.log('in main.js');
|
||||
```
|
||||
|
||||
However, if it imports `setup.js` which does use top level await, then `main.js` also becomes async.
|
||||
|
||||
```js
|
||||
import './setup.js';
|
||||
|
||||
console.log('in main.js');
|
||||
```
|
||||
|
||||
## Require
|
||||
|
||||
When using `require` to load an async module, instead of directly returning a module's exports, it will return a promise that resolves to the module's exports.
|
||||
|
||||
```js
|
||||
// resolves to the exports of init.js
|
||||
const promise = require('./init.js');
|
||||
```
|
||||
|
||||
If you are using `require`, this does mean you need to be careful when adding or removing top level await in a file since you also have to update where the module is required.
|
||||
Since a module becomes async if it depends on an async module, this could affect more than just the individual modules using top level await.
|
||||
|
||||
When possible, you can use ecmascript import syntax or dynamic imports instead so you don't have to worry about which modules are sync or async.
|
||||
|
||||
## Nested Imports
|
||||
|
||||
Nested imports refer to using `import ...` outside of the root of a module, for example in an if block or a function.
|
||||
|
||||
```js
|
||||
if (Meteor.isClient) {
|
||||
import './init-client.js';
|
||||
}
|
||||
|
||||
export function showNotification(message) {
|
||||
import show from './notifications.js';
|
||||
|
||||
show(message);
|
||||
}
|
||||
```
|
||||
|
||||
This is a feature unique to Meteor, so the top level await specification wasn't written to work with nested imports. Using nested imports to import a sync module continues to work, but it will throw an error if used to import an async module. You can use `require` or dynamic imports for async modules in these situations.
|
||||
|
||||
## Using in Packages
|
||||
|
||||
Top level await is only supported starting in Meteor 3. Published build plugins are able to use top level await in older Meteor versions since the runtime is bundled when they are published, though in development they require Meteor 3.
|
||||
|
||||
If you want to ensure your package only runs in versions of Meteor that support top level await, you can have your package use `isobuild:top-level-await`:
|
||||
|
||||
```js
|
||||
Package.onUse(function (api) {
|
||||
// Do not allow this package to be used in pre-Meteor 3 apps.
|
||||
api.use("isobuild:top-level-await@3.0.0");
|
||||
});
|
||||
```
|
||||
|
||||
When importing a package that does not have a lazy main module, it will work the same whether a package uses top level await or not. This is true even when using `require`. This allows packages to add or remove top level await without it being a breaking change.
|
||||
|
||||
There are a couple cases where adding or removing top level await from a module in a package could be considered a breaking change:
|
||||
|
||||
1. If specific modules are require'd from a package. For example: `require('meteor/zodern:aurorae/svelte.js')`. When importing a specific module from a package, `require` changes its behavior based on if the module is async or not.
|
||||
2. If a package that has lazy main modules is require'd. Unlike normal packages, `require` will return a promise if the lazy main module is an async module. Changing if the lazy main module is async or not should be considered a breaking change for the package.
|
||||
|
||||
## Module and Package Execution Order
|
||||
|
||||
Normally, modules are run one at a time. This was even true when using async code with fibers in the root of a module. However, top level await is different - it allows siblings (modules that do not depend on each other) to sometimes run in parallel. This can allow the app to load faster, which is especially important on the client. However, this could cause code to run in an unexpected order if you are used to how Meteor worked with fibers.
|
||||
|
||||
This is also applies to packages. Packages that do not directly or indirectly depend on each other are able to load in parallel if they use top level await.
|
||||
|
||||
Modules that are eagerly evaluated (added in packages with `api.addFiles`, or outside of `imports` in apps that do not have a main module) and not directly imported continue to run one at a time, even if they use top level await, since it is common for these modules to implicitly depend on the previous modules.
|
||||
@@ -285,20 +285,6 @@ You can also use Vue 3 with Vite by using the [jorgenvatle:meteor-vite](https://
|
||||
package. You can see an example on the [meteor-vite](https://github.com/JorgenVatle/meteor-vite/tree/release/examples/vue)
|
||||
repository.
|
||||
|
||||
|
||||
<h3 id="vue-2">--vue-2</h3>
|
||||
|
||||
The command `meteor create --vue-2 app-name` creates a Meteor app with [Vue 2](https://v2.vuejs.org/) and
|
||||
[MongoDB](https://www.mongodb.com/). To create a complete app, including testing and deployment, follow the
|
||||
[Vue 2 tutorial](https://vue-tutorial.meteor.com/).
|
||||
|
||||
Npm packages included: `@babel/runtime`, `meteor-node-stubs`, `vue`, `vue-meteor-tracker`.
|
||||
|
||||
Meteor packages included: `meteor-base`, `mobile-experience`, `mongo`, `reactive-var`, `standard-minifier-css`,
|
||||
`standard-minifier-js`, `es5-shim`, `ecmascript`, `typescript`, `shell-server`, `tracker`, `static-html`, `akryum:vue-component`,
|
||||
`meteortesting:mocha`, `johanbrook:publication-collector`.
|
||||
|
||||
|
||||
<h2 id="meteorgenerate"> meteor generate </h2>
|
||||
|
||||
``meteor generate`` is a command for generating scaffolds for your current project. When ran without arguments, it will ask
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Docs
|
||||
---
|
||||
|
||||
> Meteor 2.x runs on a deprecated Node.js version (14). Meteor 3.0, currently in its Release Candidate version, runs on Node.js v20. For more information, please consult our [migration guide](https://guide.meteor.com/3.0-migration.html).
|
||||
> Meteor 2.x uses the deprecated Node.js 14. Meteor 3.0 has been released and runs on Node.js 20. Check out our [v3 docs](https://v3-docs.meteor.com) and [migration guide](https://v3-migration-docs.meteor.com/).
|
||||
|
||||
<!-- XXX: note that this content is somewhat duplicated on the guide, and should be updated in parallel -->
|
||||
<h2 id="what-is-meteor">What is Meteor?</h2>
|
||||
@@ -24,11 +24,11 @@ Meteor is a full-stack JavaScript platform for developing modern web and mobile
|
||||
1. The place to get started with Meteor is the [tutorials page](https://www.meteor.com/developers/tutorials).
|
||||
|
||||
1. [Meteor Examples](https://github.com/meteor/examples) is a list of examples using Meteor. You can also include your example with Meteor.
|
||||
|
||||
|
||||
1. Once you are familiar with the basics, the [Meteor Guide](http://guide.meteor.com) covers intermediate material on how to use Meteor in a larger scale app.
|
||||
|
||||
1. Visit the [Meteor discussion forums](https://forums.meteor.com) to announce projects, get help, talk about the community, or discuss changes to core.
|
||||
|
||||
|
||||
1. [Meteor Slack Community](https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc) is the best place to ask (and answer!) technical questions and also meet Meteor developers.
|
||||
|
||||
1. [Atmosphere](https://atmospherejs.com) is the repository of community packages designed especially for Meteor.
|
||||
|
||||
@@ -8,7 +8,7 @@ You need to install the Meteor command line tool to create, run, and manage your
|
||||
|
||||
<h3 id="prereqs-node">Node.js version</h3>
|
||||
|
||||
> Meteor 2.x runs on a deprecated Node.js version (14). Meteor 3.0, currently in its Release Candidate version, runs on Node.js v20. For more information, please consult our [migration guide](https://guide.meteor.com/3.0-migration.html).
|
||||
> Meteor 2.x uses the deprecated Node.js 14. Meteor 3.0 has been released and runs on Node.js 20. Check out our [v3 docs](https://v3-docs.meteor.com) and [migration guide](https://v3-migration-docs.meteor.com/).
|
||||
|
||||
- Node.js version >= 10 and <= 14 is required.
|
||||
- We recommend you using [nvm](https://github.com/nvm-sh/nvm) or [Volta](https://volta.sh/) for managing Node.js versions.
|
||||
@@ -34,6 +34,8 @@ Install the latest official version of Meteor.js from your terminal by running o
|
||||
|
||||
For Windows, Linux and OS X, you can run the following command:
|
||||
|
||||
> Preferably, do not use `sudo` to install Meteor. If you need to use `sudo`, please check the [troubleshooting section](#troubleshooting).
|
||||
|
||||
```bash
|
||||
npm install -g meteor
|
||||
```
|
||||
@@ -67,6 +69,8 @@ If you only use sudo because of a distribution default permission system, [check
|
||||
|
||||
In some cases you can get this error `npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules` because your Node.js installation was performed with wrong permissions. An easy way to fix this is to install Node.js using [nvm](https://github.com/nvm-sh/nvm) and forcing it to be used in your terminal. You can force it in the current session of your terminal by running `nvm use 14`.
|
||||
|
||||
As a last resort you can delete the `.meteor` folder in your home directory and try to install Meteor again using the correct permissions.
|
||||
|
||||
<h2 id="path-management">PATH management</h2>
|
||||
|
||||
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:
|
||||
@@ -118,5 +122,4 @@ If you installed Meteor using npm, you can remove it by running:
|
||||
|
||||
If you installed Meteor using curl, you can remove it by running:
|
||||
`rm -rf ~/.meteor`
|
||||
`sudo rm /usr/local/bin/meteor`
|
||||
|
||||
`sudo rm /usr/local/bin/meteor`
|
||||
|
||||
@@ -13,20 +13,20 @@ This package also allows you to add handlers for HTTP requests.
|
||||
This lets other services access your app's data through an HTTP API, allowing
|
||||
it to easily interoperate with tools and frameworks that don't yet support DDP.
|
||||
|
||||
`webapp` exposes the [connect](https://github.com/senchalabs/connect) API for
|
||||
handling requests through `WebApp.connectHandlers`.
|
||||
`webapp` exposes the [express](https://github.com/expressjs/express) API for
|
||||
handling requests through `WebApp.handlers`.
|
||||
Here's an example that will let you handle a specific URL:
|
||||
|
||||
```js
|
||||
// Listen to incoming HTTP requests (can only be used on the server).
|
||||
WebApp.connectHandlers.use('/hello', (req, res, next) => {
|
||||
WebApp.handlers.use('/hello', (req, res, next) => {
|
||||
res.writeHead(200);
|
||||
res.end(`Hello world from: ${Meteor.release}`);
|
||||
});
|
||||
```
|
||||
|
||||
{% apibox "WebApp.connectHandlers" %}
|
||||
{% apibox "connectHandlersCallback(req, res, next)" %}
|
||||
{% apibox "WebApp.handlers" %}
|
||||
{% apibox "expressHandlersCallback(req, res, next)" %}
|
||||
|
||||
### Serving a Static Landing Page
|
||||
|
||||
@@ -62,36 +62,38 @@ Here's a sample _index.html_ you might use to get started:
|
||||
</html>
|
||||
```
|
||||
|
||||
Then using the connectHandlers method described above serve up your static HTML on app-root/ page load as shown below.
|
||||
Then using the handlers method described above serve up your static HTML on app-root/ page load as shown below.
|
||||
|
||||
```
|
||||
/* global WebApp Assets */
|
||||
import crypto from 'crypto'
|
||||
import connectRoute from 'connect-route'
|
||||
import express from 'express'
|
||||
|
||||
WebApp.connectHandlers.use(connectRoute(function (router) {
|
||||
router.get('/', function (req, res, next) {
|
||||
const buf = Assets.getText('index.html')
|
||||
const router = express.Router()
|
||||
|
||||
if (buf.length > 0) {
|
||||
const eTag = crypto.createHash('md5').update(buf).digest('hex')
|
||||
router.get('/', function (req, res, next) {
|
||||
const buf = Assets.getText('index.html')
|
||||
|
||||
if (req.headers['if-none-match'] === eTag) {
|
||||
res.writeHead(304, 'Not Modified')
|
||||
return res.end()
|
||||
}
|
||||
if (buf.length > 0) {
|
||||
const eTag = crypto.createHash('md5').update(buf).digest('hex')
|
||||
|
||||
res.writeHead(200, {
|
||||
ETag: eTag,
|
||||
'Content-Type': 'text/html'
|
||||
})
|
||||
|
||||
return res.end(buf);
|
||||
if (req.headers['if-none-match'] === eTag) {
|
||||
res.writeHead(304, 'Not Modified')
|
||||
return res.end()
|
||||
}
|
||||
|
||||
return res.end('<html><body>Index page not found!</body></html>')
|
||||
})
|
||||
}))
|
||||
res.writeHead(200, {
|
||||
ETag: eTag,
|
||||
'Content-Type': 'text/html'
|
||||
})
|
||||
|
||||
return res.end(buf)
|
||||
}
|
||||
|
||||
return res.end('<html><body>Index page not found!</body></html>')
|
||||
})
|
||||
|
||||
WebApp.handlers.use(router)
|
||||
```
|
||||
|
||||
There are a couple things to think about with this approach.
|
||||
@@ -160,4 +162,4 @@ WebApp.addUpdatedNotifyHook(({arch, manifest, runtimeConfig}) => {
|
||||
|
||||
{% apibox "WebApp.addUpdatedNotifyHook" %}
|
||||
{% apibox "addUpdatedNotifyHookCallback(options)" %}
|
||||
{% apibox "main" %}
|
||||
{% apibox "main" %}
|
||||
|
||||
1374
guide/package-lock.json
generated
1374
guide/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -99,7 +99,7 @@ If you are hosting a webfont as part of your application and serving it via a CD
|
||||
```js
|
||||
import { WebApp } from 'meteor/webapp';
|
||||
|
||||
WebApp.rawConnectHandlers.use(function(req, res, next) {
|
||||
WebApp.rawHandlers.use(function(req, res, next) {
|
||||
if (req._parsedUrl.pathname.match(/\.(ttf|ttc|otf|eot|woff|woff2|font\.css|css)$/)) {
|
||||
res.setHeader('Access-Control-Allow-Origin', /* your hostname, or just '*' */);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ title: Introduction
|
||||
description: This is the guide for using Meteor, a full-stack JavaScript platform for developing modern web and mobile applications.
|
||||
---
|
||||
|
||||
> Meteor 2.x runs on a deprecated Node.js version (14). Meteor 3.0, currently in its Release Candidate version, runs on Node.js v20. For more information, please consult our [migration guide](https://guide.meteor.com/3.0-migration.html).
|
||||
> Meteor 2.x uses the deprecated Node.js 14. Meteor 3.0 has been released and runs on Node.js 20. Check out our [v3 docs](https://v3-docs.meteor.com) and [migration guide](https://v3-migration-docs.meteor.com/).
|
||||
|
||||
<!-- XXX: note that this content is somewhat duplicated on the docs, and should be updated in parallel -->
|
||||
<h2 id="what-is-meteor">What is Meteor?</h2>
|
||||
@@ -44,11 +44,11 @@ meteor
|
||||
1. The place to get started with Meteor is the [tutorials page](https://www.meteor.com/developers/tutorials).
|
||||
|
||||
1. [Meteor Examples](https://github.com/meteor/examples) is a list of examples using Meteor. You can also include your example with Meteor.
|
||||
|
||||
|
||||
1. Once you are familiar with the basics, the [Meteor Guide](http://guide.meteor.com) covers intermediate material on how to use Meteor in a larger scale app.
|
||||
|
||||
1. Visit the [Meteor discussion forums](https://forums.meteor.com) to announce projects, get help, talk about the community, or discuss changes to core.
|
||||
|
||||
|
||||
1. [Meteor Slack Community](https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc) is the best place to ask (and answer!) technical questions and also meet Meteor developers.
|
||||
|
||||
1. [Atmosphere](https://atmospherejs.com) is the repository of community packages designed especially for Meteor.
|
||||
|
||||
@@ -497,7 +497,7 @@ By default, Helmet can be used to set various HTTP headers (see link above). The
|
||||
import helmet from "helmet";
|
||||
|
||||
// Within server side Meter.startup()
|
||||
WebApp.connectHandlers.use(helmet())
|
||||
WebApp.handlers.use(helmet())
|
||||
```
|
||||
|
||||
At a minimum, Meteor recommends users to set the following headers. Note that code examples shown below are specific to Helmet.
|
||||
@@ -517,7 +517,7 @@ By default, Meteor recommends unsafe inline scripts and styles are allowed, sinc
|
||||
import helmet from "helmet";
|
||||
|
||||
// Within server side Meter.startup()
|
||||
WebApp.connectHandlers.use(
|
||||
WebApp.handlers.use(
|
||||
helmet.contentSecurityPolicy({
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
@@ -696,7 +696,7 @@ With Helmet, Frameguard sets the X-Frame-Options header.
|
||||
import helmet from "helmet";
|
||||
|
||||
// Within server side Meter.startup()
|
||||
WebApp.connectHandlers.use(helmet.frameguard()); // defaults to sameorigin
|
||||
WebApp.handlers.use(helmet.frameguard()); // defaults to sameorigin
|
||||
```
|
||||
For more detail please read the following guide: [Frameguard](https://helmetjs.github.io/docs/frameguard/).
|
||||
|
||||
|
||||
9
meteor
9
meteor
@@ -1,13 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUNDLE_VERSION=14.21.4.9
|
||||
BUNDLE_VERSION=20.15.1.1
|
||||
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
# Use of : "${ARCH:=$(uname)}" assignment permits users to set their
|
||||
# architecture manually; this is useful for multi-arch systems whose
|
||||
# uname executables may sometimes return different architectures in
|
||||
# uname executables may sometimes return different architectures
|
||||
# in
|
||||
# different contexts.
|
||||
# Ex: ARCH=arm64 meteor ARGS...;
|
||||
UNAME="$(uname)"
|
||||
@@ -31,9 +32,9 @@ if [ "$UNAME" = "Darwin" ] ; then
|
||||
fi
|
||||
elif [ "$UNAME" = "Linux" ] ; then
|
||||
: "${ARCH:=$(uname -m)}"
|
||||
if [ "$ARCH" != "x86_64" ] ; then
|
||||
if [[ "$ARCH" != "x86_64" && "$ARCH" != "aarch64" ]] ; then
|
||||
echo "Unsupported architecture: $ARCH"
|
||||
echo "Meteor only supports x86_64"
|
||||
echo "Meteor only supports x86_64 and aarch64"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
exports.plugins = [
|
||||
require("@babel/plugin-syntax-nullish-coalescing-operator"),
|
||||
require("@babel/plugin-proposal-nullish-coalescing-operator"),
|
||||
|
||||
require("@babel/plugin-syntax-optional-chaining"),
|
||||
require("@babel/plugin-proposal-optional-chaining"),
|
||||
|
||||
require("@babel/plugin-syntax-optional-catch-binding"),
|
||||
require("@babel/plugin-proposal-optional-catch-binding"),
|
||||
|
||||
require("@babel/plugin-syntax-class-properties"),
|
||||
require("@babel/plugin-proposal-class-properties"),
|
||||
|
||||
require("@babel/plugin-syntax-async-generators"),
|
||||
require("@babel/plugin-proposal-async-generator-functions"),
|
||||
|
||||
require("@babel/plugin-syntax-object-rest-spread"),
|
||||
require("@babel/plugin-proposal-object-rest-spread"),
|
||||
|
||||
require("@babel/plugin-proposal-logical-assignment-operators"),
|
||||
];
|
||||
1314
npm-packages/babel-preset-meteor/package-lock.json
generated
Normal file
1314
npm-packages/babel-preset-meteor/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "babel-preset-meteor",
|
||||
"version": "7.10.2",
|
||||
"version": "7.10.4",
|
||||
"description": "Babel preset for ES2015+ features supported by Meteor",
|
||||
"author": "Ben Newman <ben@meteor.com>",
|
||||
"license": "MIT",
|
||||
@@ -11,13 +11,6 @@
|
||||
"update-versions": "bash scripts/update-versions"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.13.15",
|
||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||
"@babel/plugin-proposal-logical-assignment-operators": "^7.13.8",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.13.8",
|
||||
"@babel/plugin-proposal-optional-catch-binding": "^7.13.8",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
|
||||
"@babel/plugin-syntax-async-generators": "^7.8.4",
|
||||
"@babel/plugin-syntax-class-properties": "^7.12.13",
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
|
||||
@@ -25,16 +18,23 @@
|
||||
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
|
||||
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.13.0",
|
||||
"@babel/plugin-transform-async-generator-functions": "^7.24.6",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.13.0",
|
||||
"@babel/plugin-transform-block-scoped-functions": "^7.12.13",
|
||||
"@babel/plugin-transform-block-scoping": "^7.13.16",
|
||||
"@babel/plugin-transform-class-properties": "^7.24.6",
|
||||
"@babel/plugin-transform-classes": "^7.13.0",
|
||||
"@babel/plugin-transform-computed-properties": "^7.13.0",
|
||||
"@babel/plugin-transform-destructuring": "^7.13.17",
|
||||
"@babel/plugin-transform-exponentiation-operator": "^7.12.13",
|
||||
"@babel/plugin-transform-for-of": "^7.13.0",
|
||||
"@babel/plugin-transform-literals": "^7.12.13",
|
||||
"@babel/plugin-transform-logical-assignment-operators": "^7.24.6",
|
||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6",
|
||||
"@babel/plugin-transform-object-rest-spread": "^7.24.6",
|
||||
"@babel/plugin-transform-object-super": "^7.12.13",
|
||||
"@babel/plugin-transform-optional-catch-binding": "^7.24.6",
|
||||
"@babel/plugin-transform-optional-chaining": "^7.24.6",
|
||||
"@babel/plugin-transform-parameters": "^7.13.0",
|
||||
"@babel/plugin-transform-property-literals": "^7.12.13",
|
||||
"@babel/plugin-transform-regenerator": "^7.13.15",
|
||||
21
npm-packages/babel-preset-meteor/proposals.js
Normal file
21
npm-packages/babel-preset-meteor/proposals.js
Normal file
@@ -0,0 +1,21 @@
|
||||
exports.plugins = [
|
||||
require("@babel/plugin-syntax-nullish-coalescing-operator"),
|
||||
require("@babel/plugin-transform-nullish-coalescing-operator"),
|
||||
|
||||
require("@babel/plugin-syntax-optional-chaining"),
|
||||
require("@babel/plugin-transform-optional-chaining"),
|
||||
|
||||
require("@babel/plugin-syntax-optional-catch-binding"),
|
||||
require("@babel/plugin-transform-optional-catch-binding"),
|
||||
|
||||
require("@babel/plugin-syntax-class-properties"),
|
||||
require("@babel/plugin-transform-class-properties"),
|
||||
|
||||
require("@babel/plugin-syntax-async-generators"),
|
||||
require("@babel/plugin-transform-async-generator-functions"),
|
||||
|
||||
require("@babel/plugin-syntax-object-rest-spread"),
|
||||
require("@babel/plugin-transform-object-rest-spread"),
|
||||
|
||||
require("@babel/plugin-transform-logical-assignment-operators")
|
||||
];
|
||||
@@ -31,7 +31,7 @@
|
||||
"xcode": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cordova": "^9.0.0",
|
||||
"cordova": "^12.0.0",
|
||||
"cordova-paramedic": "github:meteor/cordova-paramedic#40df66c3efc2f0db4d66b8c172174a68c031c114",
|
||||
"ios-deploy": "^1.10.0-beta.3",
|
||||
"ios-sim": "^8.0.2"
|
||||
|
||||
@@ -60,9 +60,11 @@ if [ ! -x "$METEOR_WAREHOUSE_DIR/meteor" ]; then
|
||||
PLATFORM="os.linux.x86_32"
|
||||
elif [ "${LINUX_ARCH}" = "x86_64" ] ; then
|
||||
PLATFORM="os.linux.x86_64"
|
||||
elif [ "${LINUX_ARCH}" = "aarch64" ] ; then
|
||||
PLATFORM="os.linux.aarch64"
|
||||
else
|
||||
echo "Unusable architecture: ${LINUX_ARCH}"
|
||||
echo "Meteor only supports i686 and x86_64 for now."
|
||||
echo "Meteor only supports i686, x86_64 and aarch64 for now."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -42,7 +42,7 @@ main () {
|
||||
echo
|
||||
|
||||
# XXX there is no os.windows.x86_64 as we don't build for it at the moment
|
||||
PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 os.windows.x86_32 )
|
||||
PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 os.windows.x86_32 os.linux.aarch64 )
|
||||
for PLATFORM in ${PLATFORMS[@]}; do
|
||||
COMMAND="`dirname $0`/publish-meteor-tool-on-arch.sh $GITSHA $PLATFORM $SESSION_FILE"
|
||||
echo $COMMAND
|
||||
|
||||
@@ -18,7 +18,7 @@ main () {
|
||||
echo "usage: $0 <git sha> <platform> <path to meteor session>" 1>&2
|
||||
echo "The passed sha1 is checked out and published from the machines." 1>&2
|
||||
echo "Options for platform:" 1>&2
|
||||
echo " os.osx.x86_64 os.linux.x86_64 os.linux.x86_32" 1>&2
|
||||
echo " os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 os.linux.aarch64" 1>&2
|
||||
echo " os.windows.x86_32 os.windows.x86_64" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -33,7 +33,7 @@ main () {
|
||||
|
||||
METEOR="$CHECKOUT_DIR/meteor"
|
||||
|
||||
UNIX_PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 )
|
||||
UNIX_PLATFORMS=( os.osx.x86_64 os.linux.x86_64 os.linux.x86_32 os.linux.aarch64 )
|
||||
WINDOWS_PLATFORMS=( os.windows.x86_32 os.windows.x86_64 )
|
||||
|
||||
if [[ $PLATFORM =~ ^(os\.linux|os\.osx) ]] ; then
|
||||
|
||||
@@ -8,10 +8,6 @@ var packageJson = {
|
||||
name: "meteor-dev-bundle",
|
||||
private: true,
|
||||
dependencies: {
|
||||
// Keep the versions of these packages consistent with the versions
|
||||
// found in dev-bundle-tool-package.js.
|
||||
fibers: "https://github.com/meteor/node-fibers/archive/refs/tags/5.0.0.tar.gz",
|
||||
"meteor-promise": "0.9.0",
|
||||
promise: "8.1.0",
|
||||
"@meteorjs/reify": "0.24.0",
|
||||
"@babel/parser": "7.17.0",
|
||||
|
||||
@@ -10,16 +10,12 @@ var packageJson = {
|
||||
dependencies: {
|
||||
// Explicit dependency because we are replacing it with a bundled version
|
||||
// and we want to make sure there are no dependencies on a higher version
|
||||
npm: "6.14.18",
|
||||
npm: "10.7.0",
|
||||
pacote: "https://github.com/meteor/pacote/tarball/a81b0324686e85d22c7688c47629d4009000e8b8",
|
||||
"node-gyp": "8.0.0",
|
||||
"node-pre-gyp": "0.15.0",
|
||||
typescript: "4.9.5",
|
||||
"@meteorjs/babel": "7.18.0-beta.6",
|
||||
// Keep the versions of these packages consistent with the versions
|
||||
// found in dev-bundle-server-package.js.
|
||||
"meteor-promise": "0.9.0",
|
||||
fibers: "https://github.com/meteor/node-fibers/archive/refs/tags/5.0.0.tar.gz",
|
||||
"node-gyp": "9.4.0",
|
||||
"@mapbox/node-pre-gyp": "1.0.11",
|
||||
typescript: "5.4.5",
|
||||
"@meteorjs/babel": "7.19.0-beta.3",
|
||||
"@meteorjs/reify": "0.24.0",
|
||||
// So that Babel can emit require("@babel/runtime/helpers/...") calls.
|
||||
"@babel/runtime": "7.15.3",
|
||||
@@ -42,7 +38,7 @@ var packageJson = {
|
||||
kexec: "https://github.com/meteor/node-kexec/tarball/f29f54037c7db6ad29e1781463b182e5929215a0",
|
||||
"source-map": "0.7.3",
|
||||
chalk: "4.1.2",
|
||||
sqlite3: "5.0.2",
|
||||
sqlite3: "5.1.6",
|
||||
"http-proxy": "1.18.1",
|
||||
"is-reachable": "3.1.0",
|
||||
"wordwrap": "1.0.0",
|
||||
|
||||
@@ -35,6 +35,10 @@ function getReifyOptions(features) {
|
||||
// wrap it with a function to rename the `module` identifier.
|
||||
reifyOptions.moduleAlias = "module";
|
||||
}
|
||||
|
||||
if (features.topLevelAwait) {
|
||||
reifyOptions.topLevelAwait = true;
|
||||
}
|
||||
}
|
||||
|
||||
return reifyOptions;
|
||||
@@ -183,17 +187,15 @@ function getDefaultsForNode8(features) {
|
||||
require("@babel/plugin-proposal-object-rest-spread")
|
||||
);
|
||||
|
||||
// Ensure that async functions run in a Fiber, while also taking
|
||||
// full advantage of native async/await support in Node 8.
|
||||
const isFiberDisabled = process.env.DISABLE_FIBERS === '1';
|
||||
const ignoreAsyncPlugin = process.env.IGNORE_ASYNC_PLUGIN === '1';
|
||||
|
||||
if (!ignoreAsyncPlugin) {
|
||||
combined.plugins.push([require("./plugins/async-await.js"), {
|
||||
// Do not transform `await x` to `Promise.await(x)`, since Node
|
||||
// 8 has native support for await expressions.
|
||||
useNativeAsyncAwait: isFiberDisabled,
|
||||
}]);
|
||||
if (features.useNativeAsyncAwait === false) {
|
||||
combined.plugins.push([
|
||||
require('./plugins/async-await.js'),
|
||||
{
|
||||
// Even though Node 8 supports native async/await, it is not
|
||||
// compatible with fibers.
|
||||
useNativeAsyncAwait: false,
|
||||
},
|
||||
]);
|
||||
}
|
||||
// Enable async generator functions proposal.
|
||||
combined.plugins.push(require("@babel/plugin-proposal-async-generator-functions"));
|
||||
|
||||
2413
npm-packages/meteor-babel/package-lock.json
generated
2413
npm-packages/meteor-babel/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@meteorjs/babel",
|
||||
"author": "Meteor <dev@meteor.com>",
|
||||
"version": "7.18.4",
|
||||
"version": "7.20.0-beta.5",
|
||||
"license": "MIT",
|
||||
"type": "commonjs",
|
||||
"description": "Babel wrapper package for use with Meteor",
|
||||
@@ -42,22 +42,24 @@
|
||||
"@babel/template": "^7.16.7",
|
||||
"@babel/traverse": "^7.17.0",
|
||||
"@babel/types": "^7.17.0",
|
||||
"@meteorjs/reify": "0.24.1",
|
||||
"@meteorjs/reify": "0.25.2",
|
||||
"babel-preset-meteor": "^7.10.0",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"convert-source-map": "^1.6.0",
|
||||
"lodash": "^4.17.21",
|
||||
"meteor-babel-helpers": "0.0.3",
|
||||
"typescript": "~4.9.5"
|
||||
"typescript": "~5.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-decorators": "7.14.5",
|
||||
"@babel/plugin-syntax-decorators": "7.14.5",
|
||||
"d3": "4.13.0",
|
||||
"fibers": "5.0.0",
|
||||
"meteor-promise": "0.9.0",
|
||||
"mocha": "6.2.3",
|
||||
"promise": "8.1.0",
|
||||
"source-map": "0.6.1"
|
||||
},
|
||||
"volta": {
|
||||
"node": "14.21.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ module.exports = function (babel) {
|
||||
visitor: {
|
||||
Function: {
|
||||
exit: function (path) {
|
||||
if (this.opts.useNativeAsyncAwait !== false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = path.node;
|
||||
if (!node.async) {
|
||||
return;
|
||||
@@ -27,7 +31,7 @@ module.exports = function (babel) {
|
||||
node.body,
|
||||
// The inner function called by Promise.asyncApply should be
|
||||
// async if we have native async/await support.
|
||||
!! this.opts.useNativeAsyncAwait
|
||||
!!this.opts.useNativeAsyncAwait
|
||||
);
|
||||
|
||||
const promiseResultExpression = t.callExpression(
|
||||
@@ -53,7 +57,7 @@ module.exports = function (babel) {
|
||||
},
|
||||
|
||||
AwaitExpression: function (path) {
|
||||
if (this.opts.useNativeAsyncAwait) {
|
||||
if (this.opts.useNativeAsyncAwait !== false) {
|
||||
// No need to transform await expressions if we have native
|
||||
// support for them.
|
||||
return;
|
||||
|
||||
@@ -11,21 +11,3 @@ Module.prototype.resolve = function (id) {
|
||||
|
||||
require("@meteorjs/reify/lib/runtime").enable(Module.prototype);
|
||||
|
||||
if (!process.env.DISABLE_FIBERS) {
|
||||
require("meteor-promise").makeCompatible(
|
||||
global.Promise = global.Promise ||
|
||||
require("promise/lib/es6-extensions"),
|
||||
require("fibers")
|
||||
);
|
||||
|
||||
// If Promise.asyncApply is defined, use it to wrap calls to
|
||||
// regeneratorRuntime.async so that the entire async function will run in
|
||||
// its own Fiber, not just the code that comes after the first await.
|
||||
if (typeof Promise.asyncApply === "function") {
|
||||
var regeneratorRuntime = require("@babel/runtime/regenerator");
|
||||
var realAsync = regeneratorRuntime.async;
|
||||
regeneratorRuntime.async = function (innerFn) {
|
||||
return Promise.asyncApply(realAsync, regeneratorRuntime, arguments);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,11 @@ describe("@decorators", function () {
|
||||
.includes("decorators-legacy"));
|
||||
|
||||
assert.ok(legacyResult.options.plugins.some(function (plugin) {
|
||||
return plugin.key === "regenerator-transform";
|
||||
return plugin.key === "transform-regenerator";
|
||||
}));
|
||||
|
||||
assert.strictEqual(legacyResult.code.trim(), [
|
||||
"var _class;",
|
||||
"",
|
||||
"var A = dec(_class = function A() {}) || _class;",
|
||||
].join("\n"));
|
||||
});
|
||||
@@ -57,12 +56,11 @@ describe("@decorators", function () {
|
||||
.includes("decorators-legacy"));
|
||||
|
||||
assert.ok(legacyResult.options.plugins.every(function (plugin) {
|
||||
return plugin.key !== "regenerator-transform";
|
||||
return plugin.key !== "transform-regenerator";
|
||||
}));
|
||||
|
||||
assert.strictEqual(legacyResult.code.trim(), [
|
||||
"var _class;",
|
||||
"",
|
||||
"let A = dec(_class = class A {}) || _class;",
|
||||
].join("\n"));
|
||||
});
|
||||
@@ -89,16 +87,11 @@ describe("@decorators", function () {
|
||||
.includes("decorators-legacy"));
|
||||
|
||||
assert.ok(legacyResult.options.plugins.every(function (plugin) {
|
||||
return plugin.key !== "regenerator-transform";
|
||||
}));
|
||||
|
||||
assert.ok(legacyResult.options.plugins.some(function (plugin) {
|
||||
return plugin.key === "transform-meteor-async-await";
|
||||
return plugin.key !== "transform-regenerator";
|
||||
}));
|
||||
|
||||
assert.strictEqual(legacyResult.code.trim(), [
|
||||
"var _class;",
|
||||
"",
|
||||
"let A = dec(_class = class A {}) || _class;",
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
@@ -315,7 +315,6 @@ describe("@meteorjs/babel", () => {
|
||||
" }",
|
||||
"});",
|
||||
"var Test;",
|
||||
"",
|
||||
"(function (Test) {",
|
||||
" Test.enabled = true;",
|
||||
"})(Test || module.runSetters(Test = {}, [\"Test\"]));",
|
||||
@@ -775,40 +774,6 @@ val = "zxcv";`;
|
||||
assert.strictEqual(sum, limit * (limit + 1) / 2);
|
||||
});
|
||||
|
||||
it("Promise.await", () => {
|
||||
var markers = [];
|
||||
|
||||
async function f() {
|
||||
markers.push("before");
|
||||
if (require("fibers").current) {
|
||||
assert.strictEqual(
|
||||
Promise.await(Promise.resolve(1234)),
|
||||
1234
|
||||
);
|
||||
} else {
|
||||
assert.strictEqual(
|
||||
await Promise.resolve(1234),
|
||||
1234
|
||||
);
|
||||
}
|
||||
markers.push("after");
|
||||
return "done";
|
||||
}
|
||||
|
||||
assert.deepEqual(markers, []);
|
||||
|
||||
var promise = f();
|
||||
|
||||
// The async function should execute synchronously up to the first
|
||||
// Promise.await or await expression, but no further.
|
||||
assert.deepEqual(markers, ["before"]);
|
||||
|
||||
return promise.then(result => {
|
||||
assert.strictEqual(result, "done");
|
||||
assert.deepEqual(markers, ["before", "after"]);
|
||||
});
|
||||
});
|
||||
|
||||
it("async arrow functions", async function () {
|
||||
const addOneAsync = async arg => (await arg) + 1;
|
||||
const sum = await addOneAsync(2345);
|
||||
|
||||
@@ -1,19 +1,65 @@
|
||||
## 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 |
|
||||
| 2.15.0 | 2.15.0 |
|
||||
| 2.14.0 | 2.14.0 |
|
||||
| 2.13.3 | 2.13.3 |
|
||||
@@ -56,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.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const command = process.argv[2];
|
||||
const command = process.argv[2] || 'install';
|
||||
|
||||
if (!command) {
|
||||
console.log(`
|
||||
Usage: meteor-installer <command>
|
||||
Usage: npx meteor@<version> <command>
|
||||
|
||||
Commands:
|
||||
install
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const METEOR_LATEST_VERSION = '2.15';
|
||||
const METEOR_LATEST_VERSION = '3.0.2';
|
||||
const sudoUser = process.env.SUDO_USER || '';
|
||||
function isRoot() {
|
||||
return process.getuid && process.getuid() === 0;
|
||||
@@ -12,6 +12,7 @@ function isSudo() {
|
||||
const localAppData = process.env.LOCALAPPDATA;
|
||||
const isWindows = () => os.platform() === 'win32';
|
||||
const isMac = () => os.platform() === 'darwin';
|
||||
const isLinux = () => os.platform() === 'linux';
|
||||
|
||||
let rootPath;
|
||||
if (isWindows()) {
|
||||
@@ -21,7 +22,7 @@ if (isWindows()) {
|
||||
} else {
|
||||
if (isRoot()) {
|
||||
console.info(
|
||||
'You are running the install script as root, without SUDO. This is not recommended and should be avoided. Continuing.'
|
||||
'You are running the install script as root, without SUDO. This is not recommended and should be avoided. Continuing.',
|
||||
);
|
||||
}
|
||||
rootPath = os.homedir();
|
||||
@@ -47,6 +48,7 @@ module.exports = {
|
||||
startedPath: path.resolve(rootPath, '.meteor-install-started.txt'),
|
||||
isWindows,
|
||||
isMac,
|
||||
isLinux,
|
||||
isRoot,
|
||||
isSudo,
|
||||
shouldSetupExecPath,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const tar = require('tar');
|
||||
const sevenBin = require('7zip-bin');
|
||||
const Seven = require('node-7z');
|
||||
const fs = require('fs');
|
||||
const { resolve, dirname } = require('path');
|
||||
const child_process = require('child_process');
|
||||
const fs = require('fs');
|
||||
const Seven = require('node-7z');
|
||||
const { resolve, dirname } = require('path');
|
||||
const tar = require('tar');
|
||||
|
||||
const { isMac } = require('./config.js');
|
||||
|
||||
function extractWith7Zip(tarPath, destination, onProgress) {
|
||||
@@ -12,15 +13,15 @@ function extractWith7Zip(tarPath, destination, onProgress) {
|
||||
$progress: true,
|
||||
$bin: sevenBin.path7za,
|
||||
});
|
||||
stream.on('progress', function(progress) {
|
||||
stream.on('progress', function (progress) {
|
||||
onProgress(progress);
|
||||
});
|
||||
|
||||
stream.on('error', function(err) {
|
||||
stream.on('error', function (err) {
|
||||
return reject(err);
|
||||
});
|
||||
|
||||
stream.on('end', function() {
|
||||
stream.on('end', function () {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
@@ -55,7 +56,7 @@ function extractWithNativeTar(tarPath, destination) {
|
||||
env: process.env,
|
||||
stdio: [process.stdin, process.stdout, process.stderr],
|
||||
encoding: 'utf-8',
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ function extractWithTar(tarPath, destination, onProgress) {
|
||||
}
|
||||
createSymlinks(symlinks, destination);
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const { DownloaderHelper } = require('node-downloader-helper');
|
||||
const cliProgress = require('cli-progress');
|
||||
const Seven = require('node-7z');
|
||||
const path = require('path');
|
||||
const sevenBin = require('7zip-bin');
|
||||
const semver = require('semver');
|
||||
const child_process = require('child_process');
|
||||
const tmp = require('tmp');
|
||||
const os = require('os');
|
||||
const cliProgress = require('cli-progress');
|
||||
const fs = require('fs');
|
||||
const Seven = require('node-7z');
|
||||
const { DownloaderHelper } = require('node-downloader-helper');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const semver = require('semver');
|
||||
const tmp = require('tmp');
|
||||
|
||||
const fsPromises = fs.promises;
|
||||
|
||||
@@ -20,17 +20,17 @@ const {
|
||||
rootPath,
|
||||
sudoUser,
|
||||
isSudo,
|
||||
isMac,
|
||||
isLinux,
|
||||
METEOR_LATEST_VERSION,
|
||||
shouldSetupExecPath,
|
||||
} = require('./config');
|
||||
const { uninstall } = require('./uninstall');
|
||||
const {
|
||||
extractWithTar,
|
||||
extractWith7Zip,
|
||||
extractWithNativeTar,
|
||||
} = require('./extract');
|
||||
const { engines } = require('./package.json');
|
||||
const { uninstall } = require('./uninstall');
|
||||
|
||||
const nodeVersion = engines.node;
|
||||
const npmVersion = engines.npm;
|
||||
@@ -38,38 +38,41 @@ const npmVersion = engines.npm;
|
||||
// Compare installed NodeJs version with required NodeJs version
|
||||
if (!semver.satisfies(process.version, nodeVersion)) {
|
||||
console.warn(
|
||||
`WARNING: Recommended versions are Node.js ${nodeVersion} and npm ${npmVersion}.`
|
||||
`WARNING: Recommended versions are Node.js ${nodeVersion} and npm ${npmVersion}.`,
|
||||
);
|
||||
console.warn(
|
||||
`We recommend using a Node version manager like NVM or Volta to install Node.js and npm.\n`
|
||||
`We recommend using a Node version manager like NVM or Volta to install Node.js and npm.\n`,
|
||||
);
|
||||
}
|
||||
|
||||
const isInstalledGlobally = process.env.npm_config_global === 'true';
|
||||
const isInstalledGlobally =
|
||||
process.env.npm_config_global === 'true' ||
|
||||
process.env.npm_lifecycle_event === 'npx';
|
||||
|
||||
if (!isInstalledGlobally) {
|
||||
console.error('******************************************');
|
||||
console.error(
|
||||
'You are not using a global npm context to install, you should never add meteor to your package.json.'
|
||||
'You are not using a global npm context to install, you should never add meteor to your package.json.',
|
||||
);
|
||||
console.error('Make sure you pass -g to npm install.');
|
||||
console.error('Aborting...');
|
||||
console.error('******************************************');
|
||||
process.exit(1);
|
||||
process.exit(0);
|
||||
}
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
if (os.arch() !== 'x64') {
|
||||
const isValidM1Version = semver.gte(
|
||||
semver.coerce(METEOR_LATEST_VERSION),
|
||||
'2.5.1-beta.3'
|
||||
'2.5.1-beta.3',
|
||||
);
|
||||
if (os.arch() !== 'arm64' || !isMac() || !isValidM1Version) {
|
||||
if (os.arch() !== 'arm64' || !isValidM1Version) {
|
||||
console.error(
|
||||
'The current architecture is not supported in this version: ',
|
||||
os.arch(),
|
||||
'. Try Meteor 2.5.1-beta.3 or above.'
|
||||
'. Try Meteor 2.5.1-beta.3 or above.',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -81,9 +84,15 @@ const downloadPlatform = {
|
||||
linux: 'linux',
|
||||
};
|
||||
|
||||
const url = `https://packages.meteor.com/bootstrap-link?arch=os.${
|
||||
downloadPlatform[os.platform()]
|
||||
}.${os.arch() === 'arm64' ? 'arm64' : 'x86_64'}&release=${release}`;
|
||||
function getDownloadArch() {
|
||||
const osArch = os.arch();
|
||||
if (isLinux() && osArch === 'arm64') return 'aarch64';
|
||||
if (osArch === 'arm64') return 'arm64';
|
||||
return 'x86_64';
|
||||
}
|
||||
|
||||
const arch = `os.${downloadPlatform[os.platform()]}.${getDownloadArch()}`;
|
||||
const url = `https://packages.meteor.com/bootstrap-link?arch=${arch}&release=${release}`;
|
||||
|
||||
let tempDirObject;
|
||||
try {
|
||||
@@ -95,10 +104,10 @@ try {
|
||||
console.error("Couldn't create tmp dir for extracting meteor.");
|
||||
console.error('There are 2 possible causes:');
|
||||
console.error(
|
||||
'\t1. You are running npm install -g meteor as root without passing the --unsafe-perm option. Please rerun with this option enabled.'
|
||||
'\t1. You are running npm install -g meteor as root without passing the --unsafe-perm option. Please rerun with this option enabled.',
|
||||
);
|
||||
console.error(
|
||||
'\t2. You might not have enough space in disk or permission to create folders'
|
||||
'\t2. You might not have enough space in disk or permission to create folders',
|
||||
);
|
||||
console.error('****************************');
|
||||
console.error('');
|
||||
@@ -121,9 +130,9 @@ if (fs.existsSync(startedPath)) {
|
||||
console.log(
|
||||
`If you want to reinstall it, run:
|
||||
|
||||
$ meteor-installer uninstall
|
||||
$ meteor-installer install
|
||||
`
|
||||
$ npx meteor uninstall
|
||||
$ npx meteor@<version> install
|
||||
`,
|
||||
);
|
||||
process.exit();
|
||||
}
|
||||
@@ -151,6 +160,9 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`=> Arch: ${arch}`);
|
||||
console.log(`=> Meteor Release: ${release}`);
|
||||
|
||||
download();
|
||||
|
||||
function generateProxyAgent() {
|
||||
@@ -171,7 +183,7 @@ function download() {
|
||||
format: 'Downloading |{bar}| {percentage}%',
|
||||
clearOnComplete: true,
|
||||
},
|
||||
cliProgress.Presets.shades_classic
|
||||
cliProgress.Presets.shades_classic,
|
||||
);
|
||||
downloadProgress.start(100, 0);
|
||||
|
||||
@@ -209,7 +221,7 @@ function download() {
|
||||
await extractWithNativeTar(path.resolve(tempPath, tarGzName), extractPath);
|
||||
const extractEnd = Date.now();
|
||||
console.log(
|
||||
`=> Meteor extracted in ${(extractEnd - extractStart) / 1000}s`
|
||||
`=> Meteor extracted in ${(extractEnd - extractStart) / 1000}s`,
|
||||
);
|
||||
await setup();
|
||||
});
|
||||
@@ -224,7 +236,7 @@ function decompress() {
|
||||
format: 'Decompressing |{bar}| {percentage}%',
|
||||
clearOnComplete: true,
|
||||
},
|
||||
cliProgress.Presets.shades_classic
|
||||
cliProgress.Presets.shades_classic,
|
||||
);
|
||||
decompressProgress.start(100, 0);
|
||||
|
||||
@@ -232,11 +244,11 @@ function decompress() {
|
||||
$progress: true,
|
||||
$bin: sevenBin.path7za,
|
||||
});
|
||||
myStream.on('progress', function(progress) {
|
||||
myStream.on('progress', function (progress) {
|
||||
decompressProgress.update(progress.percent);
|
||||
});
|
||||
|
||||
myStream.on('end', function() {
|
||||
myStream.on('end', function () {
|
||||
decompressProgress.update(100);
|
||||
decompressProgress.stop();
|
||||
const end = Date.now();
|
||||
@@ -254,7 +266,7 @@ async function extract() {
|
||||
format: 'Extracting |{bar}| {percentage}% - {fileCount} files completed',
|
||||
clearOnComplete: true,
|
||||
},
|
||||
cliProgress.Presets.shades_classic
|
||||
cliProgress.Presets.shades_classic,
|
||||
);
|
||||
decompressProgress.start(100, 0, {
|
||||
fileCount: 0,
|
||||
@@ -290,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`;
|
||||
@@ -316,7 +330,7 @@ function showGettingStarted() {
|
||||
const exportCommand = `export PATH=${meteorPath}:$PATH`;
|
||||
|
||||
const runCommand = isWindows()
|
||||
? `set path "${meteorPath}/;%path%`
|
||||
? `set path "${meteorPath}/;%path%"`
|
||||
: exportCommand;
|
||||
const message = `
|
||||
***************************************
|
||||
|
||||
792
npm-packages/meteor-installer/package-lock.json
generated
Normal file
792
npm-packages/meteor-installer/package-lock.json
generated
Normal file
@@ -0,0 +1,792 @@
|
||||
{
|
||||
"name": "meteor",
|
||||
"version": "3.0.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "meteor",
|
||||
"version": "3.0.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"7zip-bin": "^5.2.0",
|
||||
"cli-progress": "^3.11.1",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"node-7z": "^2.1.2",
|
||||
"node-downloader-helper": "^2.1.9",
|
||||
"rimraf": "^6.0.1",
|
||||
"semver": "^7.3.7",
|
||||
"tar": "^6.1.11",
|
||||
"tmp": "^0.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"meteor-installer": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.x",
|
||||
"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",
|
||||
"integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"engines": {
|
||||
"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==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-progress": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz",
|
||||
"integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
|
||||
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"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": "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",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"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",
|
||||
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA=="
|
||||
},
|
||||
"node_modules/lodash.defaultto": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaultto/-/lodash.defaultto-4.14.0.tgz",
|
||||
"integrity": "sha512-G6tizqH6rg4P5j32Wy4Z3ZIip7OfG8YWWlPFzUFGcYStH1Ld0l1tWs6NevEQNEDnO1M3NZYjuHuraaFSN5WqeQ=="
|
||||
},
|
||||
"node_modules/lodash.flattendeep": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
|
||||
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ=="
|
||||
},
|
||||
"node_modules/lodash.isempty": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
|
||||
"integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg=="
|
||||
},
|
||||
"node_modules/lodash.negate": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.negate/-/lodash.negate-3.0.2.tgz",
|
||||
"integrity": "sha512-JGJYYVslKYC0tRMm/7igfdHulCjoXjoganRNWM8AgS+RXfOvFnPkOveDhPI65F9aAypCX9QEEQoBqWf7Q6uAeA=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"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": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/node-7z": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-7z/-/node-7z-2.1.2.tgz",
|
||||
"integrity": "sha512-mSmn90OIYKYIkuRwH1YRJl2sMwB9OlYhCQS4SPTOfxlzWwomoC1G9j4tsvAsv7vJPwvK7B76Z0a2dH5Mvwo91Q==",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.1.1",
|
||||
"lodash.defaultsdeep": "^4.6.1",
|
||||
"lodash.defaultto": "^4.14.0",
|
||||
"lodash.flattendeep": "^4.4.0",
|
||||
"lodash.isempty": "^4.4.0",
|
||||
"lodash.negate": "^3.0.2",
|
||||
"normalize-path": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/node-downloader-helper": {
|
||||
"version": "2.1.9",
|
||||
"resolved": "https://registry.npmjs.org/node-downloader-helper/-/node-downloader-helper-2.1.9.tgz",
|
||||
"integrity": "sha512-FSvAol2Z8UP191sZtsUZwHIN0eGoGue3uEXGdWIH5228e9KH1YHXT7fN8Oa33UGf+FbqGTQg3sJfrRGzmVCaJA==",
|
||||
"bin": {
|
||||
"ndh": "bin/ndh"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"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": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"engines": {
|
||||
"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",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"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",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"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",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meteor",
|
||||
"version": "2.15.0",
|
||||
"version": "3.0.2",
|
||||
"description": "Install Meteor",
|
||||
"main": "install.js",
|
||||
"scripts": {
|
||||
@@ -14,8 +14,8 @@
|
||||
"cli-progress": "^3.11.1",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"node-7z": "^2.1.2",
|
||||
"node-downloader-helper": "^1.0.19",
|
||||
"rimraf": "^3.0.2",
|
||||
"node-downloader-helper": "^2.1.9",
|
||||
"rimraf": "^6.0.1",
|
||||
"semver": "^7.3.7",
|
||||
"tar": "^6.1.11",
|
||||
"tmp": "^0.2.1"
|
||||
@@ -24,7 +24,7 @@
|
||||
"meteor-installer": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "<=14.x",
|
||||
"npm": "<=6.x"
|
||||
"node": ">=20.x",
|
||||
"npm": ">=10.x"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const { meteorPath } = require('./config');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
const { meteorPath } = require('./config');
|
||||
|
||||
function uninstall() {
|
||||
console.log(`Uninstalling Meteor from ${meteorPath}`);
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
"main": "promise_server.js",
|
||||
"browser": "promise_client.js",
|
||||
"typings": "promise.d.ts",
|
||||
"scripts": {
|
||||
"test": "test/run.sh"
|
||||
},
|
||||
"homepage": "https://github.com/meteor/promise",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -9,7 +9,7 @@ exports.makeCompatible = function (Promise, Fiber) {
|
||||
}
|
||||
|
||||
if (es6PromiseThen.name === "meteorPromiseThen") {
|
||||
return; // Already compatible.
|
||||
return; // Already compatible
|
||||
}
|
||||
|
||||
function meteorPromiseThen(onResolved, onRejected) {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Mocha</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="mocha.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="mocha.js"></script>
|
||||
<script>mocha.setup('bdd')</script>
|
||||
<script src="tests.js"></script>
|
||||
<script>
|
||||
mocha.run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,270 +0,0 @@
|
||||
@charset "utf-8";
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#mocha {
|
||||
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: 60px 50px;
|
||||
}
|
||||
|
||||
#mocha ul,
|
||||
#mocha li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#mocha ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#mocha h1,
|
||||
#mocha h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mocha h1 {
|
||||
margin-top: 15px;
|
||||
font-size: 1em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
#mocha h1 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha h1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#mocha .suite .suite h1 {
|
||||
margin-top: 0;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#mocha .hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#mocha .suite {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test {
|
||||
margin-left: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#mocha .test.pending:hover h2::after {
|
||||
content: '(pending)';
|
||||
font-family: arial, sans-serif;
|
||||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #c09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #b94a48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
content: '✓';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #00d6b2;
|
||||
}
|
||||
|
||||
#mocha .test.pass .duration {
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.pending::before {
|
||||
content: '◦';
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.fail {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test.fail pre {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha .test.fail::before {
|
||||
content: '✖';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre.error {
|
||||
color: #c00;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* (1): approximate for browsers not supporting calc
|
||||
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
|
||||
* ^^ seriously
|
||||
*/
|
||||
#mocha .test pre {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
max-width: 85%; /*(1)*/
|
||||
max-width: calc(100% - 42px); /*(2)*/
|
||||
word-wrap: break-word;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-border-radius: 3px;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
-moz-border-radius: 3px;
|
||||
-moz-box-shadow: 0 1px 3px #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#mocha .test h2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mocha .test a.replay {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 0;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
font-size: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
-webkit-transition: opacity 200ms;
|
||||
-moz-transition: opacity 200ms;
|
||||
transition: opacity 200ms;
|
||||
opacity: 0.3;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha .test:hover a.replay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#mocha-report.pass .test.fail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.fail .test.pass {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.pending .test.pass,
|
||||
#mocha-report.pending .test.fail {
|
||||
display: none;
|
||||
}
|
||||
#mocha-report.pending .test.pass.pending {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#mocha-error {
|
||||
color: #c00;
|
||||
font-size: 1.5em;
|
||||
font-weight: 100;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#mocha-stats {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
color: #888;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#mocha-stats .progress {
|
||||
float: right;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#mocha-stats em {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha-stats a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha-stats a:hover {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#mocha-stats li {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
list-style: none;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
#mocha-stats canvas {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#mocha code .comment { color: #ddd; }
|
||||
#mocha code .init { color: #2f6fad; }
|
||||
#mocha code .string { color: #5890ad; }
|
||||
#mocha code .keyword { color: #8a6343; }
|
||||
#mocha code .number { color: #2f6fad; }
|
||||
|
||||
@media screen and (max-device-width: 480px) {
|
||||
#mocha {
|
||||
margin: 60px 0px;
|
||||
}
|
||||
|
||||
#mocha #stats {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
mocha \
|
||||
--harmony \
|
||||
--reporter spec \
|
||||
--full-trace \
|
||||
test/tests.js
|
||||
|
||||
USE_GLOBAL_PROMISE=1 \
|
||||
mocha \
|
||||
--harmony \
|
||||
--reporter spec \
|
||||
--full-trace \
|
||||
test/tests.js
|
||||
@@ -1,411 +0,0 @@
|
||||
var assert = require("assert");
|
||||
var Fiber = require("fibers");
|
||||
var Future = require("fibers/future");
|
||||
var Promise = process.env.USE_GLOBAL_PROMISE
|
||||
? global.Promise
|
||||
: require("promise/lib/es6-extensions");
|
||||
|
||||
if (! Promise) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
require("../promise_server.js").makeCompatible(Promise, Fiber);
|
||||
|
||||
function wait(ms) {
|
||||
var self = this;
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(function () {
|
||||
resolve.apply(self, args);
|
||||
}, ms);
|
||||
});
|
||||
}
|
||||
|
||||
describe("Promise.await", function () {
|
||||
it("should work inside an existing Fiber", Promise.async(function () {
|
||||
assert.strictEqual(Promise.await(42), 42);
|
||||
assert.strictEqual(Promise.await(Promise.resolve("asdf")), "asdf");
|
||||
|
||||
var obj = {};
|
||||
assert.strictEqual(Promise.resolve(obj).await(), obj);
|
||||
}));
|
||||
|
||||
it("should not switch Fibers", Promise.async(function () {
|
||||
var originalFiber = Fiber.current;
|
||||
assert.ok(originalFiber instanceof Fiber);
|
||||
var promise = Promise.resolve(0);
|
||||
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
promise = promise.then(function (count) {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
assert.notStrictEqual(Fiber.current, originalFiber);
|
||||
return count + 1;
|
||||
});
|
||||
}
|
||||
|
||||
assert.strictEqual(Promise.await(promise), 100);
|
||||
assert.strictEqual(Fiber.current, originalFiber);
|
||||
}));
|
||||
|
||||
it("should throw rejection reasons", Promise.async(function () {
|
||||
var reason = new Error("reason");
|
||||
try {
|
||||
Promise.await(Promise.reject(reason));
|
||||
assert.ok(false, "should have thrown");
|
||||
} catch (error) {
|
||||
assert.strictEqual(error, reason);
|
||||
}
|
||||
}));
|
||||
|
||||
it("should not hang when inner promise returned from callback", Promise.async(function () {
|
||||
function go(n) {
|
||||
return n === 0
|
||||
? Promise.resolve("done")
|
||||
: wait(0, n - 1).then(go);
|
||||
}
|
||||
|
||||
var results = Promise.all([
|
||||
wait(50, "a").then(function (a) {
|
||||
return wait(100, a + "b").then(function (ab) {
|
||||
return wait(2, ab + "c");
|
||||
});
|
||||
}),
|
||||
go(10),
|
||||
go(20)
|
||||
]).await();
|
||||
|
||||
assert.deepEqual(results, [
|
||||
"abc",
|
||||
"done",
|
||||
"done"
|
||||
]);
|
||||
}));
|
||||
});
|
||||
|
||||
describe("Promise.awaitAll", function () {
|
||||
it("should await multiple promises", Promise.async(function () {
|
||||
assert.deepEqual(Promise.awaitAll([
|
||||
123,
|
||||
Promise.resolve("oyez"),
|
||||
new Promise(function (resolve) {
|
||||
process.nextTick(function () {
|
||||
resolve("resolved");
|
||||
});
|
||||
})
|
||||
]), [123, "oyez", "resolved"]);
|
||||
}));
|
||||
});
|
||||
|
||||
describe("Promise.async", function () {
|
||||
it("should create a new Fiber", function () {
|
||||
var self = this;
|
||||
|
||||
var parent = Promise.async(function () {
|
||||
var parentFiber = Fiber.current;
|
||||
assert.ok(parentFiber instanceof Fiber);
|
||||
|
||||
var childFibers = [];
|
||||
var child = Promise.async(function (arg) {
|
||||
assert.strictEqual(this, self);
|
||||
|
||||
var childFiber = Fiber.current;
|
||||
assert.ok(childFiber instanceof Fiber);
|
||||
assert.notStrictEqual(childFiber, parentFiber);
|
||||
|
||||
assert.strictEqual(childFibers.indexOf(childFiber), -1);
|
||||
childFibers.push(childFiber);
|
||||
|
||||
return Promise.await(arg);
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
child.call(this, 1),
|
||||
child.call(this, 2),
|
||||
child.call(this, 3)
|
||||
]);
|
||||
});
|
||||
|
||||
return parent.call(this).then(function (results) {
|
||||
assert.deepEqual(results, [1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should be able to reuse Fiber.current", function () {
|
||||
var self = this;
|
||||
|
||||
var parent = Promise.async(function () {
|
||||
var parentFiber = Fiber.current;
|
||||
assert.ok(parentFiber instanceof Fiber);
|
||||
|
||||
var childFibers = [];
|
||||
var child = Promise.async(function (arg) {
|
||||
assert.strictEqual(this, self);
|
||||
|
||||
var childFiber = Fiber.current;
|
||||
assert.ok(childFiber instanceof Fiber);
|
||||
assert.strictEqual(childFiber, parentFiber);
|
||||
|
||||
childFibers.forEach(function (otherChildFiber) {
|
||||
assert.strictEqual(childFiber, otherChildFiber);
|
||||
});
|
||||
childFibers.push(childFiber);
|
||||
|
||||
return Promise.await(arg);
|
||||
}, true);
|
||||
|
||||
return Promise.all([
|
||||
child.call(this, 1),
|
||||
child.call(this, 2),
|
||||
child.call(this, 3)
|
||||
]);
|
||||
});
|
||||
|
||||
return parent.call(this).then(function (results) {
|
||||
assert.deepEqual(results, [1, 2, 3]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Promise.then callbacks", function () {
|
||||
it("should always run in a fiber", Promise.async(function () {
|
||||
var parentFiber = Fiber.current;
|
||||
assert.ok(parentFiber instanceof Fiber);
|
||||
|
||||
var dynamics = { user: "ben" };
|
||||
parentFiber._meteorDynamics = dynamics;
|
||||
|
||||
function checkCallbackFiber() {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
assert.deepEqual(Fiber.current._meteorDynamics, dynamics);
|
||||
}
|
||||
|
||||
return Promise.resolve("result").then(function (result) {
|
||||
assert.strictEqual(result, "result");
|
||||
checkCallbackFiber();
|
||||
throw new Error("friendly exception");
|
||||
}).catch(function (error) {
|
||||
assert.strictEqual(error.message, "friendly exception");
|
||||
checkCallbackFiber();
|
||||
});
|
||||
}));
|
||||
|
||||
it("should not double-wrap callbacks", Promise.async(function () {
|
||||
// Consume all fibers currently in the pool, so that we can detect how many
|
||||
// new fibers are created after that point.
|
||||
var done = new Future();
|
||||
var origCount = Fiber.fibersCreated;
|
||||
|
||||
while (Fiber.fibersCreated == origCount) {
|
||||
// Force creation of a new fiber that blocks until we're done.
|
||||
var ready = new Future();
|
||||
Promise.asyncApply(function () {
|
||||
ready.return();
|
||||
done.wait();
|
||||
});
|
||||
ready.wait(); // Make sure fiber is running before we continue.
|
||||
}
|
||||
|
||||
// OK, we're now in a situation where a Promise.then() should create
|
||||
// *one* new fiber.
|
||||
var baseCount = Fiber.fibersCreated;
|
||||
|
||||
// Create some named no-op promises and callbacks. I'm assigning names
|
||||
// to these so that the comments below are easier to read.
|
||||
var promise1 = Promise.resolve();
|
||||
var promise2 = Promise.resolve();
|
||||
var returnPromise2 = function () { return promise2; };
|
||||
var cb = function () {};
|
||||
|
||||
// Make sure this didn't create any fibers.
|
||||
assert.strictEqual(baseCount, Fiber.fibersCreated);
|
||||
|
||||
// This should create one fiber, and return it to the pool.
|
||||
// Note that you can remove these two lines and the test still works and
|
||||
// tests the right thing. This is just checking my assumptions.
|
||||
promise1.then(returnPromise2).await();
|
||||
assert.strictEqual(baseCount + 1, Fiber.fibersCreated);
|
||||
|
||||
// This should NOT create a another fiber. It should reuse the fiber
|
||||
// created by the above block. However, if callback double-wrapping
|
||||
// is not prevented, then cb will end up being wrapped *twice*, and
|
||||
// thus *two* fibers will be created at the same time.
|
||||
//
|
||||
// What happens is:
|
||||
// * .then(cb) wraps cb (let's call the wrapped version wcb) and passes
|
||||
// it on to the Promise implementation.
|
||||
// * On next tick, promise1 "completes", so returnPromise2() is called.
|
||||
// * Since it returns a promise (promise2), the Promise implementation
|
||||
// calls promise2.then(wcb) -- forwarding the callback on to the next
|
||||
// promise in the chain.
|
||||
// * Our monkey-patched .then() is used here. If we don't detect that
|
||||
// the callback is already wrapped, we'll end up wrapping it again!
|
||||
var promise3 = promise1.then(returnPromise2);
|
||||
promise3.then(cb).await();
|
||||
|
||||
// If we double-wrapped the callback, then fibersCreated will end up
|
||||
// being baseCount + 2 instead of baseCount + 1.
|
||||
assert.strictEqual(baseCount + 1, Fiber.fibersCreated);
|
||||
|
||||
done.return();
|
||||
}));
|
||||
});
|
||||
|
||||
describe("FiberPool", function () {
|
||||
it("should still work when the target size is 1 or 0", function () {
|
||||
var fiberPool = require("../fiber_pool.js").makePool();
|
||||
|
||||
return fiberPool.setTargetFiberCount(1).run({
|
||||
callback: function () {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
return Fiber.current;
|
||||
}
|
||||
}, Promise).then(function (firstFiber) {
|
||||
return fiberPool.run({
|
||||
callback: function () {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
assert.strictEqual(Fiber.current, firstFiber);
|
||||
fiberPool.drain();
|
||||
return Fiber.current;
|
||||
}
|
||||
}, Promise);
|
||||
}).then(function (secondFiber) {
|
||||
return fiberPool.run({
|
||||
callback: function () {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
assert.notStrictEqual(Fiber.current, secondFiber);
|
||||
}
|
||||
}, Promise);
|
||||
});
|
||||
});
|
||||
|
||||
it("should ignore bogus fiber.run arguments", function () {
|
||||
var fiberPool = require("../fiber_pool.js").makePool();
|
||||
var fiber;
|
||||
|
||||
return fiberPool.setTargetFiberCount(1).run({
|
||||
callback() {
|
||||
fiber = Fiber.current;
|
||||
}
|
||||
}, Promise).then(() => {
|
||||
assert.ok(Fiber.current instanceof Fiber);
|
||||
assert.notStrictEqual(Fiber.current, fiber);
|
||||
fiber.run("bogus");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("dynamic environment", function () {
|
||||
it("should be restored to cloned values", Promise.async(function () {
|
||||
var fiber = Fiber.current;
|
||||
assert.ok(fiber instanceof Fiber);
|
||||
|
||||
var asdf = fiber._asdf = [1, /* hole */, 3];
|
||||
var expected = new Error("expected");
|
||||
var promise = Promise.resolve(asdf).then(function (asdf) {
|
||||
var fiber = Fiber.current;
|
||||
assert.notStrictEqual(asdf, fiber._asdf);
|
||||
assert.deepEqual(asdf, fiber._asdf);
|
||||
fiber._asdf.push(4);
|
||||
throw expected;
|
||||
}).catch(function (error) {
|
||||
assert.strictEqual(error, expected);
|
||||
var fiber = Fiber.current;
|
||||
assert.notStrictEqual(asdf, fiber._asdf);
|
||||
assert.deepEqual(asdf, fiber._asdf);
|
||||
assert.strictEqual(asdf.length, 3);
|
||||
});
|
||||
|
||||
// Own properties should have been cloned when .then and .catch were
|
||||
// called, so deleting this property here should have no impact on the
|
||||
// behavior of the callbacks.
|
||||
delete fiber._asdf;
|
||||
|
||||
return promise;
|
||||
}));
|
||||
});
|
||||
|
||||
describe("uncaught exceptions", function () {
|
||||
it("should be emitted via process.domain", function (done) {
|
||||
var domain = require("domain").create();
|
||||
var expected = new Error("expected");
|
||||
var fiber = new Fiber(function () {
|
||||
Promise.await("asdf");
|
||||
throw expected;
|
||||
});
|
||||
|
||||
function onError(error) {
|
||||
assert.strictEqual(error, expected);
|
||||
done();
|
||||
}
|
||||
|
||||
domain.on("error", onError);
|
||||
|
||||
domain.run(function () {
|
||||
fiber.run();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("promise_client.js", function () {
|
||||
it("should use Meteor.bindEnvironment", function () {
|
||||
var savedMeteor = global.Meteor;
|
||||
var calledBindEnvironment = false;
|
||||
var calledBoundFunction = false;
|
||||
|
||||
global.Meteor = {
|
||||
bindEnvironment: function (handler) {
|
||||
calledBindEnvironment = true;
|
||||
return function () {
|
||||
calledBoundFunction = true;
|
||||
return handler.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var Promise = require("promise");
|
||||
var desc = Object.getOwnPropertyDescriptor(Promise.prototype, "then");
|
||||
desc.writable = true;
|
||||
Object.defineProperty(Promise.prototype, "then", desc);
|
||||
require("../promise_client.js").makeCompatible(Promise);
|
||||
|
||||
var p = Promise.resolve(1234).then(function (value) {
|
||||
assert.strictEqual(value, 1234);
|
||||
assert.strictEqual(calledBindEnvironment, true);
|
||||
assert.strictEqual(calledBoundFunction, true);
|
||||
global.Meteor = savedMeteor;
|
||||
});
|
||||
|
||||
assert.strictEqual(calledBindEnvironment, true);
|
||||
assert.strictEqual(calledBoundFunction, false);
|
||||
|
||||
return p;
|
||||
});
|
||||
});
|
||||
|
||||
describe("stack traces", function () {
|
||||
it("should reflect awaiting context(s) as well", Promise.async(function test() {
|
||||
function inner() {
|
||||
throw new Error("oyez");
|
||||
}
|
||||
|
||||
var middle = Promise.async(function middle() {
|
||||
return Promise.await(new Promise(inner));
|
||||
});
|
||||
|
||||
var outer = Promise.async(function outer() {
|
||||
return Promise.await(middle());
|
||||
});
|
||||
|
||||
return outer().catch(function (error) {
|
||||
assert.strictEqual(error.message, "oyez");
|
||||
|
||||
var sections = error.stack.split("=> awaited here:");
|
||||
assert.strictEqual(sections.length, 3);
|
||||
|
||||
assert.notStrictEqual(sections[0].indexOf("at inner"), -1);
|
||||
assert.notStrictEqual(sections[1].indexOf("at middle"), -1);
|
||||
assert.notStrictEqual(sections[2].indexOf("at outer"), -1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
7050
package-lock.json
generated
7050
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
55
package.json
55
package.json
@@ -13,19 +13,46 @@
|
||||
},
|
||||
"homepage": "https://github.com/meteor/meteor#readme",
|
||||
"devDependencies": {
|
||||
"@quave/eslint-config-quave": "^1.0.7",
|
||||
"@types/node": "^14.18.63"
|
||||
"@babel/core": "^7.21.3",
|
||||
"@babel/eslint-parser": "^7.21.3",
|
||||
"@babel/eslint-plugin": "^7.19.1",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@types/node": "^18.16.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"@typescript-eslint/parser": "^5.56.0",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-vazco": "^7.1.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"prettier": "^2.8.6",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"esversion": 11
|
||||
},
|
||||
"prettier": {
|
||||
"semi": true,
|
||||
"singleQuote": false
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"@quave/quave"
|
||||
],
|
||||
"extends": "vazco",
|
||||
"rules": {
|
||||
"global-require": "off",
|
||||
"no-console": "off",
|
||||
"camelcase": "warn",
|
||||
"consistent-return": "off",
|
||||
"quotes": "warn",
|
||||
"quotes": [
|
||||
"warn",
|
||||
"single",
|
||||
{
|
||||
"allowTemplateLiterals": true
|
||||
}
|
||||
],
|
||||
"no-shadow": [
|
||||
"error",
|
||||
{
|
||||
@@ -35,7 +62,21 @@
|
||||
}
|
||||
],
|
||||
"no-use-before-define": "warn",
|
||||
"import/no-unresolved": "warn"
|
||||
"import/no-unresolved": "warn",
|
||||
"require-await": "warn",
|
||||
"space-before-function-paren": [
|
||||
"warn",
|
||||
{
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"complexity": "off",
|
||||
"func-names": "off",
|
||||
"no-undef": "warn",
|
||||
"curly": "off",
|
||||
"sort-imports": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 4,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "18.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz",
|
||||
"integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg=="
|
||||
"version": "22.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
|
||||
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g=="
|
||||
},
|
||||
"@types/notp": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.2.tgz",
|
||||
"integrity": "sha512-JUcVYN9Tmw0AjoAfvjslS4hbv39fPBbZdftBK3b50g5z/DmhLsu6cd0UOEBiQuMwy2FirshF2Gk9gAvfWjshMw=="
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.5.tgz",
|
||||
"integrity": "sha512-ZsZS0PYUa6ZE4K3yOGerBvaxCp4ePf6ZmkFbPeilcqz2Ui/lmXox7KlRt7XZkXzqUgXhFLkc09ixyVmFLCU3gQ=="
|
||||
},
|
||||
"node-2fa": {
|
||||
"version": "2.0.3",
|
||||
@@ -32,9 +32,14 @@
|
||||
"integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||
},
|
||||
"undici-types": {
|
||||
"version": "6.18.2",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
|
||||
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ Accounts._check2faEnabled = user => {
|
||||
);
|
||||
};
|
||||
|
||||
Accounts._is2faEnabledForUser = () => {
|
||||
const user = Meteor.user();
|
||||
Accounts._is2faEnabledForUser = async () => {
|
||||
const user = await Meteor.userAsync();
|
||||
if (!user) {
|
||||
throw new Meteor.Error('no-logged-user', 'No user logged in.');
|
||||
}
|
||||
@@ -34,9 +34,9 @@ Accounts._isTokenValid = (secret, code) => {
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
generate2faActivationQrCode(appName) {
|
||||
async generate2faActivationQrCode(appName) {
|
||||
check(appName, String);
|
||||
const user = Meteor.user();
|
||||
const user = await Meteor.userAsync();
|
||||
|
||||
if (!user) {
|
||||
throw new Meteor.Error(
|
||||
@@ -59,7 +59,7 @@ Meteor.methods({
|
||||
});
|
||||
const svg = new QRCode(uri).svg();
|
||||
|
||||
Meteor.users.update(
|
||||
await Meteor.users.updateAsync(
|
||||
{ _id: user._id },
|
||||
{
|
||||
$set: {
|
||||
@@ -72,9 +72,9 @@ Meteor.methods({
|
||||
|
||||
return { svg, secret, uri };
|
||||
},
|
||||
enableUser2fa(code) {
|
||||
async enableUser2fa(code) {
|
||||
check(code, String);
|
||||
const user = Meteor.user();
|
||||
const user = await Meteor.userAsync();
|
||||
|
||||
if (!user) {
|
||||
throw new Meteor.Error(400, 'No user logged in.');
|
||||
@@ -94,7 +94,7 @@ Meteor.methods({
|
||||
Accounts._handleError('Invalid 2FA code', true, 'invalid-2fa-code');
|
||||
}
|
||||
|
||||
Meteor.users.update(
|
||||
await Meteor.users.updateAsync(
|
||||
{ _id: user._id },
|
||||
{
|
||||
$set: {
|
||||
@@ -106,14 +106,14 @@ Meteor.methods({
|
||||
}
|
||||
);
|
||||
},
|
||||
disableUser2fa() {
|
||||
async disableUser2fa() {
|
||||
const userId = Meteor.userId();
|
||||
|
||||
if (!userId) {
|
||||
throw new Meteor.Error(400, 'No user logged in.');
|
||||
}
|
||||
|
||||
Meteor.users.update(
|
||||
await Meteor.users.updateAsync(
|
||||
{ _id: userId },
|
||||
{
|
||||
$unset: {
|
||||
@@ -122,8 +122,8 @@ Meteor.methods({
|
||||
}
|
||||
);
|
||||
},
|
||||
has2faEnabled() {
|
||||
return Accounts._is2faEnabledForUser();
|
||||
async has2faEnabled() {
|
||||
return await Accounts._is2faEnabledForUser();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
Package.describe({
|
||||
version: '2.0.2',
|
||||
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");
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { Accounts } from 'meteor/accounts-base';
|
||||
import { Random } from 'meteor/random';
|
||||
|
||||
const findUserById = id => Meteor.users.findOne(id);
|
||||
const findUserById =
|
||||
async id => await Meteor.users.findOneAsync(id);
|
||||
|
||||
Tinytest.add('account - 2fa - has2faEnabled - server', test => {
|
||||
Tinytest.addAsync('account - 2fa - has2faEnabled - server', async test => {
|
||||
// Create users
|
||||
const userWithout2FA = Accounts.insertUserDoc(
|
||||
const userWithout2FA = await Accounts.insertUserDoc(
|
||||
{},
|
||||
{ emails: [{ address: `${Random.id()}@meteorapp.com`, verified: true }] }
|
||||
);
|
||||
const userWith2FA = Accounts.insertUserDoc(
|
||||
const userWith2FA = await Accounts.insertUserDoc(
|
||||
{},
|
||||
{
|
||||
emails: [{ address: `${Random.id()}@meteorapp.com`, verified: true }],
|
||||
@@ -19,10 +20,10 @@ Tinytest.add('account - 2fa - has2faEnabled - server', test => {
|
||||
}
|
||||
);
|
||||
|
||||
test.equal(Accounts._check2faEnabled(findUserById(userWithout2FA)), false);
|
||||
test.equal(Accounts._check2faEnabled(findUserById(userWith2FA)), true);
|
||||
test.equal(Accounts._check2faEnabled(await findUserById(userWithout2FA)), false);
|
||||
test.equal(Accounts._check2faEnabled(await findUserById(userWith2FA)), true);
|
||||
|
||||
// cleanup
|
||||
Accounts.users.remove(userWithout2FA);
|
||||
Accounts.users.remove(userWith2FA);
|
||||
await Accounts.users.removeAsync(userWithout2FA);
|
||||
await Accounts.users.removeAsync(userWith2FA);
|
||||
});
|
||||
|
||||
10
packages/accounts-base/accounts-base.d.ts
vendored
10
packages/accounts-base/accounts-base.d.ts
vendored
@@ -220,12 +220,6 @@ export namespace Accounts {
|
||||
|
||||
function setUsername(userId: string, newUsername: string): void;
|
||||
|
||||
function setPassword(
|
||||
userId: string,
|
||||
newPassword: string,
|
||||
options?: { logout?: boolean | undefined }
|
||||
): void;
|
||||
|
||||
function setPasswordAsync(
|
||||
userId: string,
|
||||
newPassword: string,
|
||||
@@ -365,10 +359,10 @@ export namespace Accounts {
|
||||
* properties `digest` and `algorithm` (in which case we bcrypt
|
||||
* `password.digest`).
|
||||
*/
|
||||
function _checkPassword(
|
||||
function _checkPasswordAsync(
|
||||
user: Meteor.User,
|
||||
password: Password
|
||||
): { userId: string; error?: any };
|
||||
): Promise<{ userId: string; error?: any }>
|
||||
}
|
||||
|
||||
export namespace Accounts {
|
||||
|
||||
@@ -133,18 +133,21 @@ export class AccountsClient extends AccountsCommon {
|
||||
*/
|
||||
logout(callback) {
|
||||
this._loggingOut.set(true);
|
||||
this.connection.apply('logout', [], {
|
||||
|
||||
this.connection.applyAsync('logout', [], {
|
||||
// TODO[FIBERS]: Look this { wait: true } later.
|
||||
wait: true
|
||||
}, (error, result) => {
|
||||
this._loggingOut.set(false);
|
||||
this._loginCallbacksCalled = false;
|
||||
if (error) {
|
||||
callback && callback(error);
|
||||
} else {
|
||||
})
|
||||
.then((result) => {
|
||||
this._loggingOut.set(false);
|
||||
this._loginCallbacksCalled = false;
|
||||
this.makeClientLoggedOut();
|
||||
callback && callback();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
this._loggingOut.set(false);
|
||||
callback && callback(e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,13 +379,24 @@ export class AccountsClient extends AccountsCommon {
|
||||
|
||||
// Make the client logged in. (The user data should already be loaded!)
|
||||
this.makeClientLoggedIn(result.id, result.token, result.tokenExpires);
|
||||
loginCallbacks({ loginDetails: result });
|
||||
|
||||
// use Tracker to make we sure have a user before calling the callbacks
|
||||
Tracker.autorun(async function (computation) {
|
||||
const user = await Tracker.withComputation(computation, () =>
|
||||
Meteor.userAsync(),
|
||||
);
|
||||
|
||||
if (user) {
|
||||
loginCallbacks({ loginDetails: result })
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
if (!options._suppressLoggingIn) {
|
||||
this._setLoggingIn(true);
|
||||
}
|
||||
this.connection.apply(
|
||||
this.connection.applyAsync(
|
||||
options.methodName,
|
||||
options.methodArguments,
|
||||
{ wait: true, onResultReceived: onResultReceived },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Accounts} from "meteor/accounts-base";
|
||||
import { AccountsClient } from './accounts_client';
|
||||
|
||||
const username = 'jsmith';
|
||||
const password = 'password';
|
||||
@@ -36,9 +37,9 @@ const createUserAndLogout = (test, done, nextTests) => {
|
||||
},
|
||||
},
|
||||
() => {
|
||||
Meteor.logout(() => {
|
||||
Meteor.logout(async () => {
|
||||
// Make sure we're logged out
|
||||
test.isFalse(Meteor.user());
|
||||
test.isFalse(await Meteor.userAsync());
|
||||
// Handle next tests
|
||||
nextTests(test, done);
|
||||
});
|
||||
@@ -47,13 +48,13 @@ const createUserAndLogout = (test, done, nextTests) => {
|
||||
};
|
||||
|
||||
const removeTestUser = done => {
|
||||
Meteor.call('removeAccountsTestUser', username, () => {
|
||||
Meteor.callAsync('removeAccountsTestUser', username).then(() => {
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
const forceEnableUser2fa = done => {
|
||||
Meteor.call('forceEnableUser2fa', { username }, secret2fa, (err, token) => {
|
||||
Meteor.callAsync('forceEnableUser2fa', { username }, secret2fa).then((token) => {
|
||||
done(token);
|
||||
});
|
||||
};
|
||||
@@ -245,13 +246,13 @@ Tinytest.addAsync(
|
||||
);
|
||||
|
||||
|
||||
Tinytest.addAsync(
|
||||
Tinytest.addAsync(
|
||||
'accounts-2fa - Meteor.loginWithPasswordAnd2faCode() fails with invalid code',
|
||||
(test, done) => {
|
||||
createUserAndLogout(test, done, () => {
|
||||
forceEnableUser2fa(() => {
|
||||
Meteor.loginWithPasswordAnd2faCode(username, password, 'ABC', e => {
|
||||
test.isFalse(Meteor.user());
|
||||
Meteor.loginWithPasswordAnd2faCode(username, password, 'ABC', async e => {
|
||||
test.isFalse(await Meteor.user());
|
||||
test.equal(e.reason, 'Invalid 2FA code');
|
||||
removeTestUser(done);
|
||||
});
|
||||
@@ -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()
|
||||
});
|
||||
@@ -19,6 +19,8 @@ const VALID_CONFIG_KEYS = [
|
||||
'loginTokenExpirationHours',
|
||||
'tokenSequenceLength',
|
||||
'clientStorage',
|
||||
'ddpUrl',
|
||||
'connection',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -34,9 +36,16 @@ const VALID_CONFIG_KEYS = [
|
||||
*/
|
||||
export class AccountsCommon {
|
||||
constructor(options) {
|
||||
// Validate config options keys
|
||||
for (const key of Object.keys(options)) {
|
||||
if (!VALID_CONFIG_KEYS.includes(key)) {
|
||||
console.error(`Accounts.config: Invalid key: ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Currently this is read directly by packages like accounts-password
|
||||
// and accounts-ui-unstyled.
|
||||
this._options = {};
|
||||
this._options = options || {};
|
||||
|
||||
// Note that setting this.connection = null causes this.users to be a
|
||||
// LocalCollection, which is not what we want.
|
||||
@@ -149,15 +158,27 @@ export class AccountsCommon {
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get the current user record, or `null` if no user is logged in. A reactive data source.
|
||||
* @summary Get the current user record, or `null` if no user is logged in. A reactive data source. In the server this fuction returns a promise.
|
||||
* @locus Anywhere
|
||||
* @param {Object} [options]
|
||||
* @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.
|
||||
*/
|
||||
user(options) {
|
||||
const userId = this.userId();
|
||||
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
|
||||
? self.users.findOne(...args)
|
||||
: self.users.findOneAsync(...args);
|
||||
return userId
|
||||
? this.users.findOne(userId, this._addDefaultFieldSelector(options))
|
||||
? findOne(userId, this._addDefaultFieldSelector(options))
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -201,7 +222,7 @@ export class AccountsCommon {
|
||||
// A collection name or a Mongo.Collection object to hold the users.
|
||||
// - passwordResetTokenExpirationInDays {Number}
|
||||
// Number of days since password reset token creation until the
|
||||
// token cannt be used any longer (password reset token expires).
|
||||
// token can't be used any longer (password reset token expires).
|
||||
// - ambiguousErrorMessages {Boolean}
|
||||
// Return ambiguous error messages from login failures to prevent
|
||||
// user enumeration.
|
||||
@@ -223,7 +244,7 @@ export class AccountsCommon {
|
||||
* @param {Number} options.passwordResetTokenExpiration The number of milliseconds from when a link to reset password is sent until token expires and user can't reset password with the link anymore. If `passwordResetTokenExpirationInDays` is set, it takes precedent.
|
||||
* @param {Number} options.passwordEnrollTokenExpirationInDays The number of days from when a link to set initial password is sent until token expires and user can't set password with the link anymore. Defaults to 30.
|
||||
* @param {Number} options.passwordEnrollTokenExpiration The number of milliseconds from when a link to set initial password is sent until token expires and user can't set password with the link anymore. If `passwordEnrollTokenExpirationInDays` is set, it takes precedent.
|
||||
* @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to false.
|
||||
* @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to `false`, but in production environments it is recommended it defaults to `true`.
|
||||
* @param {Number} options.bcryptRounds Allows override of number of bcrypt rounds (aka work factor) used to store passwords. The default is 10.
|
||||
* @param {MongoFieldSpecifier} options.defaultFieldSelector To exclude by default large custom fields from `Meteor.user()` and `Meteor.findUserBy...()` functions when called without a field selector, and all `onLogin`, `onLoginFailure` and `onLogout` callbacks. Example: `Accounts.config({ defaultFieldSelector: { myBigArray: 0 }})`. Beware when using this. If, for instance, you do not include `email` when excluding the fields, you can have problems with functions like `forgotPassword` that will break because they won't have the required data available. It's recommend that you always keep the fields `_id`, `username`, and `email`.
|
||||
* @param {String|Mongo.Collection} options.collection A collection name or a Mongo.Collection object to hold the users.
|
||||
@@ -270,15 +291,14 @@ export class AccountsCommon {
|
||||
}
|
||||
|
||||
// Validate config options keys
|
||||
Object.keys(options).forEach(key => {
|
||||
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}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// set values in Accounts._options
|
||||
VALID_CONFIG_KEYS.forEach(key => {
|
||||
for (const key of VALID_CONFIG_KEYS) {
|
||||
if (key in options) {
|
||||
if (key in this._options) {
|
||||
if (key !== 'collection' && (Meteor.isTest && key !== 'clientStorage')) {
|
||||
@@ -287,7 +307,7 @@ export class AccountsCommon {
|
||||
}
|
||||
this._options[key] = options[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.collection && options.collection !== this.users._name && options.collection !== this.users) {
|
||||
this.users = this._initializeCollection(options);
|
||||
@@ -419,14 +439,14 @@ export class AccountsCommon {
|
||||
|
||||
/**
|
||||
* @summary Get the current user id, or `null` if no user is logged in. A reactive data source.
|
||||
* @locus Anywhere but publish functions
|
||||
* @locus Anywhere
|
||||
* @importFromPackage meteor
|
||||
*/
|
||||
Meteor.userId = () => Accounts.userId();
|
||||
|
||||
/**
|
||||
* @summary Get the current user record, or `null` if no user is logged in. A reactive data source.
|
||||
* @locus Anywhere but publish functions
|
||||
* @locus Anywhere
|
||||
* @importFromPackage meteor
|
||||
* @param {Object} [options]
|
||||
* @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.
|
||||
@@ -435,7 +455,7 @@ Meteor.user = options => Accounts.user(options);
|
||||
|
||||
/**
|
||||
* @summary Get the current user record, or `null` if no user is logged in. A reactive data source.
|
||||
* @locus Anywhere but publish functions
|
||||
* @locus Anywhere
|
||||
* @importFromPackage meteor
|
||||
* @param {Object} [options]
|
||||
* @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
if (Meteor.isServer) {
|
||||
Meteor.methods({
|
||||
getConnectionUserId: function() {
|
||||
getConnectionUserId: function () {
|
||||
return this.userId;
|
||||
}
|
||||
},
|
||||
logCurrentUserId: function () {
|
||||
return this.userId;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,4 +131,38 @@ if (Meteor.isClient) {
|
||||
});
|
||||
}
|
||||
);
|
||||
// Make sure this is issue is fixed: https://forums.meteor.com/t/back-from-offline-method-does-not-apply-on-server-side/61619
|
||||
// PR #13221
|
||||
Tinytest.addAsync(
|
||||
"accounts - user is in the server as soon as we reconnect",
|
||||
(test, done) => {
|
||||
loginAsUser1(async (err) => {
|
||||
test.isUndefined(err, "Unexpected error logging in as user1");
|
||||
test.isTrue(Meteor.userId(), "User should be logged in");
|
||||
|
||||
let userId = await Meteor.callAsync("logCurrentUserId");
|
||||
test.isTrue(
|
||||
userId,
|
||||
"userId exists in the server while connecting is up"
|
||||
);
|
||||
// 1. Disconnect client and server
|
||||
Meteor.disconnect();
|
||||
test.isFalse(Meteor.status().connected);
|
||||
|
||||
// 2. Invoke a method call after the disconnection
|
||||
Meteor.callAsync("logCurrentUserId")
|
||||
.then((id) => {
|
||||
// 4. the server should still return an id after connection
|
||||
test.isTrue(Meteor.status().connected);
|
||||
test.isTrue(id, 'userId exists in the server after reconnect');
|
||||
})
|
||||
.finally(done);
|
||||
|
||||
setTimeout(() => {
|
||||
// 3. reconnect the client and server after some time
|
||||
Meteor.reconnect();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import crypto from 'crypto';
|
||||
import { Meteor } from 'meteor/meteor'
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import {
|
||||
AccountsCommon,
|
||||
EXPIRE_TOKENS_INTERVAL_MS,
|
||||
@@ -14,6 +14,7 @@ const NonEmptyString = Match.Where(x => {
|
||||
return x.length > 0;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @summary Constructor for the `Accounts` namespace on the server.
|
||||
* @locus Server
|
||||
@@ -71,8 +72,6 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
// list of all registered handlers.
|
||||
this._loginHandlers = [];
|
||||
|
||||
setupUsersCollection(this.users);
|
||||
setupDefaultLoginHandlers(this);
|
||||
setExpireTokensInterval(this);
|
||||
|
||||
@@ -126,6 +125,10 @@ export class AccountsServer extends AccountsCommon {
|
||||
return currentInvocation.userId;
|
||||
}
|
||||
|
||||
async init() {
|
||||
await setupUsersCollection(this.users);
|
||||
}
|
||||
|
||||
///
|
||||
/// LOGIN HOOKS
|
||||
///
|
||||
@@ -178,7 +181,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
}
|
||||
|
||||
this._onCreateLoginTokenHook = func;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Customize new user creation.
|
||||
@@ -219,11 +222,11 @@ export class AccountsServer extends AccountsCommon {
|
||||
this._additionalFindUserOnExternalLogin = func;
|
||||
}
|
||||
|
||||
_validateLogin(connection, attempt) {
|
||||
this._validateLoginHook.forEach(callback => {
|
||||
async _validateLogin(connection, attempt) {
|
||||
await this._validateLoginHook.forEachAsync(async (callback) => {
|
||||
let ret;
|
||||
try {
|
||||
ret = callback(cloneAttemptWithConnection(connection, attempt));
|
||||
ret = await callback(cloneAttemptWithConnection(connection, attempt));
|
||||
}
|
||||
catch (e) {
|
||||
attempt.allowed = false;
|
||||
@@ -245,25 +248,25 @@ export class AccountsServer extends AccountsCommon {
|
||||
});
|
||||
};
|
||||
|
||||
_successfulLogin(connection, attempt) {
|
||||
this._onLoginHook.each(callback => {
|
||||
callback(cloneAttemptWithConnection(connection, attempt));
|
||||
async _successfulLogin(connection, attempt) {
|
||||
await this._onLoginHook.forEachAsync(async (callback) => {
|
||||
await callback(cloneAttemptWithConnection(connection, attempt));
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
_failedLogin(connection, attempt) {
|
||||
this._onLoginFailureHook.each(callback => {
|
||||
callback(cloneAttemptWithConnection(connection, attempt));
|
||||
async _failedLogin(connection, attempt) {
|
||||
await this._onLoginFailureHook.forEachAsync(async (callback) => {
|
||||
await callback(cloneAttemptWithConnection(connection, attempt));
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
_successfulLogout(connection, userId) {
|
||||
async _successfulLogout(connection, userId) {
|
||||
// don't fetch the user object unless there are some callbacks registered
|
||||
let user;
|
||||
this._onLogoutHook.each(callback => {
|
||||
if (!user && userId) user = this.users.findOne(userId, {fields: this._options.defaultFieldSelector});
|
||||
await this._onLogoutHook.forEachAsync(async callback => {
|
||||
if (!user && userId) user = await this.users.findOneAsync(userId, { fields: this._options.defaultFieldSelector });
|
||||
callback({ user, connection });
|
||||
return true;
|
||||
});
|
||||
@@ -294,12 +297,12 @@ export class AccountsServer extends AccountsCommon {
|
||||
return {$and: [{$or: orClause}, caseInsensitiveClause]};
|
||||
}
|
||||
|
||||
_findUserByQuery = (query, options) => {
|
||||
_findUserByQuery = async (query, options) => {
|
||||
let user = null;
|
||||
|
||||
if (query.id) {
|
||||
// default field selector is added within getUserById()
|
||||
user = Meteor.users.findOne(query.id, this._addDefaultFieldSelector(options));
|
||||
user = await Meteor.users.findOneAsync(query.id, this._addDefaultFieldSelector(options));
|
||||
} else {
|
||||
options = this._addDefaultFieldSelector(options);
|
||||
let fieldName;
|
||||
@@ -315,11 +318,11 @@ export class AccountsServer extends AccountsCommon {
|
||||
}
|
||||
let selector = {};
|
||||
selector[fieldName] = fieldValue;
|
||||
user = Meteor.users.findOne(selector, options);
|
||||
user = await Meteor.users.findOneAsync(selector, options);
|
||||
// If user is not found, try a case insensitive lookup
|
||||
if (!user) {
|
||||
selector = this._selectorForFastCaseInsensitiveLookup(fieldName, fieldValue);
|
||||
const candidateUsers = Meteor.users.find(selector, { ...options, limit: 2 }).fetch();
|
||||
const candidateUsers = await Meteor.users.find(selector, { ...options, limit: 2 }).fetchAsync();
|
||||
// No match if multiple candidates are found
|
||||
if (candidateUsers.length === 1) {
|
||||
user = candidateUsers[0];
|
||||
@@ -399,10 +402,10 @@ export class AccountsServer extends AccountsCommon {
|
||||
// indicates that the login token has already been inserted into the
|
||||
// database and doesn't need to be inserted again. (It's used by the
|
||||
// "resume" login handler).
|
||||
_loginUser(methodInvocation, userId, stampedLoginToken) {
|
||||
async _loginUser(methodInvocation, userId, stampedLoginToken) {
|
||||
if (! stampedLoginToken) {
|
||||
stampedLoginToken = this._generateStampedLoginToken();
|
||||
this._insertLoginToken(userId, stampedLoginToken);
|
||||
await this._insertLoginToken(userId, stampedLoginToken);
|
||||
}
|
||||
|
||||
// This order (and the avoidance of yields) is important to make
|
||||
@@ -419,7 +422,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
)
|
||||
);
|
||||
|
||||
methodInvocation.setUserId(userId);
|
||||
await methodInvocation.setUserId(userId);
|
||||
|
||||
return {
|
||||
id: userId,
|
||||
@@ -452,7 +455,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
let user;
|
||||
if (result.userId)
|
||||
user = this.users.findOne(result.userId, {fields: this._options.defaultFieldSelector});
|
||||
user = await this.users.findOneAsync(result.userId, {fields: this._options.defaultFieldSelector});
|
||||
|
||||
const attempt = {
|
||||
type: result.type || "unknown",
|
||||
@@ -470,23 +473,24 @@ export class AccountsServer extends AccountsCommon {
|
||||
// _validateLogin may mutate `attempt` by adding an error and changing allowed
|
||||
// to false, but that's the only change it can make (and the user's callbacks
|
||||
// only get a clone of `attempt`).
|
||||
this._validateLogin(methodInvocation.connection, attempt);
|
||||
await this._validateLogin(methodInvocation.connection, attempt);
|
||||
|
||||
if (attempt.allowed) {
|
||||
const o = await this._loginUser(
|
||||
methodInvocation,
|
||||
result.userId,
|
||||
result.stampedLoginToken
|
||||
)
|
||||
const ret = {
|
||||
...this._loginUser(
|
||||
methodInvocation,
|
||||
result.userId,
|
||||
result.stampedLoginToken
|
||||
),
|
||||
...o,
|
||||
...result.options
|
||||
};
|
||||
ret.type = attempt.type;
|
||||
this._successfulLogin(methodInvocation.connection, attempt);
|
||||
await this._successfulLogin(methodInvocation.connection, attempt);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
this._failedLogin(methodInvocation.connection, attempt);
|
||||
await this._failedLogin(methodInvocation.connection, attempt);
|
||||
throw attempt.error;
|
||||
}
|
||||
};
|
||||
@@ -518,7 +522,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// is no corresponding method for a successful login; methods that can
|
||||
// succeed at logging a user in should always be actual login methods
|
||||
// (using either Accounts._loginMethod or Accounts.registerLoginHandler).
|
||||
_reportLoginFailure(
|
||||
async _reportLoginFailure(
|
||||
methodInvocation,
|
||||
methodName,
|
||||
methodArgs,
|
||||
@@ -533,11 +537,11 @@ export class AccountsServer extends AccountsCommon {
|
||||
};
|
||||
|
||||
if (result.userId) {
|
||||
attempt.user = this.users.findOne(result.userId, {fields: this._options.defaultFieldSelector});
|
||||
attempt.user = this.users.findOneAsync(result.userId, {fields: this._options.defaultFieldSelector});
|
||||
}
|
||||
|
||||
this._validateLogin(methodInvocation.connection, attempt);
|
||||
this._failedLogin(methodInvocation.connection, attempt);
|
||||
await this._validateLogin(methodInvocation.connection, attempt);
|
||||
await this._failedLogin(methodInvocation.connection, attempt);
|
||||
|
||||
// _validateLogin may mutate attempt to set a new error message. Return
|
||||
// the modified version.
|
||||
@@ -615,8 +619,8 @@ export class AccountsServer extends AccountsCommon {
|
||||
// Any connections associated with old-style unhashed tokens will be
|
||||
// in the process of becoming associated with hashed tokens and then
|
||||
// they'll get closed.
|
||||
destroyToken(userId, loginToken) {
|
||||
this.users.update(userId, {
|
||||
async destroyToken(userId, loginToken) {
|
||||
await this.users.updateAsync(userId, {
|
||||
$pull: {
|
||||
"services.resume.loginTokens": {
|
||||
$or: [
|
||||
@@ -653,14 +657,14 @@ export class AccountsServer extends AccountsCommon {
|
||||
return await accounts._attemptLogin(this, "login", arguments, result);
|
||||
};
|
||||
|
||||
methods.logout = function () {
|
||||
methods.logout = async function () {
|
||||
const token = accounts._getLoginToken(this.connection.id);
|
||||
accounts._setLoginToken(this.userId, this.connection, null);
|
||||
if (token && this.userId) {
|
||||
accounts.destroyToken(this.userId, token);
|
||||
await accounts.destroyToken(this.userId, token);
|
||||
}
|
||||
accounts._successfulLogout(this.connection, this.userId);
|
||||
this.setUserId(null);
|
||||
await accounts._successfulLogout(this.connection, this.userId);
|
||||
await this.setUserId(null);
|
||||
};
|
||||
|
||||
// Generates a new login token with the same expiration as the
|
||||
@@ -671,8 +675,8 @@ export class AccountsServer extends AccountsCommon {
|
||||
// @returns Object
|
||||
// If successful, returns { token: <new token>, id: <user id>,
|
||||
// tokenExpires: <expiration date> }.
|
||||
methods.getNewToken = function () {
|
||||
const user = accounts.users.findOne(this.userId, {
|
||||
methods.getNewToken = async function () {
|
||||
const user = await accounts.users.findOneAsync(this.userId, {
|
||||
fields: { "services.resume.loginTokens": 1 }
|
||||
});
|
||||
if (! this.userId || ! user) {
|
||||
@@ -691,19 +695,19 @@ export class AccountsServer extends AccountsCommon {
|
||||
}
|
||||
const newStampedToken = accounts._generateStampedLoginToken();
|
||||
newStampedToken.when = currentStampedToken.when;
|
||||
accounts._insertLoginToken(this.userId, newStampedToken);
|
||||
return accounts._loginUser(this, this.userId, newStampedToken);
|
||||
await accounts._insertLoginToken(this.userId, newStampedToken);
|
||||
return await accounts._loginUser(this, this.userId, newStampedToken);
|
||||
};
|
||||
|
||||
// Removes all tokens except the token associated with the current
|
||||
// connection. Throws an error if the connection is not logged
|
||||
// in. Returns nothing on success.
|
||||
methods.removeOtherTokens = function () {
|
||||
methods.removeOtherTokens = async function () {
|
||||
if (! this.userId) {
|
||||
throw new Meteor.Error("You are not logged in.");
|
||||
}
|
||||
const currentToken = accounts._getLoginToken(this.connection.id);
|
||||
accounts.users.update(this.userId, {
|
||||
await accounts.users.updateAsync(this.userId, {
|
||||
$pull: {
|
||||
"services.resume.loginTokens": { hashedToken: { $ne: currentToken } }
|
||||
}
|
||||
@@ -712,7 +716,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
// Allow a one-time configuration for a login service. Modifications
|
||||
// to this collection are also allowed in insecure mode.
|
||||
methods.configureLoginService = (options) => {
|
||||
methods.configureLoginService = async (options) => {
|
||||
check(options, Match.ObjectIncluding({service: String}));
|
||||
// Don't let random users configure a service we haven't added yet (so
|
||||
// that when we do later add it, it's set up with their configuration
|
||||
@@ -727,7 +731,8 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
if (Package['service-configuration']) {
|
||||
const { ServiceConfiguration } = Package['service-configuration'];
|
||||
if (ServiceConfiguration.configurations.findOne({service: options.service}))
|
||||
const service = await ServiceConfiguration.configurations.findOneAsync({service: options.service})
|
||||
if (service)
|
||||
throw new Meteor.Error(403, `Service ${options.service} already configured`);
|
||||
|
||||
if (Package["oauth-encryption"]) {
|
||||
@@ -736,7 +741,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
options.secret = OAuthEncryption.seal(options.secret);
|
||||
}
|
||||
|
||||
ServiceConfiguration.configurations.insert(options);
|
||||
await ServiceConfiguration.configurations.insertAsync(options);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -897,10 +902,10 @@ export class AccountsServer extends AccountsCommon {
|
||||
// Using $addToSet avoids getting an index error if another client
|
||||
// logging in simultaneously has already inserted the new hashed
|
||||
// token.
|
||||
_insertHashedLoginToken(userId, hashedToken, query) {
|
||||
async _insertHashedLoginToken(userId, hashedToken, query) {
|
||||
query = query ? { ...query } : {};
|
||||
query._id = userId;
|
||||
this.users.update(query, {
|
||||
await this.users.updateAsync(query, {
|
||||
$addToSet: {
|
||||
"services.resume.loginTokens": hashedToken
|
||||
}
|
||||
@@ -908,16 +913,22 @@ export class AccountsServer extends AccountsCommon {
|
||||
};
|
||||
|
||||
// Exported for tests.
|
||||
_insertLoginToken(userId, stampedToken, query) {
|
||||
this._insertHashedLoginToken(
|
||||
async _insertLoginToken(userId, stampedToken, query) {
|
||||
await this._insertHashedLoginToken(
|
||||
userId,
|
||||
this._hashStampedToken(stampedToken),
|
||||
query
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param userId
|
||||
* @private
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
_clearAllLoginTokens(userId) {
|
||||
this.users.update(userId, {
|
||||
this.users.updateAsync(userId, {
|
||||
$set: {
|
||||
'services.resume.loginTokens': []
|
||||
}
|
||||
@@ -973,7 +984,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// already -- in this case we just clean up the observe that we started).
|
||||
const myObserveNumber = ++this._nextUserObserveNumber;
|
||||
this._userObservesForConnections[connection.id] = myObserveNumber;
|
||||
Meteor.defer(() => {
|
||||
Meteor.defer(async () => {
|
||||
// If something else happened on this connection in the meantime (it got
|
||||
// closed, or another call to _setLoginToken happened), just do
|
||||
// nothing. We don't need to start an observe for an old connection or old
|
||||
@@ -986,7 +997,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// Because we upgrade unhashed login tokens to hashed tokens at
|
||||
// login time, sessions will only be logged in with a hashed
|
||||
// token. Thus we only need to observe hashed tokens here.
|
||||
const observe = this.users.find({
|
||||
const observe = await this.users.find({
|
||||
_id: userId,
|
||||
'services.resume.loginTokens.hashedToken': newToken
|
||||
}, { fields: { _id: 1 } }).observeChanges({
|
||||
@@ -1045,7 +1056,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// tests. oldestValidDate is simulate expiring tokens without waiting
|
||||
// for them to actually expire. userId is used by tests to only expire
|
||||
// tokens for the test user.
|
||||
_expirePasswordResetTokens(oldestValidDate, userId) {
|
||||
async _expirePasswordResetTokens(oldestValidDate, userId) {
|
||||
const tokenLifetimeMs = this._getPasswordResetTokenLifetimeMs();
|
||||
|
||||
// when calling from a test with extra arguments, you must specify both!
|
||||
@@ -1063,7 +1074,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
]
|
||||
};
|
||||
|
||||
expirePasswordToken(this, oldestValidDate, tokenFilter, userId);
|
||||
await expirePasswordToken(this, oldestValidDate, tokenFilter, userId);
|
||||
}
|
||||
|
||||
// Deletes expired password enroll tokens from the database.
|
||||
@@ -1072,7 +1083,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// tests. oldestValidDate is simulate expiring tokens without waiting
|
||||
// for them to actually expire. userId is used by tests to only expire
|
||||
// tokens for the test user.
|
||||
_expirePasswordEnrollTokens(oldestValidDate, userId) {
|
||||
async _expirePasswordEnrollTokens(oldestValidDate, userId) {
|
||||
const tokenLifetimeMs = this._getPasswordEnrollTokenLifetimeMs();
|
||||
|
||||
// when calling from a test with extra arguments, you must specify both!
|
||||
@@ -1087,7 +1098,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
"services.password.enroll.reason": "enroll"
|
||||
};
|
||||
|
||||
expirePasswordToken(this, oldestValidDate, tokenFilter, userId);
|
||||
await expirePasswordToken(this, oldestValidDate, tokenFilter, userId);
|
||||
}
|
||||
|
||||
// Deletes expired tokens from the database and closes all open connections
|
||||
@@ -1097,7 +1108,14 @@ export class AccountsServer extends AccountsCommon {
|
||||
// tests. oldestValidDate is simulate expiring tokens without waiting
|
||||
// for them to actually expire. userId is used by tests to only expire
|
||||
// tokens for the test user.
|
||||
_expireTokens(oldestValidDate, userId) {
|
||||
/**
|
||||
*
|
||||
* @param oldestValidDate
|
||||
* @param userId
|
||||
* @private
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async _expireTokens(oldestValidDate, userId) {
|
||||
const tokenLifetimeMs = this._getTokenLifetimeMs();
|
||||
|
||||
// when calling from a test with extra arguments, you must specify both!
|
||||
@@ -1112,7 +1130,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
// Backwards compatible with older versions of meteor that stored login token
|
||||
// timestamps as numbers.
|
||||
this.users.update({ ...userFilter,
|
||||
await this.users.updateAsync({ ...userFilter,
|
||||
$or: [
|
||||
{ "services.resume.loginTokens.when": { $lt: oldestValidDate } },
|
||||
{ "services.resume.loginTokens.when": { $lt: +oldestValidDate } }
|
||||
@@ -1149,7 +1167,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
};
|
||||
|
||||
// Called by accounts-password
|
||||
insertUserDoc(options, user) {
|
||||
async insertUserDoc(options, user) {
|
||||
// - clone user document, to protect from modification
|
||||
// - add createdAt timestamp
|
||||
// - prepare an _id, so that you can modify other collections (eg
|
||||
@@ -1176,7 +1194,8 @@ export class AccountsServer extends AccountsCommon {
|
||||
|
||||
let fullUser;
|
||||
if (this._onCreateUserHook) {
|
||||
fullUser = this._onCreateUserHook(options, user);
|
||||
// Allows _onCreateUserHook to be a promise returning func
|
||||
fullUser = await this._onCreateUserHook(options, user);
|
||||
|
||||
// This is *not* part of the API. We need this because we can't isolate
|
||||
// the global server environment between tests, meaning we can't test
|
||||
@@ -1187,14 +1206,14 @@ export class AccountsServer extends AccountsCommon {
|
||||
fullUser = defaultCreateUserHook(options, user);
|
||||
}
|
||||
|
||||
this._validateNewUserHooks.forEach(hook => {
|
||||
if (! hook(fullUser))
|
||||
for await (const hook of this._validateNewUserHooks) {
|
||||
if (! await hook(fullUser))
|
||||
throw new Meteor.Error(403, "User validation failed");
|
||||
});
|
||||
}
|
||||
|
||||
let userId;
|
||||
try {
|
||||
userId = this.users.insert(fullUser);
|
||||
userId = await this.users.insertAsync(fullUser);
|
||||
} catch (e) {
|
||||
// XXX string parsing sucks, maybe
|
||||
// https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day
|
||||
@@ -1224,9 +1243,9 @@ export class AccountsServer extends AccountsCommon {
|
||||
/// CLEAN UP FOR `logoutOtherClients`
|
||||
///
|
||||
|
||||
_deleteSavedTokensForUser(userId, tokensToDelete) {
|
||||
async _deleteSavedTokensForUser(userId, tokensToDelete) {
|
||||
if (tokensToDelete) {
|
||||
this.users.update(userId, {
|
||||
await this.users.updateAsync(userId, {
|
||||
$unset: {
|
||||
"services.resume.haveLoginTokensToDelete": 1,
|
||||
"services.resume.loginTokensToDelete": 1
|
||||
@@ -1245,16 +1264,24 @@ export class AccountsServer extends AccountsCommon {
|
||||
// shouldn't happen very often. We shouldn't put a delay here because
|
||||
// that would give a lot of power to an attacker with a stolen login
|
||||
// token and the ability to crash the server.
|
||||
Meteor.startup(() => {
|
||||
this.users.find({
|
||||
Meteor.startup(async () => {
|
||||
const users = await this.users.find({
|
||||
"services.resume.haveLoginTokensToDelete": true
|
||||
}, {fields: {
|
||||
}, {
|
||||
fields: {
|
||||
"services.resume.loginTokensToDelete": 1
|
||||
}}).forEach(user => {
|
||||
}
|
||||
})
|
||||
users.forEach(user => {
|
||||
this._deleteSavedTokensForUser(
|
||||
user._id,
|
||||
user.services.resume.loginTokensToDelete
|
||||
);
|
||||
)
|
||||
// We don't need to wait for this to complete.
|
||||
.then(_ => _)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1274,7 +1301,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// @returns {Object} Object with token and id keys, like the result
|
||||
// of the "login" method.
|
||||
//
|
||||
updateOrCreateUserFromExternalService(
|
||||
async updateOrCreateUserFromExternalService(
|
||||
serviceName,
|
||||
serviceData,
|
||||
options
|
||||
@@ -1309,17 +1336,15 @@ export class AccountsServer extends AccountsCommon {
|
||||
} else {
|
||||
selector[serviceIdKey] = serviceData.id;
|
||||
}
|
||||
|
||||
let user = this.users.findOne(selector, {fields: this._options.defaultFieldSelector});
|
||||
|
||||
let user = await this.users.findOneAsync(selector, {fields: this._options.defaultFieldSelector});
|
||||
// Check to see if the developer has a custom way to find the user outside
|
||||
// of the general selectors above.
|
||||
if (!user && this._additionalFindUserOnExternalLogin) {
|
||||
user = this._additionalFindUserOnExternalLogin({serviceName, serviceData, options})
|
||||
user = await this._additionalFindUserOnExternalLogin({serviceName, serviceData, options})
|
||||
}
|
||||
|
||||
// Before continuing, run user hook to see if we should continue
|
||||
if (this._beforeExternalLoginHook && !this._beforeExternalLoginHook(serviceName, serviceData, user)) {
|
||||
if (this._beforeExternalLoginHook && !(await this._beforeExternalLoginHook(serviceName, serviceData, user))) {
|
||||
throw new Meteor.Error(403, "Login forbidden");
|
||||
}
|
||||
|
||||
@@ -1331,11 +1356,11 @@ export class AccountsServer extends AccountsCommon {
|
||||
// needed.
|
||||
let opts = user ? {} : options;
|
||||
if (this._onExternalLoginHook) {
|
||||
opts = this._onExternalLoginHook(options, user);
|
||||
opts = await this._onExternalLoginHook(options, user);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
pinEncryptedFieldsToUser(serviceData, user._id);
|
||||
await pinEncryptedFieldsToUser(serviceData, user._id);
|
||||
|
||||
let setAttrs = {};
|
||||
Object.keys(serviceData).forEach(key =>
|
||||
@@ -1345,7 +1370,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
// XXX Maybe we should re-use the selector above and notice if the update
|
||||
// touches nothing?
|
||||
setAttrs = { ...setAttrs, ...opts };
|
||||
this.users.update(user._id, {
|
||||
await this.users.updateAsync(user._id, {
|
||||
$set: setAttrs
|
||||
});
|
||||
|
||||
@@ -1357,9 +1382,10 @@ export class AccountsServer extends AccountsCommon {
|
||||
// Create a new user with the service data.
|
||||
user = {services: {}};
|
||||
user.services[serviceName] = serviceData;
|
||||
const userId = await this.insertUserDoc(opts, user);
|
||||
return {
|
||||
type: serviceName,
|
||||
userId: this.insertUserDoc(opts, user)
|
||||
userId
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1405,21 +1431,21 @@ export class AccountsServer extends AccountsCommon {
|
||||
* @returns {Object} Options which can be passed to `Email.send`.
|
||||
* @importFromPackage accounts-base
|
||||
*/
|
||||
generateOptionsForEmail(email, user, url, reason, extra = {}){
|
||||
async generateOptionsForEmail(email, user, url, reason, extra = {}){
|
||||
const options = {
|
||||
to: email,
|
||||
from: this.emailTemplates[reason].from
|
||||
? this.emailTemplates[reason].from(user)
|
||||
? await this.emailTemplates[reason].from(user)
|
||||
: this.emailTemplates.from,
|
||||
subject: this.emailTemplates[reason].subject(user, url, extra),
|
||||
subject: await this.emailTemplates[reason].subject(user, url, extra),
|
||||
};
|
||||
|
||||
if (typeof this.emailTemplates[reason].text === 'function') {
|
||||
options.text = this.emailTemplates[reason].text(user, url, extra);
|
||||
options.text = await this.emailTemplates[reason].text(user, url, extra);
|
||||
}
|
||||
|
||||
if (typeof this.emailTemplates[reason].html === 'function') {
|
||||
options.html = this.emailTemplates[reason].html(user, url, extra);
|
||||
options.html = await this.emailTemplates[reason].html(user, url, extra);
|
||||
}
|
||||
|
||||
if (typeof this.emailTemplates.headers === 'object') {
|
||||
@@ -1429,7 +1455,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
return options;
|
||||
};
|
||||
|
||||
_checkForCaseInsensitiveDuplicates(
|
||||
async _checkForCaseInsensitiveDuplicates(
|
||||
fieldName,
|
||||
displayName,
|
||||
fieldValue,
|
||||
@@ -1443,7 +1469,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
);
|
||||
|
||||
if (fieldValue && !skipCheck) {
|
||||
const matchedUsers = Meteor.users
|
||||
const matchedUsers = await Meteor.users
|
||||
.find(
|
||||
this._selectorForFastCaseInsensitiveLookup(fieldName, fieldValue),
|
||||
{
|
||||
@@ -1452,7 +1478,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
limit: 2,
|
||||
}
|
||||
)
|
||||
.fetch();
|
||||
.fetchAsync();
|
||||
|
||||
if (
|
||||
matchedUsers.length > 0 &&
|
||||
@@ -1467,7 +1493,7 @@ export class AccountsServer extends AccountsCommon {
|
||||
}
|
||||
};
|
||||
|
||||
_createUserCheckingDuplicates({ user, email, username, options }) {
|
||||
async _createUserCheckingDuplicates({ user, email, username, options }) {
|
||||
const newUser = {
|
||||
...user,
|
||||
...(username ? { username } : {}),
|
||||
@@ -1475,27 +1501,28 @@ export class AccountsServer extends AccountsCommon {
|
||||
};
|
||||
|
||||
// Perform a case insensitive check before insert
|
||||
this._checkForCaseInsensitiveDuplicates('username', 'Username', username);
|
||||
this._checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);
|
||||
await this._checkForCaseInsensitiveDuplicates('username', 'Username', username);
|
||||
await this._checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);
|
||||
|
||||
const userId = this.insertUserDoc(options, newUser);
|
||||
const userId = await this.insertUserDoc(options, newUser);
|
||||
// Perform another check after insert, in case a matching user has been
|
||||
// inserted in the meantime
|
||||
try {
|
||||
this._checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);
|
||||
this._checkForCaseInsensitiveDuplicates('emails.address', 'Email', email, userId);
|
||||
await this._checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);
|
||||
await this._checkForCaseInsensitiveDuplicates('emails.address', 'Email', email, userId);
|
||||
} catch (ex) {
|
||||
// Remove inserted user if the check fails
|
||||
Meteor.users.remove(userId);
|
||||
await Meteor.users.removeAsync(userId);
|
||||
throw ex;
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
_handleError = (msg, throwError = true, errorCode = 403) => {
|
||||
const isErrorAmbiguous = this._options.ambiguousErrorMessages ?? Meteor.isProduction;
|
||||
const error = new Meteor.Error(
|
||||
errorCode,
|
||||
this._options.ambiguousErrorMessages
|
||||
isErrorAmbiguous
|
||||
? "Something went wrong. Please check your credentials."
|
||||
: msg
|
||||
);
|
||||
@@ -1549,7 +1576,7 @@ const setupDefaultLoginHandlers = accounts => {
|
||||
};
|
||||
|
||||
// Login handler for resume tokens.
|
||||
const defaultResumeLoginHandler = (accounts, options) => {
|
||||
const defaultResumeLoginHandler = async (accounts, options) => {
|
||||
if (!options.resume)
|
||||
return undefined;
|
||||
|
||||
@@ -1560,7 +1587,7 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
// First look for just the new-style hashed login token, to avoid
|
||||
// sending the unhashed token to the database in a query if we don't
|
||||
// need to.
|
||||
let user = accounts.users.findOne(
|
||||
let user = await accounts.users.findOneAsync(
|
||||
{"services.resume.loginTokens.hashedToken": hashedToken},
|
||||
{fields: {"services.resume.loginTokens.$": 1}});
|
||||
|
||||
@@ -1570,7 +1597,7 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
// the old-style token OR the new-style token, because another
|
||||
// client connection logging in simultaneously might have already
|
||||
// converted the token.
|
||||
user = accounts.users.findOne({
|
||||
user = await accounts.users.findOneAsync({
|
||||
$or: [
|
||||
{"services.resume.loginTokens.hashedToken": hashedToken},
|
||||
{"services.resume.loginTokens.token": options.resume}
|
||||
@@ -1589,13 +1616,13 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
// {hashedToken, when} for a hashed token or {token, when} for an
|
||||
// unhashed token.
|
||||
let oldUnhashedStyleToken;
|
||||
let token = user.services.resume.loginTokens.find(token =>
|
||||
let token = await user.services.resume.loginTokens.find(token =>
|
||||
token.hashedToken === hashedToken
|
||||
);
|
||||
if (token) {
|
||||
oldUnhashedStyleToken = false;
|
||||
} else {
|
||||
token = user.services.resume.loginTokens.find(token =>
|
||||
token = await user.services.resume.loginTokens.find(token =>
|
||||
token.token === options.resume
|
||||
);
|
||||
oldUnhashedStyleToken = true;
|
||||
@@ -1615,7 +1642,7 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
// after we read it). Using $addToSet avoids getting an index
|
||||
// error if another client logging in simultaneously has already
|
||||
// inserted the new hashed token.
|
||||
accounts.users.update(
|
||||
await accounts.users.updateAsync(
|
||||
{
|
||||
_id: user._id,
|
||||
"services.resume.loginTokens.token": options.resume
|
||||
@@ -1631,7 +1658,7 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
// Remove the old token *after* adding the new, since otherwise
|
||||
// another client trying to login between our removing the old and
|
||||
// adding the new wouldn't find a token to login with.
|
||||
accounts.users.update(user._id, {
|
||||
await accounts.users.updateAsync(user._id, {
|
||||
$pull: {
|
||||
"services.resume.loginTokens": { "token": options.resume }
|
||||
}
|
||||
@@ -1647,55 +1674,56 @@ const defaultResumeLoginHandler = (accounts, options) => {
|
||||
};
|
||||
};
|
||||
|
||||
const expirePasswordToken = (
|
||||
accounts,
|
||||
oldestValidDate,
|
||||
tokenFilter,
|
||||
userId
|
||||
) => {
|
||||
// boolean value used to determine if this method was called from enroll account workflow
|
||||
let isEnroll = false;
|
||||
const userFilter = userId ? {_id: userId} : {};
|
||||
// check if this method was called from enroll account workflow
|
||||
if(tokenFilter['services.password.enroll.reason']) {
|
||||
isEnroll = true;
|
||||
}
|
||||
let resetRangeOr = {
|
||||
$or: [
|
||||
{ "services.password.reset.when": { $lt: oldestValidDate } },
|
||||
{ "services.password.reset.when": { $lt: +oldestValidDate } }
|
||||
]
|
||||
};
|
||||
if(isEnroll) {
|
||||
resetRangeOr = {
|
||||
const expirePasswordToken =
|
||||
async (
|
||||
accounts,
|
||||
oldestValidDate,
|
||||
tokenFilter,
|
||||
userId
|
||||
) => {
|
||||
// boolean value used to determine if this method was called from enroll account workflow
|
||||
let isEnroll = false;
|
||||
const userFilter = userId ? { _id: userId } : {};
|
||||
// check if this method was called from enroll account workflow
|
||||
if (tokenFilter['services.password.enroll.reason']) {
|
||||
isEnroll = true;
|
||||
}
|
||||
let resetRangeOr = {
|
||||
$or: [
|
||||
{ "services.password.enroll.when": { $lt: oldestValidDate } },
|
||||
{ "services.password.enroll.when": { $lt: +oldestValidDate } }
|
||||
{ "services.password.reset.when": { $lt: oldestValidDate } },
|
||||
{ "services.password.reset.when": { $lt: +oldestValidDate } }
|
||||
]
|
||||
};
|
||||
}
|
||||
const expireFilter = { $and: [tokenFilter, resetRangeOr] };
|
||||
if(isEnroll) {
|
||||
accounts.users.update({...userFilter, ...expireFilter}, {
|
||||
$unset: {
|
||||
"services.password.enroll": ""
|
||||
}
|
||||
}, { multi: true });
|
||||
} else {
|
||||
accounts.users.update({...userFilter, ...expireFilter}, {
|
||||
$unset: {
|
||||
"services.password.reset": ""
|
||||
}
|
||||
}, { multi: true });
|
||||
}
|
||||
if (isEnroll) {
|
||||
resetRangeOr = {
|
||||
$or: [
|
||||
{ "services.password.enroll.when": { $lt: oldestValidDate } },
|
||||
{ "services.password.enroll.when": { $lt: +oldestValidDate } }
|
||||
]
|
||||
};
|
||||
}
|
||||
const expireFilter = { $and: [tokenFilter, resetRangeOr] };
|
||||
if (isEnroll) {
|
||||
await accounts.users.updateAsync({ ...userFilter, ...expireFilter }, {
|
||||
$unset: {
|
||||
"services.password.enroll": ""
|
||||
}
|
||||
}, { multi: true });
|
||||
} else {
|
||||
await accounts.users.updateAsync({ ...userFilter, ...expireFilter }, {
|
||||
$unset: {
|
||||
"services.password.reset": ""
|
||||
}
|
||||
}, { multi: true });
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
const setExpireTokensInterval = accounts => {
|
||||
accounts.expireTokenInterval = Meteor.setInterval(() => {
|
||||
accounts._expireTokens();
|
||||
accounts._expirePasswordResetTokens();
|
||||
accounts._expirePasswordEnrollTokens();
|
||||
accounts.expireTokenInterval = Meteor.setInterval(async () => {
|
||||
await accounts._expireTokens();
|
||||
await accounts._expirePasswordResetTokens();
|
||||
await accounts._expirePasswordEnrollTokens();
|
||||
}, EXPIRE_TOKENS_INTERVAL_MS);
|
||||
};
|
||||
|
||||
@@ -1756,7 +1784,7 @@ function defaultValidateNewUserHook(user) {
|
||||
}
|
||||
}
|
||||
|
||||
const setupUsersCollection = users => {
|
||||
const setupUsersCollection = async users => {
|
||||
///
|
||||
/// RESTRICTING WRITES TO USER OBJECTS
|
||||
///
|
||||
@@ -1778,25 +1806,40 @@ const setupUsersCollection = users => {
|
||||
|
||||
return true;
|
||||
},
|
||||
updateAsync: (userId, user, fields, modifier) => {
|
||||
// make sure it is our record
|
||||
if (user._id !== userId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// user can only modify the 'profile' field. sets to multiple
|
||||
// sub-keys (eg profile.foo and profile.bar) are merged into entry
|
||||
// in the fields list.
|
||||
if (fields.length !== 1 || fields[0] !== 'profile') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
fetch: ['_id'] // we only look at _id.
|
||||
});
|
||||
|
||||
/// DEFAULT INDEXES ON USERS
|
||||
users.createIndexAsync('username', { unique: true, sparse: true });
|
||||
users.createIndexAsync('emails.address', { unique: true, sparse: true });
|
||||
users.createIndexAsync('services.resume.loginTokens.hashedToken',
|
||||
await users.createIndexAsync('username', { unique: true, sparse: true });
|
||||
await users.createIndexAsync('emails.address', { unique: true, sparse: true });
|
||||
await users.createIndexAsync('services.resume.loginTokens.hashedToken',
|
||||
{ unique: true, sparse: true });
|
||||
users.createIndexAsync('services.resume.loginTokens.token',
|
||||
await users.createIndexAsync('services.resume.loginTokens.token',
|
||||
{ unique: true, sparse: true });
|
||||
// For taking care of logoutOtherClients calls that crashed before the
|
||||
// tokens were deleted.
|
||||
users.createIndexAsync('services.resume.haveLoginTokensToDelete',
|
||||
await users.createIndexAsync('services.resume.haveLoginTokensToDelete',
|
||||
{ sparse: true });
|
||||
// For expiring login tokens
|
||||
users.createIndexAsync("services.resume.loginTokens.when", { sparse: true });
|
||||
await users.createIndexAsync("services.resume.loginTokens.when", { sparse: true });
|
||||
// For expiring password tokens
|
||||
users.createIndexAsync('services.password.reset.when', { sparse: true });
|
||||
users.createIndexAsync('services.password.enroll.when', { sparse: true });
|
||||
await users.createIndexAsync('services.password.reset.when', { sparse: true });
|
||||
await users.createIndexAsync('services.password.enroll.when', { sparse: true });
|
||||
};
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1,25 @@
|
||||
const getTokenFromSecret = ({ selector, secret: secretParam }) => {
|
||||
const getTokenFromSecret = async ({ selector, secret: secretParam }) => {
|
||||
let secret = secretParam;
|
||||
|
||||
if (!secret) {
|
||||
const { services: { twoFactorAuthentication } = {} } =
|
||||
Meteor.users.findOne(selector) || {};
|
||||
await Meteor.users.findOneAsync(selector) || {};
|
||||
if (!twoFactorAuthentication) {
|
||||
throw new Meteor.Error(500, 'twoFactorAuthentication not set.');
|
||||
}
|
||||
secret = twoFactorAuthentication.secret;
|
||||
}
|
||||
const { token } = Accounts._generate2faToken(secret);
|
||||
const { token } = await Accounts._generate2faToken(secret);
|
||||
|
||||
return token;
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
removeAccountsTestUser(username) {
|
||||
Meteor.users.remove({ username });
|
||||
async removeAccountsTestUser(username) {
|
||||
await Meteor.users.removeAsync({ username });
|
||||
},
|
||||
forceEnableUser2fa(selector, secret) {
|
||||
Meteor.users.update(
|
||||
async forceEnableUser2fa(selector, secret) {
|
||||
await Meteor.users.updateAsync(
|
||||
selector,
|
||||
{
|
||||
$set: {
|
||||
@@ -30,7 +30,7 @@ Meteor.methods({
|
||||
},
|
||||
}
|
||||
);
|
||||
return getTokenFromSecret({ selector, secret });
|
||||
return await getTokenFromSecret({ selector, secret });
|
||||
},
|
||||
getTokenFromSecret,
|
||||
});
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
Package.describe({
|
||||
summary: 'A user account system',
|
||||
version: '2.2.11',
|
||||
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@2.7.1', '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");
|
||||
});
|
||||
|
||||
@@ -4,8 +4,9 @@ import { AccountsServer } from "./accounts_server.js";
|
||||
* @namespace Accounts
|
||||
* @summary The namespace for all server-side accounts-related methods.
|
||||
*/
|
||||
Accounts = new AccountsServer(Meteor.server, Meteor.settings.packages?.accounts || {});
|
||||
|
||||
Accounts = new AccountsServer(Meteor.server, { ...Meteor.settings.packages?.accounts, ...Meteor.settings.packages?.['accounts-base'] });
|
||||
// TODO[FIBERS]: I need TLA
|
||||
Accounts.init().then();
|
||||
// Users table. Don't use the normal autopublish, since we want to hide
|
||||
// some fields. Code to autopublish this is in accounts_server.js.
|
||||
// XXX Allow users to configure this collection name.
|
||||
@@ -15,7 +16,7 @@ Accounts = new AccountsServer(Meteor.server, Meteor.settings.packages?.accounts
|
||||
* @locus Anywhere
|
||||
* @type {Mongo.Collection}
|
||||
* @importFromPackage meteor
|
||||
*/
|
||||
*/
|
||||
Meteor.users = Accounts.users;
|
||||
|
||||
export {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Facebook accounts",
|
||||
version: "1.3.3",
|
||||
version: '1.3.4',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: 'Login service for Github accounts',
|
||||
version: '1.5.0',
|
||||
version: '1.5.1',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Google accounts",
|
||||
version: "1.4.0",
|
||||
version: '1.4.1',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user