Merge branch 'devel' into mongo/collection-extensions

This commit is contained in:
Italo José
2025-08-14 10:52:23 -03:00
committed by GitHub
99 changed files with 1544 additions and 579 deletions

View File

@@ -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

View File

@@ -4,7 +4,7 @@ dist: jammy
sudo: required
services: xvfb
node_js:
- "22.16.0"
- "22.17.0"
cache:
directories:
- ".meteor"

View File

@@ -8,6 +8,123 @@
[//]: # (go to meteor/docs/generators/changelog/docs)
## v3.3.1, 05-08-2025
### 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.18.0` and NPM `10.9.3` [#13877](https://github.com/meteor/meteor/pull/13877)
- 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 youre 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. Well 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 thats now the default for new apps. Heres 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
- callback-hook@1.6.1
- ecmascript@0.16.12
- minifier-js@3.0.3
- minimongo@2.0.3
- modern-browsers@0.2.3
- mongo@2.1.3
- npm-mongo-legacy@6.9.0
- npm-mongo@6.16.0
- standard-minifier-js@3.1.1
- tinytest@1.3.2
- typescript@5.6.5
- meteor-tool@3.3.1
#### 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)
✨✨✨
## v3.3.0, 2025-06-11
### Highlights

421
docs/package-lock.json generated
View File

@@ -4,16 +4,41 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/parser": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz",
"integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
"@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true
},
"@babel/helper-validator-identifier": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true
},
"@babel/parser": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"dev": true,
"requires": {
"@babel/types": "^7.28.0"
}
},
"@babel/types": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"dev": true,
"requires": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
}
},
"@jsdoc/salty": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.6.tgz",
"integrity": "sha512-aA+awb5yoml8TQ3CzI5Ue7sM3VMRC4l1zJJW4fgZ8OCL1wshJZhNzaf0PL85DSnOUw6QuFgeHGD/eq/xwwAF2g==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz",
"integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==",
"dev": true,
"requires": {
"lodash": "^4.17.21"
@@ -26,31 +51,31 @@
"dev": true
},
"@meteorjs/meteor-theme-hexo": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/@meteorjs/meteor-theme-hexo/-/meteor-theme-hexo-2.0.8.tgz",
"integrity": "sha512-LQIFN05wBMjX7SXgW5CFVTfolDWMuknoypwQ0czl/44LYRBR4/LYZUgX6c+1vLjloJb+5+2HTvMGlVN9Wo1MKA==",
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/@meteorjs/meteor-theme-hexo/-/meteor-theme-hexo-2.0.9.tgz",
"integrity": "sha512-8ncpsN8MAe1F7cJBtcPgH3JE36WV03oo5mPkA1yMdRmv2kq8AQpKnd4ok0U1cr5NIIBMupLtsHDLm8PhTQcUdw==",
"dev": true
},
"@types/linkify-it": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz",
"integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
"dev": true
},
"@types/markdown-it": {
"version": "12.2.3",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
"integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
"dev": true,
"requires": {
"@types/linkify-it": "*",
"@types/mdurl": "*"
"@types/linkify-it": "^5",
"@types/mdurl": "^2"
}
},
"@types/mdurl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz",
"integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
"dev": true
},
"JSONStream": {
@@ -75,16 +100,6 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"dev": true,
"requires": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
}
},
"acorn": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
@@ -239,9 +254,9 @@
"optional": true
},
"aws4": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
"dev": true,
"optional": true
},
@@ -479,9 +494,9 @@
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
@@ -506,9 +521,9 @@
"dev": true
},
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true
},
"cache-base": {
@@ -537,17 +552,38 @@
}
},
"call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dev": true,
"optional": true,
"requires": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
"set-function-length": "^1.2.2"
}
},
"call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"optional": true,
"requires": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
}
},
"call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
"optional": true,
"requires": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
}
},
"camel-case": {
@@ -801,18 +837,26 @@
}
},
"compression": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"dev": true,
"requires": {
"accepts": "~1.3.5",
"bytes": "3.0.0",
"compressible": "~2.0.16",
"bytes": "3.1.2",
"compressible": "~2.0.18",
"debug": "2.6.9",
"on-headers": "~1.0.2",
"safe-buffer": "5.1.2",
"negotiator": "~0.6.4",
"on-headers": "~1.1.0",
"safe-buffer": "5.2.1",
"vary": "~1.1.2"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
}
}
},
"concat-map": {
@@ -1040,6 +1084,18 @@
"domelementtype": "1"
}
},
"dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"optional": true,
"requires": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -1092,14 +1148,11 @@
}
},
"es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"optional": true,
"requires": {
"get-intrinsic": "^1.2.4"
}
"optional": true
},
"es-errors": {
"version": "1.3.0",
@@ -1108,6 +1161,16 @@
"dev": true,
"optional": true
},
"es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true,
"optional": true,
"requires": {
"es-errors": "^1.3.0"
}
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1323,17 +1386,33 @@
"dev": true
},
"get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"optional": true,
"requires": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
}
},
"get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"optional": true,
"requires": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
}
},
"get-value": {
@@ -1401,14 +1480,11 @@
"dev": true
},
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"optional": true,
"requires": {
"get-intrinsic": "^1.1.3"
}
"optional": true
},
"graceful-fs": {
"version": "4.2.11",
@@ -1480,17 +1556,10 @@
"es-define-property": "^1.0.0"
}
},
"has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"optional": true
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"optional": true
},
@@ -2390,9 +2459,9 @@
},
"dependencies": {
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
@@ -2416,12 +2485,6 @@
"striptags": "^3.1.1"
}
},
"marked": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
"dev": true
},
"strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -2652,12 +2715,12 @@
"dev": true
},
"is-core-module": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
"requires": {
"hasown": "^2.0.0"
"hasown": "^2.0.2"
}
},
"is-data-descriptor": {
@@ -2839,21 +2902,21 @@
"optional": true
},
"jsdoc": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz",
"integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
"integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==",
"dev": true,
"requires": {
"@babel/parser": "^7.20.15",
"@jsdoc/salty": "^0.2.1",
"@types/markdown-it": "^12.2.3",
"@types/markdown-it": "^14.1.1",
"bluebird": "^3.7.2",
"catharsis": "^0.9.0",
"escape-string-regexp": "^2.0.0",
"js2xmlparser": "^4.0.2",
"klaw": "^3.0.0",
"markdown-it": "^12.3.2",
"markdown-it-anchor": "^8.4.1",
"markdown-it": "^14.1.0",
"markdown-it-anchor": "^8.6.7",
"marked": "^4.0.10",
"mkdirp": "^1.0.4",
"requizzle": "^0.2.3",
@@ -2861,12 +2924,6 @@
"underscore": "~1.13.2"
},
"dependencies": {
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
"escape-string-regexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
@@ -2886,9 +2943,9 @@
"dev": true
},
"underscore": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
"version": "1.13.7",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
"integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
"dev": true
}
}
@@ -2901,13 +2958,14 @@
"optional": true
},
"json-stable-stringify": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz",
"integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
"integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
"dev": true,
"optional": true,
"requires": {
"call-bind": "^1.0.5",
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
"isarray": "^2.0.5",
"jsonify": "^0.0.1",
"object-keys": "^1.1.1"
@@ -3005,12 +3063,12 @@
}
},
"linkify-it": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
"requires": {
"uc.micro": "^1.0.1"
"uc.micro": "^2.0.0"
}
},
"locate-path": {
@@ -3157,16 +3215,17 @@
}
},
"markdown-it": {
"version": "12.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
"integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
"requires": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
},
"dependencies": {
"argparse": {
@@ -3176,9 +3235,9 @@
"dev": true
},
"entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true
}
}
@@ -3189,6 +3248,19 @@
"integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
"dev": true
},
"marked": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
"dev": true
},
"math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"optional": true
},
"math-random": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
@@ -3196,9 +3268,9 @@
"dev": true
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true
},
"micromatch": {
@@ -3239,6 +3311,7 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"optional": true,
"requires": {
"mime-db": "1.52.0"
}
@@ -3302,25 +3375,25 @@
"dev": true
},
"moment-timezone": {
"version": "0.5.45",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz",
"integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==",
"version": "0.5.48",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
"integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
"dev": true,
"requires": {
"moment": "^2.29.4"
}
},
"morgan": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
"integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
"integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==",
"dev": true,
"requires": {
"basic-auth": "~2.0.1",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-finished": "~2.3.0",
"on-headers": "~1.0.2"
"on-headers": "~1.1.0"
}
},
"ms": {
@@ -3342,9 +3415,9 @@
}
},
"nan": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz",
"integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==",
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
"dev": true,
"optional": true
},
@@ -3395,9 +3468,9 @@
"optional": true
},
"negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true
},
"neo-async": {
@@ -3561,9 +3634,9 @@
}
},
"on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"dev": true
},
"once": {
@@ -3754,6 +3827,12 @@
"dev": true,
"optional": true
},
"punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"dev": true
},
"qs": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.1.tgz",
@@ -4124,12 +4203,12 @@
}
},
"resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"dev": true,
"requires": {
"is-core-module": "^2.13.0",
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
@@ -4201,9 +4280,9 @@
"dev": true
},
"send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dev": true,
"requires": {
"debug": "2.6.9",
@@ -4245,15 +4324,23 @@
}
},
"serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dev": true,
"requires": {
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
"send": "0.19.0"
},
"dependencies": {
"encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true
}
}
},
"set-blocking": {
@@ -4789,15 +4876,15 @@
"optional": true
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true
},
"uglify-js": {
"version": "3.17.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
"dev": true,
"optional": true
},

View File

@@ -6,6 +6,8 @@
"version": "3.9.0"
},
"devDependencies": {
"@meteorjs/meteor-hexo-config": "1.0.14",
"@meteorjs/meteor-theme-hexo": "^2.0.9",
"canonical-json": "0.0.4",
"chexo": "1.0.7",
"handlebars": "4.7.7",
@@ -17,15 +19,13 @@
"hexo-server": "1.0.0",
"hexo-versioned-netlify-redirects": "1.1.0",
"jsdoc": "^4.0.2",
"@meteorjs/meteor-hexo-config": "1.0.14",
"@meteorjs/meteor-theme-hexo": "2.0.8",
"showdown": "1.9.1",
"underscore": "1.13.1"
},
"scripts": {
"list-core-packages": "node ./generators/packages-listing/script.js",
"generate-history": "node ./generators/changelog/script.js",
"build": "npm run list-core-packages && npm run generate-history && jsdoc/jsdoc.sh && chexo @meteorjs/meteor-hexo-config -- generate",
"build": "npm run list-core-packages && jsdoc/jsdoc.sh && chexo @meteorjs/meteor-hexo-config -- generate",
"clean": "hexo clean; rm data/data.js data/names.json",
"test": "npm run clean; npm run build",
"predeploy": "npm run build",

2
meteor
View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
BUNDLE_VERSION=22.16.0.1
BUNDLE_VERSION=22.18.0.2
# OS Check. Put here because here is where we download the precompiled
# bundles that are arch specific.

View File

@@ -10,7 +10,7 @@ var packageJson = {
dependencies: {
// Explicit dependency because we are replacing it with a bundled version
// and we want to make sure there are no dependencies on a higher version
npm: "10.9.2",
npm: "10.9.3",
pacote: "https://github.com/meteor/pacote/tarball/a81b0324686e85d22c7688c47629d4009000e8b8",
"node-gyp": "9.4.0",
"@mapbox/node-pre-gyp": "1.0.11",

View File

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

View File

@@ -1,12 +1,12 @@
{
"name": "meteor",
"version": "3.3.0",
"version": "3.3.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "meteor",
"version": "3.3.0",
"version": "3.3.1",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "meteor",
"version": "3.3.0",
"version": "3.3.1",
"description": "Install Meteor",
"main": "install.js",
"scripts": {

View File

@@ -25,11 +25,18 @@ var BCp = BabelCompiler.prototype;
var excludedFileExtensionPattern = /\.(es5|min)\.js$/i;
var hasOwn = Object.prototype.hasOwnProperty;
function getMeteorConfig() {
return Plugin?.getMeteorConfig() || {};
}
// Check if verbose mode is enabled either in the provided config or in extraFeatures
BCp.isVerbose = function(config) {
BCp.isVerbose = function(config = getMeteorConfig()) {
if (config?.modern?.transpiler?.verbose) {
return true;
}
if (config?.modern?.verbose) {
return true;
}
if (config?.verbose) {
return true;
}
@@ -80,47 +87,13 @@ function compileWithSwc(source, swcOptions = {}, { features }) {
};
});
}
const DEFAULT_MODERN = {
transpiler: true,
};
const normalizeModern = (r = false) => Object.fromEntries(
Object.entries(DEFAULT_MODERN).map(([k, def]) => [
k,
r === true
? def
: r === false || r?.[k] === false
? false
: typeof r?.[k] === 'object'
? { ...r[k] }
: def,
]),
);
let modernForced = JSON.parse(process.env.METEOR_MODERN || "false");
let lastModifiedMeteorConfig;
let lastModifiedMeteorConfigTime;
BCp.initializeMeteorAppConfig = function () {
if (!lastModifiedMeteorConfig && !fs.existsSync(`${getMeteorAppDir()}/package.json`)) {
return;
const meteorConfig = getMeteorConfig();
if (this.isVerbose()) {
logConfigBlock('Meteor Config', meteorConfig);
}
const currentLastModifiedConfigTime = fs
.statSync(`${getMeteorAppDir()}/package.json`)
?.mtime?.getTime();
if (currentLastModifiedConfigTime !== lastModifiedMeteorConfigTime) {
lastModifiedMeteorConfigTime = currentLastModifiedConfigTime;
lastModifiedMeteorConfig = getMeteorAppPackageJson()?.meteor;
lastModifiedMeteorConfig = lastModifiedMeteorConfig != null ? {
...lastModifiedMeteorConfig,
modern: normalizeModern(modernForced || lastModifiedMeteorConfig?.modern),
} : {};
if (this.isVerbose(lastModifiedMeteorConfig)) {
logConfigBlock('Meteor Config', lastModifiedMeteorConfig);
}
}
return lastModifiedMeteorConfig;
return meteorConfig;
};
let lastModifiedSwcConfig;
@@ -139,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')
@@ -158,9 +133,11 @@ BCp.initializeMeteorAppSwcrc = function () {
lastModifiedSwcConfigTime = currentLastModifiedConfigTime;
lastModifiedSwcConfig = getMeteorAppSwcrc(swcFile);
if (this.isVerbose(lastModifiedMeteorConfig)) {
logConfigBlock('SWC Config', lastModifiedSwcConfig);
if (this.isVerbose()) {
logConfigBlock('SWC Custom Config', lastModifiedSwcConfig);
}
this._swcIncompatible = {};
}
return lastModifiedSwcConfig;
};
@@ -168,13 +145,49 @@ BCp.initializeMeteorAppSwcrc = function () {
let lastModifiedSwcLegacyConfig;
BCp.initializeMeteorAppLegacyConfig = function () {
const swcLegacyConfig = convertBabelTargetsForSwc(Babel.getMinimumModernBrowserVersions());
if (this.isVerbose(lastModifiedMeteorConfig) && !lastModifiedSwcLegacyConfig) {
if (this.isVerbose() && !lastModifiedSwcLegacyConfig) {
logConfigBlock('SWC Legacy Config', swcLegacyConfig);
}
lastModifiedSwcLegacyConfig = swcLegacyConfig;
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;
@@ -184,6 +197,7 @@ BCp.processFilesForTarget = function (inputFiles) {
this.initializeMeteorAppConfig();
this.initializeMeteorAppSwcrc();
this.initializeMeteorAppLegacyConfig();
this.initializeMeteorAppSwcHelpersAvailable();
inputFiles.forEach(function (inputFile) {
if (inputFile.supportsLazyCompilation) {
@@ -314,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,
@@ -355,37 +374,38 @@ BCp.processOneFileForTarget = function (inputFile, source) {
const isPackageCode = packageName != null;
const isLegacyWebArch = arch.includes('legacy');
const config = lastModifiedMeteorConfig?.modern?.transpiler;
const hasModernTranspiler = config != null && config !== false;
const transpConfig = getMeteorConfig()?.modern?.transpiler;
const hasModernTranspiler = transpConfig != null && transpConfig !== false;
const shouldSkipSwc =
!hasModernTranspiler ||
(isAppCode && config?.excludeApp === true) ||
(isNodeModulesCode && config?.excludeNodeModules === true) ||
(isPackageCode && config?.excludePackages === true) ||
(isLegacyWebArch && config?.excludeLegacy === true) ||
(isAppCode && transpConfig?.excludeApp === true) ||
(isNodeModulesCode && transpConfig?.excludeNodeModules === true) ||
(isPackageCode && transpConfig?.excludePackages === true) ||
(isLegacyWebArch && transpConfig?.excludeLegacy === true) ||
(isAppCode &&
Array.isArray(config?.excludeApp) &&
isExcludedConfig(inputFilePath, config?.excludeApp || [])) ||
Array.isArray(transpConfig?.excludeApp) &&
isExcludedConfig(inputFilePath, transpConfig?.excludeApp || [])) ||
(isNodeModulesCode &&
Array.isArray(config?.excludeNodeModules) &&
(isExcludedConfig(inputFilePath, config?.excludeNodeModules || []) ||
Array.isArray(transpConfig?.excludeNodeModules) &&
(isExcludedConfig(inputFilePath, transpConfig?.excludeNodeModules || []) ||
isExcludedConfig(
inputFilePath.replace('node_modules/', ''),
config?.excludeNodeModules || [],
transpConfig?.excludeNodeModules || [],
true,
))) ||
(isPackageCode &&
Array.isArray(config?.excludePackages) &&
(isExcludedConfig(packageName, config?.excludePackages || []) ||
Array.isArray(transpConfig?.excludePackages) &&
(isExcludedConfig(packageName, transpConfig?.excludePackages || []) ||
isExcludedConfig(
`${packageName}/${inputFilePath}`,
config?.excludePackages || [],
transpConfig?.excludePackages || [],
)));
const cacheKey = [
toBeAdded.hash,
lastModifiedSwcConfigTime,
isLegacyWebArch ? 'legacy' : '',
hasSwcHelpersAvailable,
]
.filter(Boolean)
.join('-');
@@ -402,7 +422,7 @@ BCp.processOneFileForTarget = function (inputFile, source) {
compilation = this.readFromSwcCache({ cacheKey });
// Return cached result if found.
if (compilation) {
if (this.isVerbose(config)) {
if (this.isVerbose()) {
logTranspilation({
usedSwc: true,
inputFilePath,
@@ -432,7 +452,7 @@ BCp.processOneFileForTarget = function (inputFile, source) {
usedSwc = false;
}
if (this.isVerbose(config)) {
if (this.isVerbose()) {
logTranspilation({
usedSwc,
inputFilePath,
@@ -448,7 +468,7 @@ BCp.processOneFileForTarget = function (inputFile, source) {
babelOptions = setupBabelOptions();
compilation = compileWithBabel(source, babelOptions, cacheOptions);
if (this.isVerbose(config)) {
if (this.isVerbose()) {
logTranspilation({
usedSwc: false,
inputFilePath,

View File

@@ -1,14 +1,14 @@
Package.describe({
name: "babel-compiler",
summary: "Parser/transpiler for ECMAScript 2015+ syntax",
version: '7.12.0',
version: '7.12.1',
});
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) {

View File

@@ -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.
*

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Register callbacks on a hook",
version: '1.6.0',
version: '1.6.1',
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'ecmascript',
version: '0.16.11',
version: '0.16.12',
summary: 'Compiler plugin that supports ES2015+ in all .js files',
documentation: 'README.md',
});

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "The Meteor command-line tool",
version: "3.3.0",
version: "3.3.1",
});
Package.includeTool();

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "JavaScript minifier",
version: '3.0.2',
version: '3.0.3',
});
Npm.depends({

View File

@@ -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);

View File

@@ -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",
});
Package.onUse((api) => {

View File

@@ -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;

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'modern-browsers',
version: '0.2.2',
version: '0.2.3',
summary:
'API for defining the boundary between modern and legacy ' +
'JavaScript clients',

View File

@@ -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();
}

View File

@@ -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
@@ -393,7 +393,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 });

View File

@@ -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,
};
}

View File

@@ -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);
}

View File

@@ -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;
}
},

View File

@@ -9,7 +9,7 @@
Package.describe({
summary: "Adaptor for using MongoDB and Minimongo over DDP",
version: "2.1.2",
version: "2.1.3",
});
Npm.depends({

View File

@@ -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({});
});

View File

@@ -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' });

View File

@@ -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');

View 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
View File

@@ -0,0 +1,3 @@
import * as NpmModuleMongodb from 'mongodb';
declare const NpmModuleMongodbVersion: string;
export { NpmModuleMongodb, NpmModuleMongodbVersion };

View 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",
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");
});

View 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;

View File

@@ -3,12 +3,12 @@
Package.describe({
summary: "Wrapper around the mongo npm package",
version: "6.10.2",
version: "6.16.0",
documentation: null,
});
Npm.depends({
mongodb: "6.9.0"
mongodb: "6.16.0"
});
Package.onUse(function (api) {

View File

@@ -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;

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'standard-minifier-js',
version: '3.1.0',
version: '3.1.1',
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',

View File

@@ -1,17 +1,4 @@
import { extractModuleSizesTree } from "./stats.js";
import fs from 'fs';
export function getConfig() {
try{
const meteorAppDir = process.cwd();
const packageJson = fs.readFileSync(`${meteorAppDir}/package.json`, 'utf8');
const meteorConfig = JSON.parse(packageJson).meteor;
return meteorConfig;
} catch (error) {
console.log(error);
return {};
}
};
const statsEnabled = process.env.DISABLE_CLIENT_STATS !== 'true'
@@ -26,9 +13,7 @@ const Meteor = typeof global.Meteor !== 'undefined' ? global.Meteor : {
// Profile for test and production environments
let Profile;
if (typeof global.Profile !== 'undefined') {
Profile = global.Profile;
} else if (typeof Plugin !== 'undefined' && Plugin.Profile) {
if (typeof Plugin !== 'undefined' && Plugin.Profile) {
Profile = Plugin.Profile;
} else {
Profile = function (label, func) {
@@ -41,6 +26,10 @@ if (typeof global.Profile !== 'undefined') {
}
}
function getMeteorConfig() {
return Plugin?.getMeteorConfig() || {};
}
let swc;
// Register the minifier only when Plugin is available (not in tests)
@@ -54,11 +43,6 @@ if (typeof Plugin !== 'undefined') {
}
export class MeteorMinifier {
constructor() {
this.config = getConfig();
}
_minifyWithSWC(file) {
return Profile('_minifyWithSWC', () => {
swc = swc || require('@meteorjs/swc-core');
@@ -120,9 +104,14 @@ export class MeteorMinifier {
minifyOneFile(file) {
return Profile('minifyOneFile', () => {
const modern = this.config && (this.config.modern === true || (this.config.modern && this.config.modern.minifier === true));
const meteorConfig = getMeteorConfig();
const modern =
meteorConfig &&
(meteorConfig?.modern === true ||
(meteorConfig?.modern &&
meteorConfig?.modern?.minifier === true));
// check if config is an empty object
if(this.config && Object.keys(this.config).length === 0 || !modern) {
if(meteorConfig && Object.keys(meteorConfig).length === 0 || !modern) {
Meteor._debug(`Minifying using Terser | file: ${file.getPathInBundle()}`);
return this._minifyWithTerser(file);
}

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Tiny testing framework",
version: '1.3.1',
version: '1.3.2',
});
Npm.depends({

View File

@@ -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();

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'typescript',
version: '5.6.4',
version: '5.6.5',
summary:
'Compiler plugin that compiles TypeScript and ECMAScript in .ts and .tsx files',
documentation: 'README.md',

View File

@@ -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"

View File

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

View File

@@ -5,10 +5,10 @@ set -u
UNAME=$(uname)
ARCH=$(uname -m)
NODE_VERSION=22.16.0
NODE_VERSION=22.18.0
MONGO_VERSION_64BIT=7.0.16
MONGO_VERSION_32BIT=3.2.22
NPM_VERSION=10.9.2
NPM_VERSION=10.9.3
if [ "$UNAME" == "Linux" ] ; then

View File

@@ -10,7 +10,7 @@ var packageJson = {
dependencies: {
// Explicit dependency because we are replacing it with a bundled version
// and we want to make sure there are no dependencies on a higher version
npm: "10.9.2",
npm: "10.9.3",
"node-gyp": "10.2.0",
"@mapbox/node-pre-gyp": "1.0.11",
typescript: "5.6.3",

View File

@@ -1,3 +1,5 @@
import { getMeteorConfig } from "../tool-env/meteor-config";
var main = require('./main.js');
var _ = require('underscore');
var files = require('../fs/files');
@@ -261,51 +263,6 @@ export function parseRunTargets(targets) {
});
};
const DEFAULT_MODERN = {
transpiler: true,
webArchOnly: true,
watcher: true,
};
const normalizeModern = (r = false) => Object.fromEntries(
Object.entries(DEFAULT_MODERN).map(([k, def]) => [
k,
r === true
? def
: r === false || r?.[k] === false
? false
: typeof r?.[k] === 'object'
? { ...r[k] }
: def,
]),
);
let modernForced = JSON.parse(process.env.METEOR_MODERN || "false");
let meteorConfig;
function getMeteorConfig(appDir) {
if (meteorConfig) return meteorConfig;
const packageJsonPath = files.pathJoin(appDir, 'package.json');
if (!files.exists(packageJsonPath)) {
return false;
}
const packageJsonFile = files.readFile(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonFile);
meteorConfig = packageJson?.meteor;
return meteorConfig;
}
function isModernArchsOnlyEnabled(appDir) {
const meteorConfig = getMeteorConfig(appDir);
return normalizeModern(modernForced || meteorConfig?.modern).webArchOnly !== false;
}
export function isModernWatcherEnabled(appDir) {
const meteorConfig = getMeteorConfig(appDir);
return normalizeModern(modernForced || meteorConfig?.modern).watcher !== false;
}
function filterWebArchs(webArchs, excludeArchsOption, appDir, options) {
const platforms = (options.platforms || []);
const isBuildMode = platforms?.length > 0;
@@ -325,7 +282,7 @@ function filterWebArchs(webArchs, excludeArchsOption, appDir, options) {
if (!isCordovaDev) {
const excludeArchsOptions = excludeArchsOption ? excludeArchsOption.trim().split(/\s*,\s*/) : [];
const hasExcludeArchsOptions = (excludeArchsOptions?.length || 0) > 0;
const hasModernArchsOnlyEnabled = appDir && isModernArchsOnlyEnabled(appDir);
const hasModernArchsOnlyEnabled = appDir && getMeteorConfig()?.modern?.webArchOnly !== false;
if (hasExcludeArchsOptions && hasModernArchsOnlyEnabled) {
console.warn('modern.webArchOnly and --exclude-archs are both active. If both are set, --exclude-archs takes priority.');
}
@@ -1246,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("");
});
@@ -3436,20 +3407,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}`,
@@ -3457,18 +3466,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) {

View File

@@ -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

View File

@@ -287,12 +287,16 @@ main.captureAndExit = async function (header, title, f) {
// NB: files required up to this point may not define commands
const { isModernWatcherEnabled } = require('./commands.js');
const { initMeteorConfig } = require('../tool-env/meteor-config');
require('./commands.js');
require('./commands-packages.js');
require('./commands-packages-query.js');
require('./commands-cordova.js');
require('./commands-aliases.js');
// Initialize meteorConfig globally
initMeteorConfig();
///////////////////////////////////////////////////////////////////////////////
// Record all the top-level commands as JSON
///////////////////////////////////////////////////////////////////////////////
@@ -865,7 +869,9 @@ makeGlobalAsyncLocalStorage().run({}, async function () {
var appDir = files.findAppDir();
if (appDir) {
appDir = files.pathResolve(appDir);
global.modernWatcher = isModernWatcherEnabled(appDir);
// Renitialize meteorConfig globally when having appDir context
initMeteorConfig(appDir);
}
await require('../tool-env/isopackets.js').ensureIsopacketsLoadable();

View File

@@ -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,

View File

@@ -4,6 +4,7 @@ import { watch as watchLegacy, addWatchRoot as addWatchRootLegacy, closeAllWatch
import { Profile } from "../tool-env/profile";
import { statOrNull, lstat, toPosixPath, convertToOSPath, pathRelative, watchFile, unwatchFile, pathResolve, pathDirname } from "./files";
import { getMeteorConfig } from "../tool-env/meteor-config";
// Register process exit handlers to ensure subscriptions are properly cleaned up
const registerExitHandlers = () => {
@@ -380,7 +381,7 @@ function startNewEntry(absPath: string): Entry {
*/
export function watch (absPath: string, callback: ChangeCallback): SafeWatcher {
// @ts-ignore
if (!global.modernWatcher) {
if (!getMeteorConfig()?.modern?.watcher) {
// @ts-ignore
return watchLegacy(absPath, callback);
}
@@ -444,7 +445,7 @@ const watchModern =
*/
export function addWatchRoot(absPath: string) {
// @ts-ignore
if (!global.modernWatcher) {
if (!getMeteorConfig()?.modern?.watcher) {
// @ts-ignore
return addWatchRootLegacy(absPath);
}
@@ -477,7 +478,7 @@ async function safeUnsubscribeSub(root: string) {
export async function closeAllWatchers() {
// @ts-ignore
if (!global.modernWatcher) {
if (!getMeteorConfig()?.modern?.watcher) {
// @ts-ignore
return closeAllWatchersLegacy();
}

View File

@@ -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 dont support JSX, only with acorn-jsx,
// but it isnt included in Reify.
result = reifyCompile(stripHashBang(source), {
...reifyOptions,
parse: reifyBabelParse,
}).code;
}
if (cacheFilePath) {
Promise.resolve().then(

View File

@@ -1,3 +1,5 @@
import { getMeteorConfig } from "../tool-env/meteor-config";
var compiler = require('./compiler.js');
var archinfo = require('../utils/archinfo');
var _ = require('underscore');
@@ -514,6 +516,9 @@ Object.assign(Isopack.prototype, {
var Plugin = {
name: pluginName,
// Share the meteorConfig object as part of plugin API
getMeteorConfig: getMeteorConfig,
// 'extension' is a file extension without the separation dot
// (eg 'js', 'coffee', 'coffee.md')
//

View File

@@ -1,3 +1,4 @@
import { normalizeModernConfig, setMeteorConfig } from "./tool-env/meteor-config";
var assert = require("assert");
var _ = require('underscore');
@@ -492,6 +493,8 @@ Object.assign(ProjectContext.prototype, {
self.meteorConfig = new MeteorConfig({
appDirectory: self.projectDir,
});
self.meteorConfig._ensureInitialized();
if (buildmessage.jobHasMessages()) {
return;
}
@@ -1217,7 +1220,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;
@@ -1811,6 +1823,13 @@ export class MeteorConfig {
},
}),
} : this._config;
const modernForced = JSON.parse(process.env.METEOR_MODERN || "false");
// Reinitialize meteorConfig globally for project context
// Updates config when package.json changes trigger rebuilds
setMeteorConfig({
...(this._config || {}),
modern: normalizeModernConfig(modernForced || this._config?.modern || false),
});
return this._config;
}
@@ -1818,18 +1837,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() {

View File

@@ -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;

View File

@@ -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",

View File

@@ -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"
},

View File

@@ -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",

View File

@@ -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
}
}

View File

@@ -9,6 +9,7 @@
},
"dependencies": {
"@babel/runtime": "^7.23.5",
"@swc/helpers": "^0.5.17",
"meteor-node-stubs": "^1.2.12"
},
"meteor": {

View File

@@ -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"

View File

@@ -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.
*/

View File

@@ -0,0 +1 @@
import '../imports/ui/main';

View File

@@ -1 +0,0 @@
// main entry point is in imports/ui/main.jsx

View File

@@ -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'));

View File

@@ -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"

View File

@@ -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.
*/

View File

@@ -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: {

View File

@@ -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"
},

View File

@@ -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",

View File

@@ -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"

View File

@@ -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.
*/

View File

@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1 +1 @@
// main entry point is in imports/ui/main.jsx
import '../imports/ui/main'

View File

@@ -1,5 +1,5 @@
<script setup>
import AppMenu from './AppMenu.vue'
import AppMenu from './components/AppMenu.vue'
</script>
<template>

View File

@@ -0,0 +1 @@
@import "tailwindcss";

View File

@@ -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'

View File

@@ -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(),

View File

@@ -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>

View File

@@ -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"
}
}

View File

@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -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.
*/

View File

@@ -1,8 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./imports/ui/**/*.{vue,js,ts,jsx,tsx}', './client/*.html'],
theme: {
extend: {},
},
plugins: [],
}

View File

@@ -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: {

View File

@@ -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();
});

View File

@@ -6,6 +6,7 @@
},
"dependencies": {
"@babel/runtime": "^7.23.5",
"config": "file:../config-package",
"meteor-node-stubs": "^1.2.12",
"react": "^18.3.1"
},

View File

@@ -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"));

View File

@@ -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;

View File

@@ -0,0 +1,85 @@
import files from "../fs/files";
/**
* Global configuration object for Meteor.
* @type {Object}
*/
export let meteorConfig;
/**
* Default configuration for modern mode features.
* @type {Object}
* @property {boolean} transpiler - Whether to use the modern transpiler.
* @property {boolean} minifier - Whether to use the modern minifier.
* @property {boolean} webArchOnly - Whether to use modern features only for web architecture.
* @property {boolean} watcher - Whether to use the modern watcher.
*/
const DEFAULT_MODERN = {
transpiler: true,
minifier: true,
webArchOnly: true,
watcher: true,
};
/**
* Normalizes the modern configuration by applying default values.
* @param {boolean|Object} r - The input modern configuration. If true, uses all defaults.
* If false, disables all modern features. If an object, merges with defaults.
* @returns {Object} - The normalized modern configuration object.
*/
export const normalizeModernConfig = (r = false) => Object.fromEntries(
Object.entries(DEFAULT_MODERN).map(([k, def]) => [
k,
r === true
? def
: r === false || r?.[k] === false
? false
: typeof r?.[k] === 'object'
? { ...r[k] }
: def,
]),
);
/**
* Initializes the Meteor configuration based on the application directory.
* Reads configuration from package.json if available, and applies environment variables.
*
* @param {string|null} appDir - The application directory path. If null, only environment variables are used.
* @returns {Object} - The initialized Meteor configuration object.
*/
export function initMeteorConfig(appDir) {
const modernForced = JSON.parse(process.env.METEOR_MODERN || "false");
let packageJson;
if (appDir) {
const packageJsonPath = files.pathJoin(appDir, 'package.json');
if (!files.exists(packageJsonPath)) {
setMeteorConfig({
modern: normalizeModernConfig(modernForced || false),
});
return meteorConfig;
}
const packageJsonFile = files.readFile(packageJsonPath, 'utf8');
packageJson = JSON.parse(packageJsonFile);
}
setMeteorConfig({
...(packageJson?.meteor || {}),
modern: normalizeModernConfig(modernForced || packageJson?.meteor?.modern || false),
});
return meteorConfig;
}
/**
* Gets the current Meteor configuration.
* @returns {Object} - The current Meteor configuration object.
*/
export function getMeteorConfig() {
return meteorConfig;
}
/**
* Sets the Meteor configuration to a new value.
* @param {Object} config - The new configuration object to set.
*/
export function setMeteorConfig(config) {
meteorConfig = config;
}

View File

@@ -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` :

View File

@@ -100,6 +100,20 @@ 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.
Meteors 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, Meteors 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.

View File

@@ -0,0 +1,116 @@
## v3.3.1, 05-08-2025
### 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.18.0` and NPM `10.9.3` [#13877](https://github.com/meteor/meteor/pull/13877)
- 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 youre 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. Well 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 thats now the default for new apps. Heres 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
- callback-hook@1.6.1
- ecmascript@0.16.12
- minifier-js@3.0.3
- minimongo@2.0.3
- modern-browsers@0.2.3
- mongo@2.1.3
- npm-mongo-legacy@6.9.0
- npm-mongo@6.16.0
- standard-minifier-js@3.1.1
- tinytest@1.3.2
- typescript@5.6.5
- meteor-tool@3.3.1
#### 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)
✨✨✨

View File

@@ -10,6 +10,123 @@ This is a complete history of changes for Meteor releases.
[//]: # (go to meteor/docs/generators/changelog/docs)
## v3.3.1, 05-08-2025
### 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.18.0` and NPM `10.9.3` [#13877](https://github.com/meteor/meteor/pull/13877)
- 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 youre 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. Well 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 thats now the default for new apps. Heres 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
- callback-hook@1.6.1
- ecmascript@0.16.12
- minifier-js@3.0.3
- minimongo@2.0.3
- modern-browsers@0.2.3
- mongo@2.1.3
- npm-mongo-legacy@6.9.0
- npm-mongo@6.16.0
- standard-minifier-js@3.1.1
- tinytest@1.3.2
- typescript@5.6.5
- meteor-tool@3.3.1
#### 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)
✨✨✨
## v3.3.0, 2025-06-11
### Highlights

View File

@@ -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