mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'release-3.3.1' into modern-bundler-integration
This commit is contained in:
@@ -79,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:2024.09.11-android-34-node-20
|
||||
- image: meteor/circleci:2025.07.8-android-35-node-22
|
||||
resource_class: large
|
||||
environment:
|
||||
# This multiplier scales the waitSecs for selftests.
|
||||
@@ -756,7 +756,7 @@ jobs:
|
||||
Docs:
|
||||
docker:
|
||||
# This Node version should match that in the meteor/docs CircleCI config.
|
||||
- image: meteor/circleci:2024.09.11-android-34-node-20
|
||||
- image: meteor/circleci:2025.07.8-android-35-node-22
|
||||
resource_class: large
|
||||
environment:
|
||||
CHECKOUT_METEOR_DOCS: /home/circleci/test_docs
|
||||
|
||||
192
.github/labeler.yml
vendored
192
.github/labeler.yml
vendored
@@ -1,124 +1,178 @@
|
||||
Project:Accounts:Password:
|
||||
- packages/accounts-password/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: packages/accounts-password/**/*
|
||||
|
||||
Project:Accounts:UI:
|
||||
- packages/meteor-developer-config-ui/**/*
|
||||
- packages/github-config-ui/**/*
|
||||
- packages/google-config-ui/**/*
|
||||
- packages/twitter-config-ui/**/*
|
||||
- packages/facebook-config-ui/**/*
|
||||
- packages/accounts-ui/**/*
|
||||
- packages/accounts-ui-unstyled/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/meteor-developer-config-ui/**/*
|
||||
- packages/github-config-ui/**/*
|
||||
- packages/google-config-ui/**/*
|
||||
- packages/twitter-config-ui/**/*
|
||||
- packages/facebook-config-ui/**/*
|
||||
- packages/accounts-ui/**/*
|
||||
- packages/accounts-ui-unstyled/**/*
|
||||
|
||||
Project:CSS:
|
||||
- packages/non-core/less/**/*
|
||||
- packages/minifier-css/**/*
|
||||
- packages/standard-minifier-css/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/non-core/less/**/*
|
||||
- packages/minifier-css/**/*
|
||||
- packages/standard-minifier-css/**/*
|
||||
|
||||
Project:DDP:
|
||||
- packages/ddp-common/**/*
|
||||
- packages/ddp-rate-limiter/**/*
|
||||
- packages/ddp-server/**/*
|
||||
- packages/ddp-client/**/*
|
||||
- packages/ddp/**/*
|
||||
- packages/socket-stream-client/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/ddp-common/**/*
|
||||
- packages/ddp-rate-limiter/**/*
|
||||
- packages/ddp-server/**/*
|
||||
- packages/ddp-client/**/*
|
||||
- packages/ddp/**/*
|
||||
- packages/socket-stream-client/**/*
|
||||
|
||||
Project:EJSON:
|
||||
- packages/ejson/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: packages/ejson/**/*
|
||||
|
||||
Project:HMR:
|
||||
- packages/hot-code-push/**/*
|
||||
- packages/hot-module-replacement/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/hot-code-push/**/*
|
||||
- packages/hot-module-replacement/**/*
|
||||
|
||||
Project:Isobuild:Minifiers:
|
||||
- packages/minifier-css/**/*
|
||||
- packages/minifier-js/**/*
|
||||
- packages/standard-minifier-js/**/*
|
||||
- packages/standard-minifier-css/**/*
|
||||
- packages/standard-minifiers/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/minifier-css/**/*
|
||||
- packages/minifier-js/**/*
|
||||
- packages/standard-minifier-js/**/*
|
||||
- packages/standard-minifier-css/**/*
|
||||
- packages/standard-minifiers/**/*
|
||||
|
||||
Project:Isobuild:
|
||||
- tools/isobuild/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tools/isobuild/**/*
|
||||
|
||||
Project:JS Environment:Typescript:
|
||||
- packages/typescript/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/typescript/**/*
|
||||
|
||||
Project:JS Environment:
|
||||
- packages/babel-compiler/**/*
|
||||
- packages/babel-runtime/**/*
|
||||
- packages/ecmascript/**/*
|
||||
- packages/ecmascript-runtime/**/*
|
||||
- packages/ecmascript-runtime-client/**/*
|
||||
- packages/ecmascript-runtime-server/**/*
|
||||
- packages/es5-shim/**/*
|
||||
- packages/jshint/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/babel-compiler/**/*
|
||||
- packages/babel-runtime/**/*
|
||||
- packages/ecmascript/**/*
|
||||
- packages/ecmascript-runtime/**/*
|
||||
- packages/ecmascript-runtime-client/**/*
|
||||
- packages/ecmascript-runtime-server/**/*
|
||||
- packages/es5-shim/**/*
|
||||
- packages/jshint/**/*
|
||||
|
||||
Project:Livequery:
|
||||
- packages/livedata/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/livedata/**/*
|
||||
|
||||
Project:Minimongo:
|
||||
- packages/minimongo
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/minimongo
|
||||
|
||||
Project:Mobile:
|
||||
- tools/cordova/**/*
|
||||
- packages/launch-screen/**/*
|
||||
- packages/mobile-experience/**/*
|
||||
- packages/mobile-status-bar/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tools/cordova/**/*
|
||||
- packages/launch-screen/**/*
|
||||
- packages/mobile-experience/**/*
|
||||
- packages/mobile-status-bar/**/*
|
||||
|
||||
Project:Mongo Driver:
|
||||
- packages/mongo/**/*
|
||||
- packages/mongo-dev-server/**/*
|
||||
- packages/mongo-id/**/*
|
||||
- packages/mongo-livedata/**/*
|
||||
- packages/disable-oplog/**/*
|
||||
- packages/non-core/mongo-decimal/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/mongo/**/*
|
||||
- packages/mongo-dev-server/**/*
|
||||
- packages/mongo-id/**/*
|
||||
- packages/mongo-livedata/**/*
|
||||
- packages/disable-oplog/**/*
|
||||
- packages/non-core/mongo-decimal/**/*
|
||||
|
||||
Project:NPM:
|
||||
- npm-packages/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- npm-packages/**/*
|
||||
|
||||
Project:Release Process:
|
||||
- scripts/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- scripts/**/*
|
||||
|
||||
Project:Tool:
|
||||
- tools/**/*
|
||||
- packages/meteor-tool/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tools/**/*
|
||||
- packages/meteor-tool/**/*
|
||||
|
||||
Project:Tool:Shell:
|
||||
- tools/console/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tools/console/**/*
|
||||
|
||||
Project:Utilities:Email:
|
||||
- packages/email/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/email/**/*
|
||||
|
||||
Project:Utilities:HTTP:
|
||||
- packages/deprecated/http/**/*
|
||||
- packages/fetch/**/*
|
||||
- packages/url/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/deprecated/http/**/*
|
||||
- packages/fetch/**/*
|
||||
- packages/url/**/*
|
||||
|
||||
Project:Webapp:
|
||||
- packages/webapp/**/*
|
||||
- packages/webapp-hashing/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/webapp/**/*
|
||||
- packages/webapp-hashing/**/*
|
||||
|
||||
Project:Windows:
|
||||
- scripts/windows/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- scripts/windows/**/*
|
||||
|
||||
Project:Webapp:Browser Policy:
|
||||
- packages/browser-policy/**/*
|
||||
- packages/browser-policy-common/**/*
|
||||
- packages/browser-policy-content/**/*
|
||||
- packages/browser-policy-framing/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/browser-policy/**/*
|
||||
- packages/browser-policy-common/**/*
|
||||
- packages/browser-policy-content/**/*
|
||||
- packages/browser-policy-framing/**/*
|
||||
|
||||
Project:Examples:
|
||||
- tools/cli/example-repositories.js
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tools/cli/example-repositories.js
|
||||
|
||||
Project:Dynamic Import:
|
||||
- packages/dynamic-import/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/dynamic-import/**/*
|
||||
|
||||
Project:Docs:
|
||||
- docs/**/*
|
||||
- v3-docs/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- docs/**/*
|
||||
- v3-docs/**/*
|
||||
|
||||
Project:Guide:
|
||||
- guide/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- guide/**/*
|
||||
|
||||
github_actions:
|
||||
- ./github/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ./github/**/*
|
||||
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -17,6 +17,6 @@ jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
@@ -4,7 +4,7 @@ dist: jammy
|
||||
sudo: required
|
||||
services: xvfb
|
||||
node_js:
|
||||
- "22.16.0"
|
||||
- "22.17.0"
|
||||
cache:
|
||||
directories:
|
||||
- ".meteor"
|
||||
|
||||
@@ -151,7 +151,8 @@ password-based users or from an external service login flow. `options` may come
|
||||
from an untrusted client so make sure to validate any values you read from
|
||||
it. The `user` argument is created on the server and contains a
|
||||
proposed user object with all the automatically generated fields
|
||||
required for the user to log in, including the `_id`.
|
||||
required for the user to log in, including a temporary `_id` (the final _id is
|
||||
generated upon document insertion and not available in this function).
|
||||
|
||||
The function should return the user document (either the one passed in or a
|
||||
newly-created object) with whatever modifications are desired. The returned
|
||||
|
||||
2
meteor
2
meteor
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUNDLE_VERSION=22.16.0.1
|
||||
BUNDLE_VERSION=22.17.1.1
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/node_modules
|
||||
|
||||
1010
npm-packages/meteor-node-stubs/package-lock.json
generated
1010
npm-packages/meteor-node-stubs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "meteor-node-stubs",
|
||||
"author": "Ben Newman <ben@meteor.com>",
|
||||
"description": "Stub implementations of Node built-in modules, a la Browserify",
|
||||
"version": "1.2.13",
|
||||
"version": "1.2.21",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/meteor/meteor/blob/devel/npm-packages/meteor-node-stubs/README.md",
|
||||
|
||||
@@ -689,7 +689,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
/**
|
||||
* @summary Register a function to call when a reset password link is clicked
|
||||
* in an email sent by
|
||||
* [`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail).
|
||||
* [`Accounts.sendResetPasswordEmail`](#Accounts-sendResetPasswordEmail).
|
||||
* This function should be called in top-level code, not inside
|
||||
* `Meteor.startup()`.
|
||||
* @memberof! Accounts
|
||||
@@ -697,7 +697,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
* @param {Function} callback The function to call. It is given two arguments:
|
||||
*
|
||||
* 1. `token`: A password reset token that can be passed to
|
||||
* [`Accounts.resetPassword`](#accounts_resetpassword).
|
||||
* [`Accounts.resetPassword`](#Accounts-resetPassword).
|
||||
* 2. `done`: A function to call when the password reset UI flow is complete. The normal
|
||||
* login process is suspended until this function is called, so that the
|
||||
* password for user A can be reset even if user B was logged in.
|
||||
@@ -715,7 +715,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
/**
|
||||
* @summary Register a function to call when an email verification link is
|
||||
* clicked in an email sent by
|
||||
* [`Accounts.sendVerificationEmail`](#accounts_sendverificationemail).
|
||||
* [`Accounts.sendVerificationEmail`](#Accounts-sendVerificationEmail).
|
||||
* This function should be called in top-level code, not inside
|
||||
* `Meteor.startup()`.
|
||||
* @memberof! Accounts
|
||||
@@ -723,7 +723,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
* @param {Function} callback The function to call. It is given two arguments:
|
||||
*
|
||||
* 1. `token`: An email verification token that can be passed to
|
||||
* [`Accounts.verifyEmail`](#accounts_verifyemail).
|
||||
* [`Accounts.verifyEmail`](#Accounts-verifyEmail).
|
||||
* 2. `done`: A function to call when the email verification UI flow is complete.
|
||||
* The normal login process is suspended until this function is called, so
|
||||
* that the user can be notified that they are verifying their email before
|
||||
@@ -742,7 +742,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
/**
|
||||
* @summary Register a function to call when an account enrollment link is
|
||||
* clicked in an email sent by
|
||||
* [`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail).
|
||||
* [`Accounts.sendEnrollmentEmail`](#Accounts-sendEnrollmentEmail).
|
||||
* This function should be called in top-level code, not inside
|
||||
* `Meteor.startup()`.
|
||||
* @memberof! Accounts
|
||||
@@ -750,7 +750,7 @@ export class AccountsClient extends AccountsCommon {
|
||||
* @param {Function} callback The function to call. It is given two arguments:
|
||||
*
|
||||
* 1. `token`: A password reset token that can be passed to
|
||||
* [`Accounts.resetPassword`](#accounts_resetpassword) to give the newly
|
||||
* [`Accounts.resetPassword`](#Accounts-resetPassword) to give the newly
|
||||
* enrolled account a password.
|
||||
* 2. `done`: A function to call when the enrollment UI flow is complete.
|
||||
* The normal login process is suspended until this function is called, so that
|
||||
|
||||
@@ -34,6 +34,9 @@ BCp.isVerbose = function(config = getMeteorConfig()) {
|
||||
if (config?.modern?.transpiler?.verbose) {
|
||||
return true;
|
||||
}
|
||||
if (config?.modern?.verbose) {
|
||||
return true;
|
||||
}
|
||||
if (config?.verbose) {
|
||||
return true;
|
||||
}
|
||||
@@ -109,7 +112,9 @@ BCp.initializeMeteorAppSwcrc = function () {
|
||||
let currentLastModifiedConfigTime;
|
||||
if (hasSwcJs) {
|
||||
// For dynamic JS files, first get the resolved configuration
|
||||
const resolvedConfig = lastModifiedSwcConfig || getMeteorAppSwcrc(swcFile);
|
||||
const resolvedConfig = lastModifiedSwcConfigTime?.includes(`${fileModTime}`)
|
||||
? lastModifiedSwcConfig || getMeteorAppSwcrc(swcFile)
|
||||
: getMeteorAppSwcrc(swcFile);
|
||||
// Calculate a hash of the resolved configuration to detect changes
|
||||
const contentHash = crypto
|
||||
.createHash('sha256')
|
||||
@@ -129,8 +134,10 @@ BCp.initializeMeteorAppSwcrc = function () {
|
||||
lastModifiedSwcConfig = getMeteorAppSwcrc(swcFile);
|
||||
|
||||
if (this.isVerbose()) {
|
||||
logConfigBlock('SWC Config', lastModifiedSwcConfig);
|
||||
logConfigBlock('SWC Custom Config', lastModifiedSwcConfig);
|
||||
}
|
||||
|
||||
this._swcIncompatible = {};
|
||||
}
|
||||
return lastModifiedSwcConfig;
|
||||
};
|
||||
@@ -145,6 +152,42 @@ BCp.initializeMeteorAppLegacyConfig = function () {
|
||||
return lastModifiedSwcConfig;
|
||||
};
|
||||
|
||||
// Helper function to check if @swc/helpers is available
|
||||
function hasSwcHelpers() {
|
||||
return fs.existsSync(`${getMeteorAppDir()}/node_modules/@swc/helpers`);
|
||||
}
|
||||
|
||||
// Helper function to log friendly messages about SWC helpers
|
||||
function logSwcHelpersStatus(isAvailable) {
|
||||
const label = color('[SWC Helpers]', 36);
|
||||
|
||||
if (isAvailable) {
|
||||
// Green message for when helpers are available
|
||||
console.log(`${label} ${color('✓ @swc/helpers is available in your project!', 32)}`);
|
||||
console.log(` ${color('Benefits:', 32)}`);
|
||||
console.log(` ${color('• Smaller bundle size: External helpers reduce code duplication', 32)}`);
|
||||
console.log(` ${color('• Faster loads: less code to parse on first download', 32)}`);
|
||||
console.log(` ${color('• Optional caching: separate vendor chunk can be cached by browsers', 32)}`);
|
||||
} else {
|
||||
// Yellow message for when helpers are not available
|
||||
console.log(`${label} ${color('⚠ @swc/helpers is not available in your project', 33)}`);
|
||||
console.log(` ${color('Suggestion:', 33)}`);
|
||||
console.log(` ${color('• Add @swc/helpers to your project:', 33)}`);
|
||||
console.log(` ${color('meteor npm install --save @swc/helpers', 33)}`);
|
||||
console.log(` ${color('• This will reduce bundle size and improve performance', 33)}`);
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
let hasSwcHelpersAvailable = false;
|
||||
BCp.initializeMeteorAppSwcHelpersAvailable = function () {
|
||||
hasSwcHelpersAvailable = hasSwcHelpers();
|
||||
if (this.isVerbose()) {
|
||||
logSwcHelpersStatus(hasSwcHelpersAvailable);
|
||||
}
|
||||
return hasSwcHelpersAvailable;
|
||||
};
|
||||
|
||||
BCp.processFilesForTarget = function (inputFiles) {
|
||||
var compiler = this;
|
||||
|
||||
@@ -154,6 +197,7 @@ BCp.processFilesForTarget = function (inputFiles) {
|
||||
this.initializeMeteorAppConfig();
|
||||
this.initializeMeteorAppSwcrc();
|
||||
this.initializeMeteorAppLegacyConfig();
|
||||
this.initializeMeteorAppSwcHelpersAvailable();
|
||||
|
||||
inputFiles.forEach(function (inputFile) {
|
||||
if (inputFile.supportsLazyCompilation) {
|
||||
@@ -284,6 +328,11 @@ BCp.processOneFileForTarget = function (inputFile, source) {
|
||||
jsx: hasJSXSupport,
|
||||
tsx: hasTSXSupport,
|
||||
},
|
||||
...(hasSwcHelpersAvailable &&
|
||||
(packageName == null ||
|
||||
!['modules-runtime'].includes(packageName)) && {
|
||||
externalHelpers: true,
|
||||
}),
|
||||
},
|
||||
module: { type: 'es6' },
|
||||
minify: false,
|
||||
@@ -356,6 +405,7 @@ BCp.processOneFileForTarget = function (inputFile, source) {
|
||||
toBeAdded.hash,
|
||||
lastModifiedSwcConfigTime,
|
||||
isLegacyWebArch ? 'legacy' : '',
|
||||
hasSwcHelpersAvailable,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('-');
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
Package.describe({
|
||||
name: "babel-compiler",
|
||||
summary: "Parser/transpiler for ECMAScript 2015+ syntax",
|
||||
version: '7.12.0',
|
||||
version: '7.12.1-rc331.2',
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'@meteorjs/babel': '7.20.1',
|
||||
'json5': '2.2.3',
|
||||
'semver': '7.6.3',
|
||||
"@meteorjs/swc-core": "1.1.3",
|
||||
"@meteorjs/swc-core": "1.12.14",
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -124,20 +124,6 @@ export class Hook {
|
||||
}
|
||||
}
|
||||
|
||||
async forEachAsync(iterator) {
|
||||
const ids = Object.keys(this.callbacks);
|
||||
for (let i = 0; i < ids.length; ++i) {
|
||||
const id = ids[i];
|
||||
// check to see if the callback was removed during iteration
|
||||
if (hasOwn.call(this.callbacks, id)) {
|
||||
const callback = this.callbacks[id];
|
||||
if (!await iterator(callback)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For each registered callback, call the passed iterator function with the callback.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Register callbacks on a hook",
|
||||
version: '1.6.0',
|
||||
version: '1.6.1-rc331.2',
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'ecmascript',
|
||||
version: '0.16.11',
|
||||
version: '0.16.12-rc331.2',
|
||||
summary: 'Compiler plugin that supports ES2015+ in all .js files',
|
||||
documentation: 'README.md',
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "The Meteor command-line tool",
|
||||
version: "3.3.0",
|
||||
version: "3.3.1-rc.2",
|
||||
});
|
||||
|
||||
Package.includeTool();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "JavaScript minifier",
|
||||
version: '3.0.2',
|
||||
version: '3.0.3-rc331.2',
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -2,6 +2,7 @@ import LocalCollection from './local_collection.js';
|
||||
|
||||
export const hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
export class MiniMongoQueryError extends Error {}
|
||||
// Each element selector contains:
|
||||
// - compileElementSelector, a function with args:
|
||||
// - operand - the "right hand side" of the operator
|
||||
@@ -24,7 +25,7 @@ export const ELEMENT_OPERATORS = {
|
||||
if (!(Array.isArray(operand) && operand.length === 2
|
||||
&& typeof operand[0] === 'number'
|
||||
&& typeof operand[1] === 'number')) {
|
||||
throw Error('argument to $mod must be an array of two numbers');
|
||||
throw new MiniMongoQueryError('argument to $mod must be an array of two numbers');
|
||||
}
|
||||
|
||||
// XXX could require to be ints or round or something
|
||||
@@ -38,7 +39,7 @@ export const ELEMENT_OPERATORS = {
|
||||
$in: {
|
||||
compileElementSelector(operand) {
|
||||
if (!Array.isArray(operand)) {
|
||||
throw Error('$in needs an array');
|
||||
throw new MiniMongoQueryError('$in needs an array');
|
||||
}
|
||||
|
||||
const elementMatchers = operand.map(option => {
|
||||
@@ -47,7 +48,7 @@ export const ELEMENT_OPERATORS = {
|
||||
}
|
||||
|
||||
if (isOperatorObject(option)) {
|
||||
throw Error('cannot nest $ under $in');
|
||||
throw new MiniMongoQueryError('cannot nest $ under $in');
|
||||
}
|
||||
|
||||
return equalityElementMatcher(option);
|
||||
@@ -74,7 +75,7 @@ export const ELEMENT_OPERATORS = {
|
||||
// does.
|
||||
operand = 0;
|
||||
} else if (typeof operand !== 'number') {
|
||||
throw Error('$size needs a number');
|
||||
throw new MiniMongoQueryError('$size needs a number');
|
||||
}
|
||||
|
||||
return value => Array.isArray(value) && value.length === operand;
|
||||
@@ -112,16 +113,16 @@ export const ELEMENT_OPERATORS = {
|
||||
'maxKey': 127,
|
||||
};
|
||||
if (!hasOwn.call(operandAliasMap, operand)) {
|
||||
throw Error(`unknown string alias for $type: ${operand}`);
|
||||
throw new MiniMongoQueryError(`unknown string alias for $type: ${operand}`);
|
||||
}
|
||||
operand = operandAliasMap[operand];
|
||||
} else if (typeof operand === 'number') {
|
||||
if (operand === 0 || operand < -1
|
||||
|| (operand > 19 && operand !== 127)) {
|
||||
throw Error(`Invalid numerical $type code: ${operand}`);
|
||||
throw new MiniMongoQueryError(`Invalid numerical $type code: ${operand}`);
|
||||
}
|
||||
} else {
|
||||
throw Error('argument to $type is not a number or a string');
|
||||
throw new MiniMongoQueryError('argument to $type is not a number or a string');
|
||||
}
|
||||
|
||||
return value => (
|
||||
@@ -168,7 +169,7 @@ export const ELEMENT_OPERATORS = {
|
||||
$regex: {
|
||||
compileElementSelector(operand, valueSelector) {
|
||||
if (!(typeof operand === 'string' || operand instanceof RegExp)) {
|
||||
throw Error('$regex has to be a string or RegExp');
|
||||
throw new MiniMongoQueryError('$regex has to be a string or RegExp');
|
||||
}
|
||||
|
||||
let regexp;
|
||||
@@ -180,7 +181,7 @@ export const ELEMENT_OPERATORS = {
|
||||
// ones (eg, Mongo supports x and s). Ideally we would implement x and s
|
||||
// by transforming the regexp, but not today...
|
||||
if (/[^gim]/.test(valueSelector.$options)) {
|
||||
throw new Error('Only the i, m, and g regexp options are supported');
|
||||
throw new MiniMongoQueryError('Only the i, m, and g regexp options are supported');
|
||||
}
|
||||
|
||||
const source = operand instanceof RegExp ? operand.source : operand;
|
||||
@@ -198,7 +199,7 @@ export const ELEMENT_OPERATORS = {
|
||||
dontExpandLeafArrays: true,
|
||||
compileElementSelector(operand, valueSelector, matcher) {
|
||||
if (!LocalCollection._isPlainObject(operand)) {
|
||||
throw Error('$elemMatch need an object');
|
||||
throw new MiniMongoQueryError('$elemMatch need an object');
|
||||
}
|
||||
|
||||
const isDocMatcher = !isOperatorObject(
|
||||
@@ -353,7 +354,7 @@ const VALUE_OPERATORS = {
|
||||
// $options just provides options for $regex; its logic is inside $regex
|
||||
$options(operand, valueSelector) {
|
||||
if (!hasOwn.call(valueSelector, '$regex')) {
|
||||
throw Error('$options needs a $regex');
|
||||
throw new MiniMongoQueryError('$options needs a $regex');
|
||||
}
|
||||
|
||||
return everythingMatcher;
|
||||
@@ -361,14 +362,14 @@ const VALUE_OPERATORS = {
|
||||
// $maxDistance is basically an argument to $near
|
||||
$maxDistance(operand, valueSelector) {
|
||||
if (!valueSelector.$near) {
|
||||
throw Error('$maxDistance needs a $near');
|
||||
throw new MiniMongoQueryError('$maxDistance needs a $near');
|
||||
}
|
||||
|
||||
return everythingMatcher;
|
||||
},
|
||||
$all(operand, valueSelector, matcher) {
|
||||
if (!Array.isArray(operand)) {
|
||||
throw Error('$all requires array');
|
||||
throw new MiniMongoQueryError('$all requires array');
|
||||
}
|
||||
|
||||
// Not sure why, but this seems to be what MongoDB does.
|
||||
@@ -379,7 +380,7 @@ const VALUE_OPERATORS = {
|
||||
const branchedMatchers = operand.map(criterion => {
|
||||
// XXX handle $all/$elemMatch combination
|
||||
if (isOperatorObject(criterion)) {
|
||||
throw Error('no $ expressions in $all');
|
||||
throw new MiniMongoQueryError('no $ expressions in $all');
|
||||
}
|
||||
|
||||
// This is always a regexp or equality selector.
|
||||
@@ -392,7 +393,7 @@ const VALUE_OPERATORS = {
|
||||
},
|
||||
$near(operand, valueSelector, matcher, isRoot) {
|
||||
if (!isRoot) {
|
||||
throw Error('$near can\'t be inside another $ operator');
|
||||
throw new MiniMongoQueryError('$near can\'t be inside another $ operator');
|
||||
}
|
||||
|
||||
matcher._hasGeoQuery = true;
|
||||
@@ -433,7 +434,7 @@ const VALUE_OPERATORS = {
|
||||
maxDistance = valueSelector.$maxDistance;
|
||||
|
||||
if (!isIndexable(operand)) {
|
||||
throw Error('$near argument must be coordinate pair or GeoJSON');
|
||||
throw new MiniMongoQueryError('$near argument must be coordinate pair or GeoJSON');
|
||||
}
|
||||
|
||||
point = pointToArray(operand);
|
||||
@@ -549,12 +550,12 @@ const andBranchedMatchers = andSomeMatchers;
|
||||
|
||||
function compileArrayOfDocumentSelectors(selectors, matcher, inElemMatch) {
|
||||
if (!Array.isArray(selectors) || selectors.length === 0) {
|
||||
throw Error('$and/$or/$nor must be nonempty array');
|
||||
throw new MiniMongoQueryError('$and/$or/$nor must be nonempty array');
|
||||
}
|
||||
|
||||
return selectors.map(subSelector => {
|
||||
if (!LocalCollection._isPlainObject(subSelector)) {
|
||||
throw Error('$or/$and/$nor entries need to be full objects');
|
||||
throw new MiniMongoQueryError('$or/$and/$nor entries need to be full objects');
|
||||
}
|
||||
|
||||
return compileDocumentSelector(subSelector, matcher, {inElemMatch});
|
||||
@@ -576,7 +577,7 @@ export function compileDocumentSelector(docSelector, matcher, options = {}) {
|
||||
// Outer operators are either logical operators (they recurse back into
|
||||
// this function), or $where.
|
||||
if (!hasOwn.call(LOGICAL_OPERATORS, key)) {
|
||||
throw new Error(`Unrecognized logical operator: ${key}`);
|
||||
throw new MiniMongoQueryError(`Unrecognized logical operator: ${key}`);
|
||||
}
|
||||
|
||||
matcher._isSimple = false;
|
||||
@@ -682,7 +683,7 @@ function distanceCoordinatePairs(a, b) {
|
||||
// for equality with that thing.
|
||||
export function equalityElementMatcher(elementSelector) {
|
||||
if (isOperatorObject(elementSelector)) {
|
||||
throw Error('Can\'t create equalityValueSelector for operator object');
|
||||
throw new MiniMongoQueryError('Can\'t create equalityValueSelector for operator object');
|
||||
}
|
||||
|
||||
// Special-case: null and undefined are equal (if you got undefined in there
|
||||
@@ -759,7 +760,7 @@ function getOperandBitmask(operand, selector) {
|
||||
}
|
||||
|
||||
// bad operand
|
||||
throw Error(
|
||||
throw new MiniMongoQueryError(
|
||||
`operand to ${selector} must be a numeric bitmask (representable as a ` +
|
||||
'non-negative 32-bit signed integer), a bindata bitmask or an array with ' +
|
||||
'bit positions (non-negative integers)'
|
||||
@@ -813,12 +814,11 @@ function insertIntoDocument(document, key, value) {
|
||||
(existingKey.length > key.length && existingKey.indexOf(`${key}.`) === 0) ||
|
||||
(key.length > existingKey.length && key.indexOf(`${existingKey}.`) === 0)
|
||||
) {
|
||||
throw new Error(
|
||||
`cannot infer query fields to set, both paths '${existingKey}' and ` +
|
||||
`'${key}' are matched`
|
||||
throw new MiniMongoQueryError(
|
||||
`cannot infer query fields to set, both paths '${existingKey}' and '${key}' are matched`
|
||||
);
|
||||
} else if (existingKey === key) {
|
||||
throw new Error(
|
||||
throw new MiniMongoQueryError(
|
||||
`cannot infer query fields to set, path '${key}' is matched twice`
|
||||
);
|
||||
}
|
||||
@@ -863,7 +863,7 @@ export function isOperatorObject(valueSelector, inconsistentOK) {
|
||||
theseAreOperators = thisIsOperator;
|
||||
} else if (theseAreOperators !== thisIsOperator) {
|
||||
if (!inconsistentOK) {
|
||||
throw new Error(
|
||||
throw new MiniMongoQueryError(
|
||||
`Inconsistent operator: ${JSON.stringify(valueSelector)}`
|
||||
);
|
||||
}
|
||||
@@ -1132,7 +1132,7 @@ function operatorBranchedMatcher(valueSelector, matcher, isRoot) {
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(`Unrecognized operator: ${operator}`);
|
||||
throw new MiniMongoQueryError(`Unrecognized operator: ${operator}`);
|
||||
});
|
||||
|
||||
return andBranchedMatchers(operatorMatchers);
|
||||
@@ -1232,7 +1232,7 @@ function populateDocumentWithObject(document, key, value) {
|
||||
// Literal (possibly empty) object ( or empty object )
|
||||
// Don't allow mixing '$'-prefixed with non-'$'-prefixed fields
|
||||
if (keys.length !== unprefixedKeys.length) {
|
||||
throw new Error(`unknown operator: ${unprefixedKeys[0]}`);
|
||||
throw new MiniMongoQueryError(`unknown operator: ${unprefixedKeys[0]}`);
|
||||
}
|
||||
|
||||
validateObject(value, key);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Meteor's client-side datastore: a port of MongoDB to Javascript",
|
||||
version: "2.0.2",
|
||||
version: "2.0.3-rc331.2",
|
||||
});
|
||||
|
||||
Package.onUse((api) => {
|
||||
|
||||
10
packages/modern-browsers/modern.d.ts
vendored
10
packages/modern-browsers/modern.d.ts
vendored
@@ -1,4 +1,12 @@
|
||||
export declare function isModern(
|
||||
browser: { name: string, major: number, minor?: number, patch?: number }
|
||||
): boolean;
|
||||
|
||||
export declare function setMinimumBrowserVersions(
|
||||
versions: Record<string, number | number[]>,
|
||||
source: string
|
||||
source?: string
|
||||
): void;
|
||||
|
||||
export declare function getMinimumBrowserVersions(): Record<string, Record<string, number | number[]>>;
|
||||
|
||||
export declare function calculateHashOfMinimumVersions(): string;
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'modern-browsers',
|
||||
version: '0.2.2',
|
||||
version: '0.2.3-rc331.2',
|
||||
summary:
|
||||
'API for defining the boundary between modern and legacy ' +
|
||||
'JavaScript clients',
|
||||
|
||||
@@ -8,6 +8,8 @@ import { replaceMongoAtomWithMeteor, replaceTypes } from './mongo_common';
|
||||
* This is an internal implementation detail and is created lazily by the main Cursor class.
|
||||
*/
|
||||
export class AsynchronousCursor {
|
||||
_closing = false;
|
||||
_pendingNext = null;
|
||||
constructor(dbCursor, cursorDescription, options) {
|
||||
this._dbCursor = dbCursor;
|
||||
this._cursorDescription = cursorDescription;
|
||||
@@ -36,10 +38,19 @@ export class AsynchronousCursor {
|
||||
// Returns a Promise for the next object from the underlying cursor (before
|
||||
// the Mongo->Meteor type replacement).
|
||||
async _rawNextObjectPromise() {
|
||||
if (this._closing) {
|
||||
// Prevent next() after close is called
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return this._dbCursor.next();
|
||||
this._pendingNext = this._dbCursor.next();
|
||||
const result = await this._pendingNext;
|
||||
this._pendingNext = null;
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
this._pendingNext = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,24 +85,24 @@ export class AsynchronousCursor {
|
||||
// _nextObjectPromise) or rejected if the cursor doesn't return within
|
||||
// timeoutMS ms.
|
||||
_nextObjectPromiseWithTimeout(timeoutMS) {
|
||||
if (!timeoutMS) {
|
||||
return this._nextObjectPromise();
|
||||
}
|
||||
const nextObjectPromise = this._nextObjectPromise();
|
||||
const timeoutErr = new Error('Client-side timeout waiting for next object');
|
||||
const timeoutPromise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(timeoutErr);
|
||||
if (!timeoutMS) {
|
||||
return nextObjectPromise;
|
||||
}
|
||||
|
||||
const timeoutPromise = new Promise(resolve => {
|
||||
// On timeout, close the cursor.
|
||||
const timeoutId = setTimeout(() => {
|
||||
resolve(this.close());
|
||||
}, timeoutMS);
|
||||
});
|
||||
return Promise.race([nextObjectPromise, timeoutPromise])
|
||||
.catch((err) => {
|
||||
if (err === timeoutErr) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
|
||||
// If the `_nextObjectPromise` returned first, cancel the timeout.
|
||||
nextObjectPromise.finally(() => {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.race([nextObjectPromise, timeoutPromise]);
|
||||
}
|
||||
|
||||
async forEach(callback, thisArg) {
|
||||
@@ -123,7 +134,16 @@ export class AsynchronousCursor {
|
||||
}
|
||||
|
||||
// Mostly usable for tailable cursors.
|
||||
close() {
|
||||
async close() {
|
||||
this._closing = true;
|
||||
// If there's a pending next(), wait for it to finish or abort
|
||||
if (this._pendingNext) {
|
||||
try {
|
||||
await this._pendingNext;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
this._dbCursor.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import { AsyncMethods } from './methods_async';
|
||||
import { SyncMethods } from './methods_sync';
|
||||
import { IndexMethods } from './methods_index';
|
||||
import {
|
||||
ID_GENERATORS, normalizeOptions,
|
||||
ID_GENERATORS,
|
||||
normalizeOptions,
|
||||
setupAutopublish,
|
||||
setupConnection,
|
||||
setupDriver,
|
||||
@@ -11,7 +12,6 @@ import {
|
||||
validateCollectionName
|
||||
} from './collection_utils';
|
||||
import { ReplicationMethods } from './methods_replication';
|
||||
import { watchChangeStream } from './watch_change_stream';
|
||||
|
||||
/**
|
||||
* @summary Namespace for MongoDB-related items
|
||||
@@ -267,7 +267,3 @@ Meteor.Collection = Mongo.Collection;
|
||||
|
||||
// Allow deny stuff is now in the allow-deny package
|
||||
Object.assign(Mongo.Collection.prototype, AllowDeny.CollectionPrototype);
|
||||
|
||||
// Só agora que Mongo.Collection existe, adicionamos o método ao prototype
|
||||
Object.assign(Mongo.Collection.prototype, { watchChangeStream });
|
||||
|
||||
|
||||
@@ -88,12 +88,17 @@ export function normalizeOptions(options) {
|
||||
options.connection = options.manager;
|
||||
}
|
||||
|
||||
const cleanedOptions = Object.fromEntries(
|
||||
Object.entries(options || {}).filter(([_, v]) => v !== undefined),
|
||||
);
|
||||
|
||||
// 2) Spread defaults first, then only the defined overrides
|
||||
return {
|
||||
connection: undefined,
|
||||
idGeneration: 'STRING',
|
||||
transform: null,
|
||||
_driver: undefined,
|
||||
_preventAutopublish: false,
|
||||
...options,
|
||||
...cleanedOptions,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* @summary Watches the MongoDB collection using Change Streams.
|
||||
* @locus Server
|
||||
* @memberof Mongo.Collection
|
||||
* @instance
|
||||
* @param {Array} [pipeline] Optional aggregation pipeline to filter Change Stream events.
|
||||
* @param {Object} [options] Optional settings for the Change Stream.
|
||||
* @returns {ChangeStream} The MongoDB ChangeStream instance.
|
||||
* @throws {Error} If called on a client/minimongo collection.
|
||||
*
|
||||
* @example
|
||||
* const changeStream = MyCollection.watchChangeStream([
|
||||
* { $match: { 'operationType': 'insert' } }
|
||||
* ]);
|
||||
* changeStream.on('change', (change) => {
|
||||
* console.log('Change detected:', change);
|
||||
* });
|
||||
*/
|
||||
|
||||
export function watchChangeStream(pipeline = [], options = {}) {
|
||||
// Only available on server
|
||||
if (typeof Package === 'undefined' || !this.rawCollection) {
|
||||
throw new Error('watchChangeStream is only available on server collections');
|
||||
}
|
||||
const raw = this.rawCollection();
|
||||
if (!raw.watch) {
|
||||
throw new Error('Underlying collection does not support watch (Change Streams)');
|
||||
}
|
||||
console.log('[watchChangeStream] Chamando raw.watch() com pipeline:', JSON.stringify(pipeline, null, 2), 'e options:', JSON.stringify(options, null, 2));
|
||||
return raw.watch(pipeline, options);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { CLIENT_ONLY_METHODS, getAsyncMethodName } from 'meteor/minimongo/constants';
|
||||
import { MiniMongoQueryError } from 'meteor/minimongo/common';
|
||||
import path from 'path';
|
||||
import { AsynchronousCursor } from './asynchronous_cursor';
|
||||
import { Cursor } from './cursor';
|
||||
@@ -886,6 +887,9 @@ Object.assign(MongoConnection.prototype, {
|
||||
} catch (e) {
|
||||
// XXX make all compilation errors MinimongoError or something
|
||||
// so that this doesn't ignore unrelated exceptions
|
||||
if (e instanceof MiniMongoQueryError) {
|
||||
throw e;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Package.describe({
|
||||
summary: "Adaptor for using MongoDB and Minimongo over DDP",
|
||||
version: "2.1.2",
|
||||
version: "2.1.3-rc331.2",
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -485,3 +485,58 @@ Meteor.isServer && Tinytest.addAsync('collection - simple add', async function(t
|
||||
test.equal((await collection.findOneAsync(id)).a, 2);
|
||||
await collection.removeAsync({});
|
||||
});
|
||||
|
||||
Tinytest.addAsync('collection - default idGeneration when not provided', async function(test) {
|
||||
if (!Meteor.isServer) {
|
||||
return;
|
||||
}
|
||||
// Create a collection without specifying idGeneration option
|
||||
var collectionName = 'defaultIdGeneration' + test.id;
|
||||
var collection = new Mongo.Collection(collectionName, { idGeneration: undefined });
|
||||
|
||||
// Insert a document
|
||||
var id = await collection.insertAsync({a: 1});
|
||||
|
||||
// Verify that the _id is a string
|
||||
test.isTrue(typeof id === 'string', 'Document _id should be a string when no idGeneration option is provided');
|
||||
test.isFalse(id instanceof Mongo.ObjectID, 'Document _id should not be a Mongo.ObjectID when no idGeneration option is provided');
|
||||
|
||||
// Clean up
|
||||
await collection.removeAsync({});
|
||||
});
|
||||
|
||||
Tinytest.addAsync('collection - compare default idGeneration with explicit idGeneration', async function(test) {
|
||||
if (!Meteor.isServer) {
|
||||
return;
|
||||
}
|
||||
// Create a collection without specifying idGeneration option
|
||||
var defaultCollectionName = 'defaultIdGeneration2' + test.id;
|
||||
var defaultCollection = new Mongo.Collection(defaultCollectionName, { idGeneration: undefined });
|
||||
|
||||
// Create a collection with explicit STRING idGeneration
|
||||
var stringCollectionName = 'stringIdGeneration' + test.id;
|
||||
var stringCollection = new Mongo.Collection(stringCollectionName, { idGeneration: 'STRING' });
|
||||
|
||||
// Create a collection with MONGO idGeneration
|
||||
var mongoCollectionName = 'mongoIdGeneration' + test.id;
|
||||
var mongoCollection = new Mongo.Collection(mongoCollectionName, { idGeneration: 'MONGO' });
|
||||
|
||||
// Insert documents
|
||||
var defaultId = await defaultCollection.insertAsync({a: 1});
|
||||
var stringId = await stringCollection.insertAsync({a: 1});
|
||||
var mongoId = await mongoCollection.insertAsync({a: 1});
|
||||
|
||||
// Verify default behaves like STRING
|
||||
test.isTrue(typeof defaultId === 'string', 'Default idGeneration should produce string IDs');
|
||||
test.isTrue(typeof stringId === 'string', 'STRING idGeneration should produce string IDs');
|
||||
test.isFalse(defaultId instanceof Mongo.ObjectID, 'Default idGeneration should not produce Mongo.ObjectID');
|
||||
test.isFalse(stringId instanceof Mongo.ObjectID, 'STRING idGeneration should not produce Mongo.ObjectID');
|
||||
|
||||
// Verify MONGO produces ObjectIDs
|
||||
test.isTrue(mongoId instanceof Mongo.ObjectID, 'MONGO idGeneration should produce Mongo.ObjectID');
|
||||
|
||||
// Clean up
|
||||
await defaultCollection.removeAsync({});
|
||||
await stringCollection.removeAsync({});
|
||||
await mongoCollection.removeAsync({});
|
||||
});
|
||||
|
||||
@@ -4298,9 +4298,10 @@ Tinytest.addAsync(
|
||||
await Collection.updateAsync({ _id: 'a' }, { $set: { num: 1 } });
|
||||
await Collection.updateAsync({ _id: 'b' }, { $set: { num: 2 } });
|
||||
|
||||
if(Meteor.isClient) Meteor._sleepForMs(100); // wait for async operations to complete
|
||||
items = await Collection.find().fetchAsync();
|
||||
itemIds = items.map(_item => _item.num);
|
||||
|
||||
|
||||
test.equal(itemIds, [1, 2]);
|
||||
|
||||
await Collection.removeAsync({ _id: 'a' });
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { MiniMongoQueryError } from 'meteor/minimongo/common';
|
||||
|
||||
var randomId = Random.id();
|
||||
var OplogCollection = new Mongo.Collection("oplog-" + randomId);
|
||||
|
||||
@@ -9,11 +11,16 @@ Tinytest.addAsync('mongo-livedata - oplog - cursorSupported', async function(
|
||||
|
||||
var supported = async function(expected, selector, options) {
|
||||
var cursor = OplogCollection.find(selector, options);
|
||||
var handle = await cursor.observeChanges({ added: function() {} });
|
||||
// If there's no oplog at all, we shouldn't ever use it.
|
||||
if (!oplogEnabled) expected = false;
|
||||
test.equal(!!handle._multiplexer._observeDriver._usesOplog, expected);
|
||||
handle.stop();
|
||||
try {
|
||||
var handle = await cursor.observeChanges({ added: function() {} });
|
||||
// If there's no oplog at all, we shouldn't ever use it.
|
||||
if (!oplogEnabled) expected = false;
|
||||
test.equal(!!handle._multiplexer._observeDriver._usesOplog, !!expected);
|
||||
handle.stop();
|
||||
} catch(e){
|
||||
if (e instanceof MiniMongoQueryError) return test.isFalse(expected);
|
||||
else test.fail(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
await supported(true, 'asdf');
|
||||
|
||||
4
packages/npm-mongo-legacy/README.md
Normal file
4
packages/npm-mongo-legacy/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# npm-mongo-legacy
|
||||
[Source code of released version](https://github.com/meteor/meteor/tree/devel/packages/npm-mongo-legacy)
|
||||
***
|
||||
|
||||
3
packages/npm-mongo-legacy/index.d.ts
vendored
Normal file
3
packages/npm-mongo-legacy/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as NpmModuleMongodb from 'mongodb';
|
||||
declare const NpmModuleMongodbVersion: string;
|
||||
export { NpmModuleMongodb, NpmModuleMongodbVersion };
|
||||
18
packages/npm-mongo-legacy/package.js
Normal file
18
packages/npm-mongo-legacy/package.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// This has been moved out of the `mongo` package so it can be used by the tool
|
||||
// via isopacket, without having to also load ddp-server.
|
||||
|
||||
Package.describe({
|
||||
summary: "Wrapper around the mongo npm package (legacy)",
|
||||
version: "6.9.0-rc331.2",
|
||||
documentation: null,
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
mongodb: "6.9.0",
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
api.addFiles("wrapper.js", "server");
|
||||
api.export(["NpmModuleMongodb", "NpmModuleMongodbVersion"], "server");
|
||||
api.addAssets("index.d.ts", "server");
|
||||
});
|
||||
11
packages/npm-mongo-legacy/wrapper.js
Normal file
11
packages/npm-mongo-legacy/wrapper.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const oldNoDeprecationValue = process.noDeprecation;
|
||||
try {
|
||||
// Silence deprecation warnings introduced in a patch update to mongodb:
|
||||
// https://github.com/meteor/meteor/pull/9942#discussion_r218564879
|
||||
process.noDeprecation = true;
|
||||
NpmModuleMongodb = Npm.require('mongodb');
|
||||
} finally {
|
||||
process.noDeprecation = oldNoDeprecationValue;
|
||||
}
|
||||
|
||||
NpmModuleMongodbVersion = Npm.require('mongodb/package.json').version;
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
Package.describe({
|
||||
summary: "Wrapper around the mongo npm package",
|
||||
version: "6.10.2",
|
||||
version: "6.16.0-rc331.2",
|
||||
documentation: null,
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
mongodb: "6.9.0"
|
||||
mongodb: "6.16.0"
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,11 +1,49 @@
|
||||
const { MongoClient, MongoCompatibilityError } = Npm.require('mongodb');
|
||||
|
||||
function connect(client) {
|
||||
return client.connect()
|
||||
.catch(error => {
|
||||
if (error.cause instanceof MongoCompatibilityError && error.message.includes('maximum wire version')) {
|
||||
console.warn(`[DEPRECATION] Legacy MongoDB version detected, using mongo-legacy package: ${error.message}
|
||||
Warning: MongoDB versions <= 3.6 are deprecated. Some Meteor features may not work properly with this version.
|
||||
It is recommended to use MongoDB >= 4.`);
|
||||
if (!Package['npm-mongo-legacy']) {
|
||||
throw new Error('Please, install npm-mongo-legacy package to use this version of MongoDB running "meteor add npm-mongo-legacy", then move the listed package inside .meteor/packages to the top.');
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (process.env.MONGO_URL && (/^mongodb(\+srv)?:\/\//.test(process.env.MONGO_URL))) {
|
||||
try {
|
||||
connect(new MongoClient(process.env.MONGO_URL, {
|
||||
tls: true,
|
||||
tlsAllowInvalidCertificates: true,
|
||||
})).then(client => {
|
||||
if (client) client.close();
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('Invalid MongoDB connection string in MONGO_URL:', process.env.MONGO_URL);
|
||||
}
|
||||
}
|
||||
|
||||
const useLegacyMongo = !!Package['npm-mongo-legacy']
|
||||
const oldNoDeprecationValue = process.noDeprecation;
|
||||
|
||||
useLegacyMongo && console.log('WARN: npm-mongo-legacy package detected, using package for mongo <= 3.6');
|
||||
|
||||
try {
|
||||
// Silence deprecation warnings introduced in a patch update to mongodb:
|
||||
// https://github.com/meteor/meteor/pull/9942#discussion_r218564879
|
||||
process.noDeprecation = true;
|
||||
NpmModuleMongodb = Npm.require('mongodb');
|
||||
NpmModuleMongodb = useLegacyMongo
|
||||
? Package['npm-mongo-legacy'].NpmModuleMongodb
|
||||
: Npm.require('mongodb');
|
||||
} finally {
|
||||
process.noDeprecation = oldNoDeprecationValue;
|
||||
}
|
||||
|
||||
NpmModuleMongodbVersion = Npm.require('mongodb/package.json').version;
|
||||
NpmModuleMongodbVersion = useLegacyMongo
|
||||
? Package['npm-mongo-legacy'].NpmModuleMongodbVersion
|
||||
: Npm.require('mongodb/package.json').version;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'standard-minifier-js',
|
||||
version: '3.1.0',
|
||||
version: '3.1.1-rc331.2',
|
||||
summary: 'Standard javascript minifiers used with Meteor apps by default.',
|
||||
documentation: 'README.md',
|
||||
});
|
||||
@@ -12,7 +12,7 @@ Package.registerBuildPlugin({
|
||||
'ecmascript'
|
||||
],
|
||||
npmDependencies: {
|
||||
'@meteorjs/swc-core': '1.1.3',
|
||||
'@meteorjs/swc-core': '1.12.14',
|
||||
'acorn': '8.10.0',
|
||||
"@babel/runtime": "7.18.9",
|
||||
'@babel/parser': '7.22.7',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Tiny testing framework",
|
||||
version: '1.3.1',
|
||||
version: '1.3.2-rc331.2',
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -74,7 +74,7 @@ export class TestCaseResults {
|
||||
var frame = stack[i];
|
||||
// Heuristic: use the OUTERMOST line which is in a :tests.js
|
||||
// file (this is less likely to be a test helper function).
|
||||
const fileName = frame.getFileName();
|
||||
const fileName = frame?.getFileName ? frame.getFileName() : null;
|
||||
if (fileName && fileName.match(/:tests\.js/)) {
|
||||
doc.filename = fileName;
|
||||
doc.line = frame.getLineNumber();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'typescript',
|
||||
version: '5.6.4',
|
||||
version: '5.6.5-rc331.2',
|
||||
summary:
|
||||
'Compiler plugin that compiles TypeScript and ECMAScript in .ts and .tsx files',
|
||||
documentation: 'README.md',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"track": "METEOR",
|
||||
"version": "3.3-rc.0",
|
||||
"version": "3.3.1-rc.2",
|
||||
"recommended": false,
|
||||
"official": false,
|
||||
"description": "Meteor experimental release"
|
||||
|
||||
@@ -5,7 +5,7 @@ set -u
|
||||
|
||||
UNAME=$(uname)
|
||||
ARCH=$(uname -m)
|
||||
NODE_VERSION=22.16.0
|
||||
NODE_VERSION=22.17.1
|
||||
MONGO_VERSION_64BIT=7.0.16
|
||||
MONGO_VERSION_32BIT=3.2.22
|
||||
NPM_VERSION=10.9.2
|
||||
|
||||
@@ -1203,71 +1203,85 @@ main.registerCommand({
|
||||
toIgnore.push(/(\.html|\.js|\.css)/);
|
||||
}
|
||||
|
||||
try {
|
||||
// Prototype option should use local skeleton.
|
||||
// Maybe we should use a different skeleton for prototype
|
||||
if (options.prototype) throw new Error("Using prototype option");
|
||||
// if using the release option we should use the default skeleton
|
||||
// using it as it was before 2.x
|
||||
if (release.explicit) throw new Error("Using release option");
|
||||
const copyFromLocalSkeleton = async () => {
|
||||
await files.cp_r(
|
||||
skeletonPath,
|
||||
appPath,
|
||||
{
|
||||
transformFilename: function (f) {
|
||||
return transform(f);
|
||||
},
|
||||
transformContents: function (contents, f) {
|
||||
// check if this app is just for prototyping if it is then we need to add autopublish and insecure in the packages file
|
||||
if (/packages/.test(f)) {
|
||||
const prototypePackages = () =>
|
||||
"autopublish # Publish all data to the clients (for prototyping)\n" +
|
||||
"insecure # Allow all DB writes from clients (for prototyping)";
|
||||
|
||||
await setupExampleByURL(`https://github.com/meteor/skel-${skeleton}`);
|
||||
} catch (e) {
|
||||
// XXX: if there is the need to add more options maybe we should have a better abstraction for this if-else
|
||||
if (options.prototype) {
|
||||
return Buffer.from(
|
||||
contents.toString().replace(/~prototype~/g, prototypePackages())
|
||||
);
|
||||
} else {
|
||||
return Buffer.from(contents.toString().replace(/~prototype~/g, ""));
|
||||
}
|
||||
}
|
||||
if (/(\.html|\.[jt]sx?|\.css)/.test(f)) {
|
||||
return Buffer.from(transform(contents.toString()));
|
||||
} else {
|
||||
return contents;
|
||||
}
|
||||
},
|
||||
ignore: toIgnore,
|
||||
preserveSymlinks: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (
|
||||
e.message !== "Using prototype option" &&
|
||||
e.message !== "Using release option"
|
||||
) {
|
||||
// something has happened while creating the app using git clone
|
||||
Console.error(
|
||||
`Something has happened while creating your app using git clone.
|
||||
// Check if the local skeleton path exists
|
||||
const skeletonPath = files.pathJoin(
|
||||
__dirnameConverted,
|
||||
"..",
|
||||
"static-assets",
|
||||
`skel-${skeleton}`
|
||||
);
|
||||
|
||||
const useLocalSkeleton = files.exists(skeletonPath) ||
|
||||
options.prototype ||
|
||||
release.explicit;
|
||||
if (useLocalSkeleton) {
|
||||
// Use local skeleton
|
||||
await copyFromLocalSkeleton();
|
||||
} else {
|
||||
try {
|
||||
// Prototype option should use local skeleton.
|
||||
// Maybe we should use a different skeleton for prototype
|
||||
if (options.prototype) throw new Error("Using prototype option");
|
||||
// if using the release option we should use the default skeleton
|
||||
// using it as it was before 2.x
|
||||
if (release.explicit) throw new Error("Using release option");
|
||||
|
||||
// If local skeleton doesn't exist, use setupExampleByURL
|
||||
await setupExampleByURL(`https://github.com/meteor/skel-${skeleton}`);
|
||||
} catch (e) {
|
||||
if (
|
||||
e.message !== "Using prototype option" &&
|
||||
e.message !== "Using release option"
|
||||
) {
|
||||
// something has happened while creating the app using git clone
|
||||
Console.error(
|
||||
`Something has happened while creating your app using git clone.
|
||||
Will use cached version of skeletons.
|
||||
Error message: `,
|
||||
e.message
|
||||
);
|
||||
e.message
|
||||
);
|
||||
}
|
||||
// For prototype or release options, use local skeleton
|
||||
await copyFromLocalSkeleton();
|
||||
}
|
||||
|
||||
// TODO: decide if this should stay here or not.
|
||||
await files.cp_r(
|
||||
files.pathJoin(
|
||||
__dirnameConverted,
|
||||
"..",
|
||||
"static-assets",
|
||||
`skel-${skeleton}`
|
||||
),
|
||||
appPath,
|
||||
{
|
||||
transformFilename: function (f) {
|
||||
return transform(f);
|
||||
},
|
||||
transformContents: function (contents, f) {
|
||||
// check if this app is just for prototyping if it is then we need to add autopublish and insecure in the packages file
|
||||
if (/packages/.test(f)) {
|
||||
const prototypePackages = () =>
|
||||
"autopublish # Publish all data to the clients (for prototyping)\n" +
|
||||
"insecure # Allow all DB writes from clients (for prototyping)";
|
||||
|
||||
// XXX: if there is the need to add more options maybe we should have a better abstraction for this if-else
|
||||
if (options.prototype) {
|
||||
return Buffer.from(
|
||||
contents.toString().replace(/~prototype~/g, prototypePackages())
|
||||
);
|
||||
} else {
|
||||
return Buffer.from(contents.toString().replace(/~prototype~/g, ""));
|
||||
}
|
||||
}
|
||||
if (/(\.html|\.[jt]sx?|\.css)/.test(f)) {
|
||||
return Buffer.from(transform(contents.toString()));
|
||||
} else {
|
||||
return contents;
|
||||
}
|
||||
},
|
||||
ignore: toIgnore,
|
||||
preserveSymlinks: true,
|
||||
}
|
||||
);
|
||||
await setupMessages();
|
||||
}
|
||||
await setupMessages();
|
||||
|
||||
Console.info("");
|
||||
});
|
||||
@@ -3412,20 +3426,58 @@ const setupBenchmarkSuite = async (profilingPath) => {
|
||||
if (await files.exists(profilingPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check git availability and version
|
||||
const [okGitVersion, errGitVersion] = await bash`git --version`;
|
||||
if (errGitVersion) throw new Error("git is not installed");
|
||||
|
||||
const parsedGitVersion = semver.coerce(okGitVersion.match(/\d+\.\d+\.\d+/)[0] || '')?.version;
|
||||
const checkInvalidGitVersion = parsedGitVersion == null || semver.lt(parsedGitVersion, '2.25.0');
|
||||
if (checkInvalidGitVersion) {
|
||||
const parsedGitVersion = semver.coerce(okGitVersion.match(/\d+\.\d+\.\d+/)?.[0] || '')?.version;
|
||||
if (!parsedGitVersion || semver.lt(parsedGitVersion, '2.25.0')) {
|
||||
throw new Error("git version is too old. Please upgrade to at least 2.25");
|
||||
}
|
||||
|
||||
// Set GIT_TERMINAL_PROMPT=0 to disable prompting
|
||||
// Check tar availability
|
||||
const [okTar, errTar] = await bash`tar --version`;
|
||||
const hasTar = !errTar;
|
||||
|
||||
// Disable interactive git prompts
|
||||
process.env.GIT_TERMINAL_PROMPT = 0;
|
||||
|
||||
const repoUrl = "https://github.com/meteor/performance";
|
||||
const branch = "v3.3.0";
|
||||
|
||||
let tarFailed = false;
|
||||
|
||||
// If tar is available, prefer tar-based extraction
|
||||
if (hasTar) {
|
||||
const tempDir = "/tmp/meteor-performance-benchmark-suite";
|
||||
const tarCommand = [
|
||||
`rm -rf ${tempDir}`,
|
||||
`git clone --no-checkout --depth 1 --filter=tree:0 --sparse --progress --branch ${branch} --single-branch ${repoUrl} ${tempDir}`,
|
||||
`cd ${tempDir}`,
|
||||
`git sparse-checkout init --cone`,
|
||||
`git sparse-checkout set scripts`,
|
||||
`git checkout ${branch}`,
|
||||
`mkdir -p ${profilingPath}/scripts`,
|
||||
`tar -czf /tmp/scripts.tar.gz -C ./scripts .`,
|
||||
`tar -xzf /tmp/scripts.tar.gz -C ${profilingPath}/scripts`,
|
||||
`rm -rf ${tempDir}`,
|
||||
`rm -f /tmp/scripts.tar.gz`
|
||||
].join(" && ");
|
||||
|
||||
const [okTarClone, errTarClone] = await bash`${tarCommand}`;
|
||||
if (!errTarClone) {
|
||||
Console.info("Meteor profiling suite cloned to: " + Console.path(profilingPath));
|
||||
return;
|
||||
} else {
|
||||
Console.warn("Tar-based cloning failed. Will attempt standard git clone...");
|
||||
tarFailed = errTarClone;
|
||||
}
|
||||
} else {
|
||||
Console.warn("Tar not available. Will use standard git clone...");
|
||||
}
|
||||
|
||||
// Fallback to plain git clone
|
||||
const gitCommand = [
|
||||
`mkdir -p ${profilingPath}`,
|
||||
`git clone --no-checkout --depth 1 --filter=tree:0 --sparse --progress --branch ${branch} --single-branch ${repoUrl} ${profilingPath}`,
|
||||
@@ -3433,18 +3485,22 @@ const setupBenchmarkSuite = async (profilingPath) => {
|
||||
`git sparse-checkout init --cone`,
|
||||
`git sparse-checkout set scripts`,
|
||||
`git checkout ${branch}`,
|
||||
`find ${profilingPath} -maxdepth 1 -type f -delete`,
|
||||
`find ${profilingPath} -maxdepth 1 -type f -delete`
|
||||
].join(" && ");
|
||||
const [, errClone] = await bash`${gitCommand}`;
|
||||
const errorMessage = errClone && typeof errClone === "string" ? errClone : errClone?.message;
|
||||
if (errorMessage && errorMessage.includes("Cloning into")) {
|
||||
throw new Error("error cloning benchmark");
|
||||
|
||||
const [okClone, errClone] = await bash`${gitCommand}`;
|
||||
if (errClone) {
|
||||
let combinedMessage = "Git clone failed.";
|
||||
if (tarFailed) {
|
||||
combinedMessage = `Tar-based cloning also failed:\n${tarFailed}\n\nGit fallback failed:\n${errClone}`;
|
||||
}
|
||||
throw new Error(combinedMessage);
|
||||
}
|
||||
// remove .git folder from the example
|
||||
|
||||
// Remove .git folder if present
|
||||
await files.rm_recursive_async(files.pathJoin(profilingPath, ".git"));
|
||||
Console.info(
|
||||
"Meteor profiling suite cloned to: " + Console.path(profilingPath),
|
||||
);
|
||||
|
||||
Console.info("Meteor profiling suite cloned to: " + Console.path(profilingPath));
|
||||
};
|
||||
|
||||
async function doBenchmarkCommand(options) {
|
||||
|
||||
@@ -492,7 +492,7 @@ Note that you must have mongosh installed to use this option.
|
||||
Options:
|
||||
--url, -U return a Mongo database URL
|
||||
--verbose, -v to show the errors that have occurred while connecting to the
|
||||
database
|
||||
database
|
||||
|
||||
Currently, this feature can only be used when developing locally.
|
||||
The opened Mongo shell connects to the current project's local
|
||||
@@ -816,7 +816,16 @@ Usage: meteor admin <command> [args]
|
||||
Rarely used commands for administering official Meteor services.
|
||||
|
||||
Commands:
|
||||
{{commands}}
|
||||
|
||||
make-bootstrap-tarballs
|
||||
recommend-release
|
||||
change-homepage
|
||||
set-unmigrated
|
||||
set-banners
|
||||
list-organizations
|
||||
members
|
||||
set-latest-readme
|
||||
get-machine
|
||||
|
||||
See 'meteor help admin <command>' for details on an admin command.
|
||||
|
||||
@@ -875,12 +884,12 @@ for replacing the names, we offer $$PascalName$$, $$camelName$$, $$name$$.
|
||||
This is a MeteorJS project command.
|
||||
|
||||
Options:
|
||||
--help Show help.
|
||||
--path The path to the folder where the files will be generated. Default is the current folder.
|
||||
--templatePath Path to the template file check https://docs.meteor.com/commandline.html#meteorgenerate-templating for more info.
|
||||
--replaceFn Replace function to replace the names in the template. Check https://docs.meteor.com/commandline.html#meteorgenerate-templating for more info.
|
||||
--methods Generate methods.
|
||||
--publications Generate publications.
|
||||
--help Show help.
|
||||
--path The path to the folder where the files will be generated. Default is the current folder.
|
||||
--templatePath Path to the template file check https://docs.meteor.com/commandline.html#meteorgenerate-templating for more info.
|
||||
--replaceFn Replace function to replace the names in the template. Check https://docs.meteor.com/commandline.html#meteorgenerate-templating for more info.
|
||||
--methods Generate methods.
|
||||
--publications Generate publications.
|
||||
|
||||
|
||||
>>> publish-release
|
||||
|
||||
6
tools/cordova/index.js
vendored
6
tools/cordova/index.js
vendored
@@ -13,11 +13,11 @@ export const CORDOVA_ARCH = "web.cordova";
|
||||
|
||||
export const CORDOVA_PLATFORMS = ['ios', 'android'];
|
||||
|
||||
const CORDOVA_ANDROID_VERSION = "13.0.0";
|
||||
const CORDOVA_ANDROID_VERSION = "14.0.1";
|
||||
|
||||
export const CORDOVA_DEV_BUNDLE_VERSIONS = {
|
||||
'cordova-lib': '12.0.1',
|
||||
'cordova-common': '5.0.0',
|
||||
'cordova-lib': '12.0.2',
|
||||
'cordova-common': '5.0.1',
|
||||
'cordova-create': '2.0.0',
|
||||
'cordova-registry-mapper': '1.1.15',
|
||||
'cordova-android': CORDOVA_ANDROID_VERSION,
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
import { wrap } from "optimism";
|
||||
const { compile: reifyCompile } = require("@meteorjs/reify/lib/compiler");
|
||||
const { parse: reifyAcornParse } = require("@meteorjs/reify/lib/parsers/acorn");
|
||||
const { parse: reifyBabelParse } = require("@meteorjs/reify/lib/parsers/babel");
|
||||
|
||||
import Resolver, { Resolution } from "./resolver";
|
||||
import LRUCache from 'lru-cache';
|
||||
@@ -87,14 +88,32 @@ const reifyCompileWithCache = Profile("reifyCompileWithCache", wrap(function (
|
||||
}
|
||||
|
||||
const isLegacy = isLegacyArch(bundleArch);
|
||||
let result = reifyCompile(stripHashBang(source), {
|
||||
parse: reifyAcornParse,
|
||||
const reifyOptions = {
|
||||
generateLetDeclarations: !isLegacy,
|
||||
avoidModernSyntax: isLegacy,
|
||||
enforceStrictMode: false,
|
||||
dynamicImport: true,
|
||||
ast: false,
|
||||
}).code;
|
||||
};
|
||||
|
||||
let result;
|
||||
try {
|
||||
// First attempt: use Acorn
|
||||
result = reifyCompile(stripHashBang(source), {
|
||||
...reifyOptions,
|
||||
parse: reifyAcornParse,
|
||||
}).code;
|
||||
} catch (acornError) {
|
||||
// Fallback: use Babel parser
|
||||
// acorn may throw SyntaxError due to the lack of support for
|
||||
// some features, but babel should still be able to parse the file
|
||||
// For example, acorn don’t support JSX, only with acorn-jsx,
|
||||
// but it isn’t included in Reify.
|
||||
result = reifyCompile(stripHashBang(source), {
|
||||
...reifyOptions,
|
||||
parse: reifyBabelParse,
|
||||
}).code;
|
||||
}
|
||||
|
||||
if (cacheFilePath) {
|
||||
Promise.resolve().then(
|
||||
|
||||
@@ -1234,7 +1234,16 @@ Object.assign(exports.ProjectConstraintsFile.prototype, {
|
||||
constraint: constraintToAdd,
|
||||
trailingSpaceAndComment: ''
|
||||
};
|
||||
self._constraintLines.push(lineRecord);
|
||||
if (constraintToAdd.package === 'npm-mongo-legacy') {
|
||||
const mongoIdx = self._constraintLines.findIndex(lr => lr.constraint && lr.constraint.package === 'mongo');
|
||||
if (mongoIdx > -1) {
|
||||
self._constraintLines.splice(mongoIdx, 0, lineRecord);
|
||||
} else {
|
||||
self._constraintLines.push(lineRecord);
|
||||
}
|
||||
} else {
|
||||
self._constraintLines.push(lineRecord);
|
||||
}
|
||||
self._constraintMap[constraintToAdd.package] = lineRecord;
|
||||
self._modified = true;
|
||||
return;
|
||||
@@ -1878,18 +1887,14 @@ export class MeteorConfig {
|
||||
// General utility for querying the "meteor" section of package.json.
|
||||
// TODO Implement an API for setting these values?
|
||||
get(...keys) {
|
||||
let config = this._ensureInitialized();
|
||||
let filteredConfig = keys.length ? {} : config;
|
||||
if (config) {
|
||||
keys.every(key => {
|
||||
if (config && _.has(config, key)) {
|
||||
filteredConfig = config[key];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return filteredConfig;
|
||||
}
|
||||
const config = this._ensureInitialized();
|
||||
if (!config) return undefined;
|
||||
|
||||
return keys.reduce((cur, key) => {
|
||||
return (cur != null && _.has(cur, key))
|
||||
? cur[key]
|
||||
: undefined;
|
||||
}, config);
|
||||
}
|
||||
|
||||
getNodeModulesToRecompileByArch() {
|
||||
|
||||
@@ -48,13 +48,15 @@ module.exports = function enable ({ cachePath, createLoader = true } = {}) {
|
||||
|
||||
const reifyVersion = require("@meteorjs/reify/package.json").version;
|
||||
const reifyAcornParse = require("@meteorjs/reify/lib/parsers/acorn").parse;
|
||||
const reifyBabelParse = require("@meteorjs/reify/lib/parsers/babel").parse;
|
||||
const reifyCompile = require("@meteorjs/reify/lib/compiler").compile;
|
||||
|
||||
function compileContent (content) {
|
||||
let identical = true;
|
||||
|
||||
let result;
|
||||
try {
|
||||
const result = reifyCompile(content, {
|
||||
result = reifyCompile(content, {
|
||||
parse: reifyAcornParse,
|
||||
generateLetDeclarations: false,
|
||||
ast: false,
|
||||
@@ -63,9 +65,20 @@ module.exports = function enable ({ cachePath, createLoader = true } = {}) {
|
||||
identical = false;
|
||||
content = result.code;
|
||||
}
|
||||
} finally {
|
||||
return { content, identical };
|
||||
} catch (acornError) {
|
||||
// Fallback: Babel
|
||||
result = reifyCompile(content, {
|
||||
parse: reifyBabelParse,
|
||||
generateLetDeclarations: false,
|
||||
ast: false,
|
||||
});
|
||||
if (!result.identical) {
|
||||
identical = false;
|
||||
content = result.code;
|
||||
}
|
||||
}
|
||||
|
||||
return { content, identical };
|
||||
}
|
||||
|
||||
const _compile = Mp._compile;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"@apollo/client": "^3.9.2",
|
||||
"@apollo/server": "^4.10.0",
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"graphql": "^16.8.1",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"jquery": "^3.7.1",
|
||||
"meteor-node-stubs": "^1.2.12"
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"@chakra-ui/icons": "^1.1.7",
|
||||
"@chakra-ui/react": "^1.8.8",
|
||||
"@emotion/react": "^11.9.3",
|
||||
|
||||
@@ -7,10 +7,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"jquery": "^3.7.1",
|
||||
"meteor-node-stubs": "^1.2.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0"
|
||||
},
|
||||
"meteor": {
|
||||
"mainModule": {
|
||||
"client": "client/main.js",
|
||||
"server": "server/main.js"
|
||||
},
|
||||
"modern": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12"
|
||||
},
|
||||
"meteor": {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Entrypoint for the Meteor client
|
||||
*
|
||||
* Generally, this file can be left empty. Vite will add imports for
|
||||
* lazy-loaded Meteor packages to this file to ensure they aren't omitted from
|
||||
* the final production bundle.
|
||||
*
|
||||
* Use ./main.js as the primary entrypoint for your client code to take full
|
||||
* advantage of Vite's plugin and build system.
|
||||
*
|
||||
* This can also be a good place to put code that you don't want Vite to
|
||||
* process, for example, if you run into a compatibility issue or need to use
|
||||
* nested imports which Vite doesn't support.
|
||||
*/
|
||||
1
tools/static-assets/skel-solid/client/main.js
Normal file
1
tools/static-assets/skel-solid/client/main.js
Normal file
@@ -0,0 +1 @@
|
||||
import '../imports/ui/main';
|
||||
@@ -1 +0,0 @@
|
||||
// main entry point is in imports/ui/main.jsx
|
||||
@@ -2,6 +2,7 @@
|
||||
import { render } from 'solid-js/web';
|
||||
import { App } from './App';
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import './main.css';
|
||||
|
||||
Meteor.startup(() => {
|
||||
render(() => <App/>, document.getElementById('root'));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"picocolors": "^1.1.1",
|
||||
"solid-js": "^1.9.4"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Entrypoint for the Meteor server
|
||||
* Generally, this file can be left empty. Vite will add imports for your app's
|
||||
* server bundle here during both development and production build.
|
||||
*
|
||||
* Use ./main.js as the primary entrypoint for your app to take full advantage
|
||||
* of Vite's plugin and build system.
|
||||
*
|
||||
* This can also be a good place to put code that you don't want Vite to
|
||||
* process, for example, if you run into a compatibility issue or need to use
|
||||
* nested imports.
|
||||
*/
|
||||
@@ -8,7 +8,7 @@ export default defineConfig({
|
||||
solidPlugin(),
|
||||
solidSvg({ defaultExport: 'component' }),
|
||||
meteor({
|
||||
clientEntry: 'imports/ui/main.jsx',
|
||||
clientEntry: 'client/main.js',
|
||||
serverEntry: 'server/main.js',
|
||||
enableExperimentalFeatures: true,
|
||||
stubValidation: {
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"svelte": "^3.59.2"
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"postcss": "^8.4.12",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Entrypoint for the Meteor client
|
||||
*
|
||||
* Generally, this file can be left empty. Vite will add imports for
|
||||
* lazy-loaded Meteor packages to this file to ensure they aren't omitted from
|
||||
* the final production bundle.
|
||||
*
|
||||
* Use ./main.js as the primary entrypoint for your client code to take full
|
||||
* advantage of Vite's plugin and build system.
|
||||
*
|
||||
* This can also be a good place to put code that you don't want Vite to
|
||||
* process, for example, if you run into a compatibility issue or need to use
|
||||
* nested imports which Vite doesn't support.
|
||||
*/
|
||||
@@ -1,3 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -1 +1 @@
|
||||
// main entry point is in imports/ui/main.jsx
|
||||
import '../imports/ui/main'
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import AppMenu from './AppMenu.vue'
|
||||
import AppMenu from './components/AppMenu.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
1
tools/static-assets/skel-vue/imports/ui/main.css
Normal file
1
tools/static-assets/skel-vue/imports/ui/main.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
@@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'
|
||||
import { createApp } from 'vue'
|
||||
import { VueMeteor } from 'vue-meteor-tracker'
|
||||
|
||||
import './main.css'
|
||||
import App from './App.vue'
|
||||
import { router } from './router'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Home from './Home.vue'
|
||||
import About from './About.vue'
|
||||
import Home from './views/Home.vue'
|
||||
import About from './views/About.vue'
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import Hello from './Hello.vue'
|
||||
import Info from './Info.vue'
|
||||
import Hello from '../components/Hello.vue'
|
||||
import Info from '../components/Info.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -10,12 +10,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"@swc/helpers": "^0.5.17",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"vue": "^3.3.9",
|
||||
"vue-meteor-tracker": "^3.0.0-beta.7",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"meteor": {
|
||||
"modern": true,
|
||||
"mainModule": {
|
||||
"client": "client/entry-meteor.js",
|
||||
"server": "server/entry-meteor.js"
|
||||
@@ -24,11 +26,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/meteor": "^2.9.7",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"meteor-vite": "^3.2.1",
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"vite": "^6.0.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Entrypoint for the Meteor server
|
||||
* Generally, this file can be left empty. Vite will add imports for your app's
|
||||
* server bundle here during both development and production build.
|
||||
*
|
||||
* Use ./main.js as the primary entrypoint for your app to take full advantage
|
||||
* of Vite's plugin and build system.
|
||||
*
|
||||
* This can also be a good place to put code that you don't want Vite to
|
||||
* process, for example, if you run into a compatibility issue or need to use
|
||||
* nested imports.
|
||||
*/
|
||||
@@ -1,8 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./imports/ui/**/*.{vue,js,ts,jsx,tsx}', './client/*.html'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { meteor } from 'meteor-vite/plugin';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
tailwindcss(),
|
||||
meteor({
|
||||
clientEntry: 'imports/ui/main.js',
|
||||
clientEntry: 'client/main.js',
|
||||
serverEntry: 'server/main.js',
|
||||
enableExperimentalFeatures: true,
|
||||
stubValidation: {
|
||||
@@ -199,3 +199,71 @@ selftest.define("testModule", async function () {
|
||||
|
||||
await run.stop();
|
||||
});
|
||||
|
||||
async function writeModernConfig(s, run, modernConfig, errorPattern) {
|
||||
const json = JSON.parse(s.read("package.json"));
|
||||
|
||||
json.meteor = {
|
||||
// Make sure the tests.js module is always loaded eagerly.
|
||||
testModule: "tests.js"
|
||||
};
|
||||
|
||||
if (typeof modernConfig === "undefined") {
|
||||
delete json.meteor.modern;
|
||||
} else {
|
||||
json.meteor.modern = modernConfig;
|
||||
}
|
||||
|
||||
s.write("package.json", JSON.stringify(json, null, 2) + "\n");
|
||||
|
||||
run.waitSecs(10);
|
||||
|
||||
if (errorPattern instanceof RegExp) {
|
||||
await run.match(errorPattern);
|
||||
} else {
|
||||
run.forbid(" 0 passing ");
|
||||
await run.match("SERVER FAILURES: 0");
|
||||
await run.match("CLIENT FAILURES: 0");
|
||||
}
|
||||
}
|
||||
|
||||
selftest.define("modernConfig", async function () {
|
||||
const s = new Sandbox();
|
||||
await s.init();
|
||||
|
||||
await s.createApp("app-config-modernConfig", "app-config");
|
||||
await s.cd("app-config-modernConfig");
|
||||
|
||||
// For meteortesting:mocha to work we must set test broswer driver
|
||||
// See https://github.com/meteortesting/meteor-mocha
|
||||
s.set("TEST_BROWSER_DRIVER", "puppeteer");
|
||||
|
||||
const run = s.run(
|
||||
"test",
|
||||
"--full-app",
|
||||
"--driver-package", "meteortesting:mocha"
|
||||
);
|
||||
|
||||
run.waitSecs(60);
|
||||
await run.match("App running at");
|
||||
|
||||
function check(modernConfig) {
|
||||
return writeModernConfig(s, run, modernConfig);
|
||||
}
|
||||
|
||||
// Test with modern disabled
|
||||
await check(false);
|
||||
|
||||
// Test with modern enabled
|
||||
await check(true);
|
||||
|
||||
// Test with combined options
|
||||
await check({
|
||||
transpiler: true,
|
||||
watcher: true,
|
||||
webArchOnly: true,
|
||||
minifier: true,
|
||||
});
|
||||
|
||||
await run.stop();
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.5",
|
||||
"config": "file:../config-package",
|
||||
"meteor-node-stubs": "^1.2.12",
|
||||
"react": "^18.3.1"
|
||||
},
|
||||
|
||||
@@ -38,7 +38,7 @@ selftest.define("help", async function () {
|
||||
var checkSubcommandList = async function (run) {
|
||||
await run.read("Usage: meteor admin <command>");
|
||||
await run.match("Commands:");
|
||||
await run.match(/recommend-release\s*Recommend a previously published/);
|
||||
await run.match(/\s*recommend-release\s*/);
|
||||
await run.expectExit(0);
|
||||
};
|
||||
await checkCommandHelp(s.run("create", "--help"));
|
||||
|
||||
@@ -188,9 +188,35 @@ selftest.define("modern build stack - transpiler boolean-like options", async fu
|
||||
const s = new Sandbox();
|
||||
await s.init();
|
||||
|
||||
s.mkdir("config-package");
|
||||
s.cd("config-package");
|
||||
|
||||
s.write(
|
||||
"package.json",
|
||||
JSON.stringify({
|
||||
name: "config",
|
||||
version: "1.2.3",
|
||||
"private": true,
|
||||
main: "index.js"
|
||||
}, null, 2) + "\n"
|
||||
);
|
||||
|
||||
s.write(
|
||||
"index.js",
|
||||
"exports.id = module.id;\n"
|
||||
);
|
||||
|
||||
s.cd(s.home);
|
||||
|
||||
await s.createApp("modern", "modern");
|
||||
await s.cd("modern");
|
||||
|
||||
s.append(
|
||||
"server/main.js",
|
||||
`if (require('config')) {
|
||||
console.log('Loaded NPM package "config"', require('config').id);
|
||||
}`);
|
||||
|
||||
process.env.METEOR_DISABLE_COLORS = true;
|
||||
|
||||
await writeModernConfig(s, {
|
||||
@@ -204,14 +230,18 @@ selftest.define("modern build stack - transpiler boolean-like options", async fu
|
||||
run.waitSecs(waitToStart);
|
||||
await run.match("App running at");
|
||||
|
||||
/* check appended NPM package require */
|
||||
await run.match(/Loaded NPM package "config"/, false, true);
|
||||
|
||||
/* check verbose logs */
|
||||
await run.match(/SWC Config/, false, true);
|
||||
await run.match(/SWC Custom Config/, false, true);
|
||||
await run.match(/SWC Legacy Config/, false, true);
|
||||
await run.match(/Meteor Config/, false, true);
|
||||
|
||||
/* check transpiler options */
|
||||
await run.match(/\[Transpiler] Used SWC.*\(app\)/, false, true);
|
||||
await run.match(/\[Transpiler] Used SWC.*\(package\)/, false, true);
|
||||
run.forbid(/\[Transpiler] Used SWC.*\(node_modules\)/, false, true);
|
||||
|
||||
await writeModernConfig(s, {
|
||||
transpiler: {
|
||||
@@ -229,6 +259,20 @@ selftest.define("modern build stack - transpiler boolean-like options", async fu
|
||||
});
|
||||
await run.match(/\[Transpiler] Used Babel.*\(package\)/, false, true);
|
||||
|
||||
await writeConfig(s, {
|
||||
modern: {
|
||||
transpiler: {
|
||||
verbose: true,
|
||||
},
|
||||
},
|
||||
nodeModules: {
|
||||
recompile: {
|
||||
config: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await run.match(/\[Transpiler] Used SWC.*\(node_modules\)/, false, true);
|
||||
|
||||
await run.stop();
|
||||
|
||||
process.env.METEOR_MODERN = currentMeteorModern;
|
||||
@@ -241,9 +285,34 @@ selftest.define("modern build stack - transpiler string-like options", async fun
|
||||
const s = new Sandbox();
|
||||
await s.init();
|
||||
|
||||
s.mkdir("config-package");
|
||||
s.cd("config-package");
|
||||
|
||||
s.write(
|
||||
"package.json",
|
||||
JSON.stringify({
|
||||
name: "config",
|
||||
version: "1.2.3",
|
||||
"private": true,
|
||||
main: "index.js"
|
||||
}, null, 2) + "\n"
|
||||
);
|
||||
|
||||
s.write(
|
||||
"index.js",
|
||||
"exports.id = module.id;\n"
|
||||
);
|
||||
|
||||
s.cd(s.home);
|
||||
|
||||
await s.createApp("modern", "modern");
|
||||
await s.cd("modern");
|
||||
|
||||
s.append(
|
||||
"server/main.js",
|
||||
`import { id } from 'config';
|
||||
console.log('Loaded NPM package "config"', require('config').id);`);
|
||||
|
||||
process.env.METEOR_DISABLE_COLORS = true;
|
||||
|
||||
await writeModernConfig(s, {
|
||||
@@ -257,14 +326,18 @@ selftest.define("modern build stack - transpiler string-like options", async fun
|
||||
run.waitSecs(waitToStart);
|
||||
await run.match("App running at");
|
||||
|
||||
/* check appended NPM package imported */
|
||||
await run.match(/Loaded NPM package "config"/, false, true);
|
||||
|
||||
/* check verbose logs */
|
||||
await run.match(/SWC Config/, false, true);
|
||||
await run.match(/SWC Custom Config/, false, true);
|
||||
await run.match(/SWC Legacy Config/, false, true);
|
||||
await run.match(/Meteor Config/, false, true);
|
||||
|
||||
/* check transpiler options */
|
||||
await run.match(/\[Transpiler] Used SWC.*\(app\)/, false, true);
|
||||
await run.match(/\[Transpiler] Used SWC.*\(package\)/, false, true);
|
||||
run.forbid(/\[Transpiler] Used SWC.*\(node_modules\)/, false, true);
|
||||
|
||||
await writeModernConfig(s, {
|
||||
transpiler: {
|
||||
@@ -282,6 +355,20 @@ selftest.define("modern build stack - transpiler string-like options", async fun
|
||||
});
|
||||
await run.match(/\[Transpiler] Used Babel.*\(package\)/, false, true);
|
||||
|
||||
await writeConfig(s, {
|
||||
modern: {
|
||||
transpiler: {
|
||||
verbose: true,
|
||||
},
|
||||
},
|
||||
nodeModules: {
|
||||
recompile: {
|
||||
config: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await run.match(/\[Transpiler] Used SWC.*\(node_modules\)/, false, true);
|
||||
|
||||
await run.stop();
|
||||
|
||||
process.env.METEOR_MODERN = currentMeteorModern;
|
||||
|
||||
@@ -73,7 +73,7 @@ $env:PATH += ";%JAVA_HOME%\bin"
|
||||
|
||||
For Android builds, you will need the Android SDK. You can install it via [Android Studio](https://developer.android.com/studio).
|
||||
|
||||
Once Android Studio is installed, go to **SDK Manager** and install the required SDK packages. The minimum required version is Android SDK 34. Install the `Android SDK Command-line Tools (latest)` as well.
|
||||
Once Android Studio is installed, go to **SDK Manager** and install the required SDK packages. The minimum required version is Android SDK 35. Install the `Android SDK Command-line Tools (latest)` as well.
|
||||
|
||||
Ensure `ANDROID_HOME` environment variable is set by adding it to `~/.bashrc` or `~/.zshrc` :
|
||||
|
||||
|
||||
@@ -100,30 +100,41 @@ Most apps will benefit just by enabling `modern: true`. Most Meteor packages sho
|
||||
|
||||
> Remember to turn off verbosity when you're done with optimizations.
|
||||
|
||||
## Externalize SWC Helpers
|
||||
|
||||
By default, SWC inlines transformation helpers (e.g. _extends, _objectSpread) into every file that uses them. While this ensures compatibility out of the box, it can lead to duplicated code across your bundles increasing bundle size.
|
||||
|
||||
To centralize these helpers and keep your client builds lean, you can add the `@swc/helpers` in your app project.
|
||||
|
||||
``` bash
|
||||
meteor npm install --save @swc/helpers
|
||||
```
|
||||
|
||||
> This package is installed by default for new apps.
|
||||
|
||||
Meteor’s build tool comes pre-configured to externalize SWC helpers for you, no extra setup or .swcrc tweaks are needed. As soon as you install @swc/helpers, Meteor’s SWC pipeline will automatically emit imports for shared helper functions rather than inlining them, ensuring your app ships each helper just once.
|
||||
|
||||
## Custom .swcrc
|
||||
|
||||
You can use `.swcrc` config in the root of your project to describe specific [SWC plugins](https://github.com/swc-project/plugins) there, that will be applied to compile the entire files of your project.
|
||||
|
||||
You can also configure other options using the `.swcrc` format. One common case is when your project uses `.js` files for React code. React typically uses `.jsx` for components. We still recommend following that convention for compatibility, but if you prefer `.js`, you can provide a custom `.swcrc` like this:
|
||||
|
||||
``` json
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"jsx": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> You can also configure it for TypeScript, make sure to set `"syntax": "typescript"` and `"tsx": true` instead.
|
||||
|
||||
This overrides Meteor's internal SWC config to apply your settings, ensuring SWC processes `.js` or `.ts` files with React components without falling back to Babel.
|
||||
You can also configure other options using the `.swcrc` format. For custom SWC configs, see the [SWC configuration API](https://swc.rs/docs/configuration/compilation).
|
||||
|
||||
Use `swc.config.js` in your project root for dynamic configuration. Meteor will import and apply the SWC config automatically. This lets you choose a config based on environment variables or other runtime factors.
|
||||
|
||||
Explore additional custom SWC configs, including ["Import Aliases"](#import-aliases) and ["React Runtime"](#react-runtime).
|
||||
You can also review these migration topics that use custom `.swcrc` configs:
|
||||
|
||||
- [Import Aliases](#import-aliases)
|
||||
- [JSX Syntax in JS files](#jsx-syntax-in-js-files)
|
||||
- [React Runtime](#react-runtime)
|
||||
- [Transform Imports](#transform-imports)
|
||||
- [Private Properties](#private-properties)
|
||||
|
||||
:::warning
|
||||
The standard name for the SWC configuration file is [`.swcrc`](https://swc.rs/docs/configuration/compilation).
|
||||
|
||||
Using as an extension, such as `config.swcrc`, won’t work.
|
||||
:::
|
||||
|
||||
## Config API
|
||||
|
||||
@@ -252,11 +263,32 @@ SWC resolve aliases for imports correctly, but require calls won’t. For requir
|
||||
|
||||
SWC has no [module-resolver plugin like Babel’s](https://www.npmjs.com/package/babel-plugin-module-resolver) yet, which could affect require calls in the future.
|
||||
|
||||
### JSX Syntax in JS files
|
||||
|
||||
When migrating your app to use SWC, Meteor SWC falls back to Babel if you include JSX in `.js` files, since JSX is only recognized in `.jsx` files.
|
||||
|
||||
To enable JSX in `.js` files, create a [`.swcrc`](#custom-swcrc) file with this config:
|
||||
|
||||
``` json
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"jsx": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> For TypeScript, set "syntax": "typescript" and "tsx": true instead.
|
||||
|
||||
This overrides Meteor’s internal SWC config so SWC handles `.js` and `.ts` files with React components instead of falling back to Babel.
|
||||
|
||||
### React Runtime
|
||||
|
||||
Meteor Babel lets you skip importing React in your files by using the [`@babel/plugin-transform-react-jsx`](https://www.npmjs.com/package/@babel/plugin-transform-react-jsx) runtime config.
|
||||
|
||||
To use the same config in SWC, add it to your [.swcrc](#custom-swcrc):
|
||||
To use the same config in SWC, add it to your [`.swcrc`](#custom-swcrc):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -270,6 +302,79 @@ To use the same config in SWC, add it to your [.swcrc](#custom-swcrc):
|
||||
}
|
||||
```
|
||||
|
||||
### Transform Imports
|
||||
|
||||
You might have used Meteor Babel with the [`babel-plugin-transform-imports`](https://www.npmjs.com/package/babel-plugin-transform-imports) plugin to rewrite imports in your app.
|
||||
|
||||
SWC offers a similar plugin: [`@swc/plugin-transform-imports`](https://www.npmjs.com/package/@swc/plugin-transform-imports).
|
||||
|
||||
To switch to SWC, install the plugin:
|
||||
|
||||
```bash
|
||||
meteor npm install -D @swc/plugin-transform-imports
|
||||
```
|
||||
|
||||
and add it to your [`.swcrc`](#custom-swcrc):
|
||||
|
||||
```json
|
||||
{
|
||||
"jsc": {
|
||||
"experimental": {
|
||||
"plugins": [
|
||||
[
|
||||
"@swc/plugin-transform-imports",
|
||||
{
|
||||
"lodash": {
|
||||
"transform": "lodash/{{member}}",
|
||||
"preventFullImport": true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This tells SWC to replace, for example,
|
||||
|
||||
``` javascript
|
||||
import { map } from "lodash"
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
``` javascript
|
||||
import map from "lodash/map"
|
||||
```
|
||||
|
||||
avoiding full-package imports and reducing bundle size.
|
||||
|
||||
You can use advanced import transformations. [See the test suite for examples.](https://github.com/swc-project/plugins/blob/main/packages/transform-imports/__tests__/wasm.test.ts#L12-L63)
|
||||
|
||||
|
||||
### Private Properties
|
||||
|
||||
SWC supports many of the most modern JS systax features, including private class properties, which Meteor Babel doesn’t.
|
||||
|
||||
Just by enabling SWC, Meteor will parse properly code like:
|
||||
|
||||
``` javascript
|
||||
class ClassWithPrivate {
|
||||
#privateField;
|
||||
#privateFieldWithInitializer = 42;
|
||||
|
||||
#privateMethod() {}
|
||||
|
||||
static #privateStaticField;
|
||||
static #privateStaticFieldWithInitializer = 42;
|
||||
|
||||
static #privateStaticMethod() {}
|
||||
}
|
||||
```
|
||||
|
||||
You can opt-out of [private properties in SWC options with "privateMethod" setting](https://swc.rs/docs/configuration/compilation#ecmascript) with the [`.swcrc`](#custom-swcrc) file.
|
||||
|
||||
## Troubleshotting
|
||||
|
||||
If you run into issues, try `meteor reset` or delete the `.meteor/local` folder in the project root.
|
||||
|
||||
@@ -533,7 +533,8 @@ password-based users or from an external service login flow. `options` may come
|
||||
from an untrusted client so make sure to validate any values you read from
|
||||
it. The `user` argument is created on the server and contains a
|
||||
proposed user object with all the automatically generated fields
|
||||
required for the user to log in, including the `_id`.
|
||||
required for the user to log in, including a temporary `_id` (the final _id is
|
||||
generated upon document insertion and not available in this function).
|
||||
|
||||
The function should return the user document (either the one passed in or a
|
||||
newly-created object) with whatever modifications are desired. The returned
|
||||
|
||||
@@ -914,6 +914,7 @@ const handle = await cursor.observeChangesAsync({
|
||||
setTimeout(() => handle.stop(), 5000);
|
||||
```
|
||||
|
||||
<ApiBox name="Mongo.getCollection" />
|
||||
<ApiBox name="Mongo.ObjectID" />
|
||||
|
||||
|
||||
|
||||
116
v3-docs/docs/generators/changelog/versions/3.3.1.md
Normal file
116
v3-docs/docs/generators/changelog/versions/3.3.1.md
Normal file
@@ -0,0 +1,116 @@
|
||||
## v3.3.1, no-date
|
||||
|
||||
### Highlights
|
||||
|
||||
- **MongoDB Driver Upgrades**
|
||||
- Upgraded core MongoDB driver to `6.16.0` to address latest issues reported [#13710](https://github.com/meteor/meteor/pull/13710)
|
||||
- Introduced `npm-mongo-legacy` to maintain compatibility with MongoDB 3.6 via `mongodb@6.9.0` [#13736](https://github.com/meteor/meteor/pull/13736)
|
||||
- Mitigated a cursor leak issue by synchronizing `next()` and `close()` operations [#13786](https://github.com/meteor/meteor/pull/13786)
|
||||
|
||||
- **Improved SWC integration**
|
||||
- Fixed edge cases in config cache invalidation [#13809](https://github.com/meteor/meteor/pull/13809)
|
||||
- Ensured `@swc/helpers` is consistently used for better bundle size and performance [#13820](https://github.com/meteor/meteor/pull/13820)
|
||||
- Updated to SWC `1.12.14` [#13851](https://github.com/meteor/meteor/pull/13851)
|
||||
|
||||
- **Tooling and Build System**
|
||||
- Fixed regression affecting rebuild behavior [#13810](https://github.com/meteor/meteor/pull/13810)
|
||||
- Addressed issues getting performance profiles in mounted volumes [#13827](https://github.com/meteor/meteor/pull/13827)
|
||||
- Fallback to Babel parser when Acorn fails to parse source code [#13844](https://github.com/meteor/meteor/pull/13844)
|
||||
|
||||
- **Mobile Support**
|
||||
- Upgraded Cordova platform to version 14 [#13837](https://github.com/meteor/meteor/pull/13837)
|
||||
|
||||
- **Developer Experience**
|
||||
- Added TypeScript types for `isModern` and `getMinimumBrowserVersions` functions [#13704](https://github.com/meteor/meteor/pull/13704)
|
||||
- Enhanced CLI help output and documented admin commands [#13826](https://github.com/meteor/meteor/pull/13826)
|
||||
|
||||
- **Vite Tooling**
|
||||
- Updated official Meteor + Vite skeletons [#13835](https://github.com/meteor/meteor/pull/13835)
|
||||
|
||||
- **Runtime & Dependencies**
|
||||
- Updated to Node.js `22.17.1` [#13853](https://github.com/meteor/meteor/pull/13853)
|
||||
- Bumped `meteor-node-stubs` to `1.2.21` [#13825](https://github.com/meteor/meteor/pull/13825)
|
||||
|
||||
All Merged PRs@[GitHub PRs 3.3.1](https://github.com/meteor/meteor/pulls?q=is%3Apr+is%3Amerged+base%3Arelease-3.3.1)
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
##### MongoDB Driver Upgrades
|
||||
|
||||
If you're using MongoDB 3.6 or earlier, install the new legacy package:
|
||||
|
||||
```bash
|
||||
meteor add npm-mongo-legacy
|
||||
```
|
||||
This will pin the MongoDB driver to 6.9.0 for compatibility.
|
||||
|
||||
If you’re on MongoDB 4+, the default [MongoDB driver 6.16.0](https://github.com/mongodb/node-mongodb-native/releases/tag/v6.16.0) is applied automatically.
|
||||
|
||||
Please migrate your database as soon as possible to MongoDB 5 onward, as [MongoDB driver 6.17.0](https://github.com/mongodb/node-mongodb-native/releases/tag/v6.17.0) will drop MongoDB 4 support. We’ll keep offering `npm-mongo-legacy` so you can keep getting Meteor updates with your existing MongoDB legacy version.
|
||||
|
||||
##### Cordova Upgrade
|
||||
|
||||
The Cordova platform has been upgraded to version 14. Refer to the [Cordova Changelog](https://cordova.apache.org/announcements/2025/03/26/cordova-android-14.0.0.html) for more details on the changes and migration steps.
|
||||
|
||||
#### Internal API changes
|
||||
|
||||
N/A
|
||||
|
||||
#### Migration Steps
|
||||
|
||||
Please run the following command to update your project:
|
||||
|
||||
```bash
|
||||
meteor update --release 3.3.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
While this is a patch release, Meteor 3.3, a recent minor update, introduced a modern build stack that’s now the default for new apps. Here’s how you can migrate to it.
|
||||
|
||||
**Add this to your `package.json` to enable the new modern build stack:**
|
||||
|
||||
```json
|
||||
"meteor": {
|
||||
"modern": true
|
||||
}
|
||||
```
|
||||
|
||||
Check the docs for help with the SWC migration, especially if your project uses many Babel plugins.
|
||||
|
||||
[Modern Transpiler: SWC docs](https://docs.meteor.com/about/modern-build-stack/transpiler-swc.html)
|
||||
|
||||
If you find any issues, please report them to the [Meteor issues tracker](https://github.com/meteor/meteor).
|
||||
|
||||
#### Bumped Meteor Packages
|
||||
|
||||
- babel-compiler@7.12.1-rc331.2
|
||||
- callback-hook@1.6.1-rc331.2
|
||||
- ecmascript@0.16.12-rc331.2
|
||||
- minifier-js@3.0.3-rc331.2
|
||||
- minimongo@2.0.3-rc331.2
|
||||
- modern-browsers@0.2.3-rc331.2
|
||||
- mongo@2.1.3-rc331.2
|
||||
- npm-mongo-legacy@6.9.0-rc331.2
|
||||
- npm-mongo@6.16.0-rc331.2
|
||||
- standard-minifier-js@3.1.1-rc331.2
|
||||
- tinytest@1.3.2-rc331.2
|
||||
- typescript@5.6.5-rc331.2
|
||||
- meteor-tool@3.3.1-rc.2
|
||||
|
||||
#### Bumped NPM Packages
|
||||
|
||||
- meteor-node-stubs@1.2.21
|
||||
|
||||
#### Special thanks to
|
||||
|
||||
✨✨✨
|
||||
|
||||
- [@nachocodoner](https://github.com/nachocodoner)
|
||||
- [@italojs](https://github.com/italojs)
|
||||
- [@StorytellerCZ](https://github.com/StorytellerCZ)
|
||||
- [@JorgenVatle](https://github.com/JorgenVatle)
|
||||
- [@welkinwong](https://github.com/welkinwong)
|
||||
- [@Saksham-Goel1107](https://github.com/Saksham-Goel1107)
|
||||
|
||||
✨✨✨
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
meteor_version: 3.3
|
||||
node_version: 22.16.0
|
||||
meteor_version: 3.3.1
|
||||
node_version: 22.17.1
|
||||
npm_version: 10.9.2
|
||||
---
|
||||
# Meteor 3.0 Migration Guide
|
||||
|
||||
Reference in New Issue
Block a user