diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d4c8e377..36a1b157d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,6 +52,10 @@ jobs: - name: Test run: npm run test + - name: Test (Publish) + if: matrix.node-version != '20' + run: npx vitest run --project publish + - name: Test (Integration) if: matrix.operating-system == 'ubuntu-latest' run: npm run test:integration diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 7c7d10e2b..000000000 --- a/Gruntfile.js +++ /dev/null @@ -1,9 +0,0 @@ -// Legacy Gruntfile — kept only for the 'metrics' and 'version' tasks. -// The main build pipeline uses rspack + swc (see rspack.config.js and .swcrc). -module.exports = function (grunt) { - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - }); - - grunt.task.loadTasks('tasks'); -}; diff --git a/package-lock.json b/package-lock.json index db79d4120..383276b77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "yargs": "^18.0.0" }, "bin": { - "handlebars": "bin/handlebars.js" + "handlebars": "bin/handlebars.mjs" }, "devDependencies": { "@aws-sdk/client-s3": "^3.1011.0", @@ -393,20 +393,20 @@ "license": "0BSD" }, "node_modules/@aws-sdk/core": { - "version": "3.973.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.20.tgz", - "integrity": "sha512-i3GuX+lowD892F3IuJf8o6AbyDupMTdyTxQrCJGcn71ni5hTZ82L4nQhcdumxZ7XPJRJJVHS/CR3uYOIIs0PVA==", + "version": "3.973.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.22.tgz", + "integrity": "sha512-lY6g5L95jBNgOUitUhfV2N/W+i08jHEl3xuLODYSQH5Sf50V+LkVYBSyZRLtv2RyuXZXiV7yQ+acpswK1tlrOA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.6", - "@aws-sdk/xml-builder": "^3.972.11", - "@smithy/core": "^3.23.11", + "@aws-sdk/xml-builder": "^3.972.14", + "@smithy/core": "^3.23.12", "@smithy/node-config-provider": "^4.3.12", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/signature-v4": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.12", @@ -446,13 +446,13 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.18.tgz", - "integrity": "sha512-X0B8AlQY507i5DwjLByeU2Af4ARsl9Vr84koDcXCbAkplmU+1xBFWxEPrWRAoh56waBne/yJqEloSwvRf4x6XA==", + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.20.tgz", + "integrity": "sha512-vI0QN96DFx3g9AunfOWF3CS4cMkqFiR/WM/FyP9QHr5rZ2dKPkYwP3tCgAOvGuu9CXI7dC1vU2FVUuZ+tfpNvQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/types": "^4.13.1", @@ -470,21 +470,21 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.20.tgz", - "integrity": "sha512-ey9Lelj001+oOfrbKmS6R2CJAiXX7QKY4Vj9VJv6L2eE6/VjD8DocHIoYqztTm70xDLR4E1jYPTKfIui+eRNDA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.22.tgz", + "integrity": "sha512-aS/81smalpe7XDnuQfOq4LIPuaV2PRKU2aMTrHcqO5BD4HwO5kESOHNcec2AYfBtLtIDqgF6RXisgBnfK/jt0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.4.16", + "@smithy/node-http-handler": "^4.5.0", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.19", + "@smithy/util-stream": "^4.5.20", "tslib": "^2.6.2" }, "engines": { @@ -499,20 +499,20 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.20.tgz", - "integrity": "sha512-5flXSnKHMloObNF+9N0cupKegnH1Z37cdVlpETVgx8/rAhCe+VNlkcZH3HDg2SDn9bI765S+rhNPXGDJJPfbtA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.22.tgz", + "integrity": "sha512-rpF8fBT0LllMDp78s62aL2A/8MaccjyJ0ORzqu+ZADeECLSrrCWIeeXsuRam+pxiAMkI1uIyDZJmgLGdadkPXw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/credential-provider-env": "^3.972.18", - "@aws-sdk/credential-provider-http": "^3.972.20", - "@aws-sdk/credential-provider-login": "^3.972.20", - "@aws-sdk/credential-provider-process": "^3.972.18", - "@aws-sdk/credential-provider-sso": "^3.972.20", - "@aws-sdk/credential-provider-web-identity": "^3.972.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/credential-provider-env": "^3.972.20", + "@aws-sdk/credential-provider-http": "^3.972.22", + "@aws-sdk/credential-provider-login": "^3.972.22", + "@aws-sdk/credential-provider-process": "^3.972.20", + "@aws-sdk/credential-provider-sso": "^3.972.22", + "@aws-sdk/credential-provider-web-identity": "^3.972.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -532,14 +532,14 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.20.tgz", - "integrity": "sha512-gEWo54nfqp2jABMu6HNsjVC4hDLpg9HC8IKSJnp0kqWtxIJYHTmiLSsIfI4ScQjxEwpB+jOOH8dOLax1+hy/Hw==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.22.tgz", + "integrity": "sha512-u33CO9zeNznlVSg9tWTCRYxaGkqr1ufU6qeClpmzAabXZa8RZxQoVXxL5T53oZJFzQYj+FImORCSsi7H7B77gQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", @@ -559,18 +559,18 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.21.tgz", - "integrity": "sha512-hah8if3/B/Q+LBYN5FukyQ1Mym6PLPDsBOBsIgNEYD6wLyZg0UmUF/OKIVC3nX9XH8TfTPuITK+7N/jenVACWA==", + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.23.tgz", + "integrity": "sha512-U8tyLbLOZItuVWTH0ay9gWo4xMqZwqQbg1oMzdU4FQSkTpqXemm4X0uoKBR6llqAStgBp30ziKFJHTA43l4qMw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.18", - "@aws-sdk/credential-provider-http": "^3.972.20", - "@aws-sdk/credential-provider-ini": "^3.972.20", - "@aws-sdk/credential-provider-process": "^3.972.18", - "@aws-sdk/credential-provider-sso": "^3.972.20", - "@aws-sdk/credential-provider-web-identity": "^3.972.20", + "@aws-sdk/credential-provider-env": "^3.972.20", + "@aws-sdk/credential-provider-http": "^3.972.22", + "@aws-sdk/credential-provider-ini": "^3.972.22", + "@aws-sdk/credential-provider-process": "^3.972.20", + "@aws-sdk/credential-provider-sso": "^3.972.22", + "@aws-sdk/credential-provider-web-identity": "^3.972.22", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -590,13 +590,13 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.18.tgz", - "integrity": "sha512-Tpl7SRaPoOLT32jbTWchPsn52hYYgJ0kpiFgnwk8pxTANQdUymVSZkzFvv1+oOgZm1CrbQUP9MBeoMZ9IzLZjA==", + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.20.tgz", + "integrity": "sha512-QRfk7GbA4/HDRjhP3QYR6QBr/QKreVoOzvvlRHnOuGgYJkeoPgPY3LAI1kK1ZMgZ4hH9KiGp757/ntol+INAig==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -615,15 +615,15 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.20.tgz", - "integrity": "sha512-p+R+PYR5Z7Gjqf/6pvbCnzEHcqPCpLzR7Yf127HjJ6EAb4hUcD+qsNRnuww1sB/RmSeCLxyay8FMyqREw4p1RA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.22.tgz", + "integrity": "sha512-4vqlSaUbBj4aNPVKfB6yXuIQ2Z2mvLfIGba2OzzF6zUkN437/PGWsxBU2F8QPSFHti6seckvyCXidU3H+R8NvQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", - "@aws-sdk/token-providers": "3.1009.0", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", + "@aws-sdk/token-providers": "3.1013.0", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -642,14 +642,14 @@ "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.20.tgz", - "integrity": "sha512-rWCmh8o7QY4CsUj63qopzMzkDq/yPpkrpb+CnjBEFSOg/02T/we7sSTVg4QsDiVS9uwZ8VyONhq98qt+pIh3KA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.22.tgz", + "integrity": "sha512-/wN1CYg2rVLhW8/jLxMWacQrkpaynnL+4j/Z+e6X1PfoE6NiC0BeOw3i0JmtZrKun85wNV5GmspvuWJihfeeUw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -896,16 +896,16 @@ "license": "0BSD" }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.21.tgz", - "integrity": "sha512-62XRl1GDYPpkt7cx1AX1SPy9wgNE9Iw/NPuurJu4lmhCWS7sGKO+kS53TQ8eRmIxy3skmvNInnk0ZbWrU5Dpyg==", + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.23.tgz", + "integrity": "sha512-HQu8QoqGZZTvg0Spl9H39QTsSMFwgu+8yz/QGKndXFLk9FZMiCiIgBCVlTVKMDvVbgqIzD9ig+/HmXsIL2Rb+g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", - "@smithy/core": "^3.23.11", + "@smithy/core": "^3.23.12", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", "@smithy/util-retry": "^4.2.12", @@ -923,45 +923,45 @@ "license": "0BSD" }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.996.10", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.10.tgz", - "integrity": "sha512-SlDol5Z+C7Ivnc2rKGqiqfSUmUZzY1qHfVs9myt/nxVwswgfpjdKahyTzLTx802Zfq0NFRs7AejwKzzzl5Co2w==", + "version": "3.996.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.12.tgz", + "integrity": "sha512-KLdQGJPSm98uLINolQ0Tol8OAbk7g0Y7zplHJ1K83vbMIH13aoCvR6Tho66xueW4l4aZlEgVGLWBnD8ifUMsGQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.21", + "@aws-sdk/middleware-user-agent": "^3.972.23", "@aws-sdk/region-config-resolver": "^3.972.8", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.7", + "@aws-sdk/util-user-agent-node": "^3.973.9", "@smithy/config-resolver": "^4.4.11", - "@smithy/core": "^3.23.11", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.25", - "@smithy/middleware-retry": "^4.4.42", - "@smithy/middleware-serde": "^4.2.14", + "@smithy/middleware-endpoint": "^4.4.26", + "@smithy/middleware-retry": "^4.4.43", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.4.16", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.41", - "@smithy/util-defaults-mode-node": "^4.2.44", + "@smithy/util-defaults-mode-browser": "^4.3.42", + "@smithy/util-defaults-mode-node": "^4.2.45", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", "@smithy/util-retry": "^4.2.12", @@ -1029,14 +1029,14 @@ "license": "0BSD" }, "node_modules/@aws-sdk/token-providers": { - "version": "3.1009.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1009.0.tgz", - "integrity": "sha512-KCPLuTqN9u0Rr38Arln78fRG9KXpzsPWmof+PZzfAHMMQq2QED6YjQrkrfiH7PDefLWEposY1o4/eGwrmKA4JA==", + "version": "3.1013.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1013.0.tgz", + "integrity": "sha512-IL1c54UvbuERrs9oLm5rvkzMciwhhpn1FL0SlC3XUMoLlFhdBsWJgQKK8O5fsQLxbFVqjbjFx9OBkrn44X9PHw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -1160,13 +1160,13 @@ "license": "0BSD" }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.7", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.7.tgz", - "integrity": "sha512-Hz6EZMUAEzqUd7e+vZ9LE7mn+5gMbxltXy18v+YSFY+9LBJz15wkNZvw5JqfX3z0FS9n3bgUtz3L5rAsfh4YlA==", + "version": "3.973.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.9.tgz", + "integrity": "sha512-jeFqqp8KD/P5O+qeKxyGeu7WEVIZFNprnkaDjGmBOjwxYwafCBhpxTgV1TlW6L8e76Vh/siNylNmN/OmSIFBUQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.21", + "@aws-sdk/middleware-user-agent": "^3.972.23", "@aws-sdk/types": "^3.973.6", "@smithy/node-config-provider": "^4.3.12", "@smithy/types": "^4.13.1", @@ -1193,14 +1193,14 @@ "license": "0BSD" }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.11", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.11.tgz", - "integrity": "sha512-iitV/gZKQMvY9d7ovmyFnFuTHbBAtrmLnvaSb/3X8vOKyevwtpmEtyc8AdhVWZe0pI/1GsHxlEvQeOePFzy7KQ==", + "version": "3.972.14", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.14.tgz", + "integrity": "sha512-G/Yd8Bnnyh8QrqLf8jWJbixEnScUFW24e/wOBGYdw1Cl4r80KX/DvHyM2GVZ2vTp7J4gTEr8IXJlTadA8+UfuQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.13.1", - "fast-xml-parser": "5.4.1", + "fast-xml-parser": "5.5.6", "tslib": "^2.6.2" }, "engines": { @@ -9187,9 +9187,9 @@ } }, "node_modules/fast-xml-parser": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", - "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.6.tgz", + "integrity": "sha512-3+fdZyBRVg29n4rXP0joHthhcHdPUHaIC16cuyyd1iLsuaO6Vea36MPrxgAzbZna8lhvZeRL8Bc9GP56/J9xEw==", "dev": true, "funding": [ { @@ -9199,7 +9199,8 @@ ], "license": "MIT", "dependencies": { - "fast-xml-builder": "^1.0.0", + "fast-xml-builder": "^1.1.4", + "path-expression-matcher": "^1.1.3", "strnum": "^2.1.2" }, "bin": { @@ -12883,9 +12884,9 @@ } }, "node_modules/strnum": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", - "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.1.tgz", + "integrity": "sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==", "dev": true, "funding": [ { @@ -14303,19 +14304,19 @@ } }, "@aws-sdk/core": { - "version": "3.973.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.20.tgz", - "integrity": "sha512-i3GuX+lowD892F3IuJf8o6AbyDupMTdyTxQrCJGcn71ni5hTZ82L4nQhcdumxZ7XPJRJJVHS/CR3uYOIIs0PVA==", + "version": "3.973.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.22.tgz", + "integrity": "sha512-lY6g5L95jBNgOUitUhfV2N/W+i08jHEl3xuLODYSQH5Sf50V+LkVYBSyZRLtv2RyuXZXiV7yQ+acpswK1tlrOA==", "dev": true, "requires": { "@aws-sdk/types": "^3.973.6", - "@aws-sdk/xml-builder": "^3.972.11", - "@smithy/core": "^3.23.11", + "@aws-sdk/xml-builder": "^3.972.14", + "@smithy/core": "^3.23.12", "@smithy/node-config-provider": "^4.3.12", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/signature-v4": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.12", @@ -14350,12 +14351,12 @@ } }, "@aws-sdk/credential-provider-env": { - "version": "3.972.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.18.tgz", - "integrity": "sha512-X0B8AlQY507i5DwjLByeU2Af4ARsl9Vr84koDcXCbAkplmU+1xBFWxEPrWRAoh56waBne/yJqEloSwvRf4x6XA==", + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.20.tgz", + "integrity": "sha512-vI0QN96DFx3g9AunfOWF3CS4cMkqFiR/WM/FyP9QHr5rZ2dKPkYwP3tCgAOvGuu9CXI7dC1vU2FVUuZ+tfpNvQ==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/types": "^4.13.1", @@ -14371,20 +14372,20 @@ } }, "@aws-sdk/credential-provider-http": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.20.tgz", - "integrity": "sha512-ey9Lelj001+oOfrbKmS6R2CJAiXX7QKY4Vj9VJv6L2eE6/VjD8DocHIoYqztTm70xDLR4E1jYPTKfIui+eRNDA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.22.tgz", + "integrity": "sha512-aS/81smalpe7XDnuQfOq4LIPuaV2PRKU2aMTrHcqO5BD4HwO5kESOHNcec2AYfBtLtIDqgF6RXisgBnfK/jt0w==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/fetch-http-handler": "^5.3.15", - "@smithy/node-http-handler": "^4.4.16", + "@smithy/node-http-handler": "^4.5.0", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", - "@smithy/util-stream": "^4.5.19", + "@smithy/util-stream": "^4.5.20", "tslib": "^2.6.2" }, "dependencies": { @@ -14397,19 +14398,19 @@ } }, "@aws-sdk/credential-provider-ini": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.20.tgz", - "integrity": "sha512-5flXSnKHMloObNF+9N0cupKegnH1Z37cdVlpETVgx8/rAhCe+VNlkcZH3HDg2SDn9bI765S+rhNPXGDJJPfbtA==", - "dev": true, - "requires": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/credential-provider-env": "^3.972.18", - "@aws-sdk/credential-provider-http": "^3.972.20", - "@aws-sdk/credential-provider-login": "^3.972.20", - "@aws-sdk/credential-provider-process": "^3.972.18", - "@aws-sdk/credential-provider-sso": "^3.972.20", - "@aws-sdk/credential-provider-web-identity": "^3.972.20", - "@aws-sdk/nested-clients": "^3.996.10", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.22.tgz", + "integrity": "sha512-rpF8fBT0LllMDp78s62aL2A/8MaccjyJ0ORzqu+ZADeECLSrrCWIeeXsuRam+pxiAMkI1uIyDZJmgLGdadkPXw==", + "dev": true, + "requires": { + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/credential-provider-env": "^3.972.20", + "@aws-sdk/credential-provider-http": "^3.972.22", + "@aws-sdk/credential-provider-login": "^3.972.22", + "@aws-sdk/credential-provider-process": "^3.972.20", + "@aws-sdk/credential-provider-sso": "^3.972.22", + "@aws-sdk/credential-provider-web-identity": "^3.972.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -14427,13 +14428,13 @@ } }, "@aws-sdk/credential-provider-login": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.20.tgz", - "integrity": "sha512-gEWo54nfqp2jABMu6HNsjVC4hDLpg9HC8IKSJnp0kqWtxIJYHTmiLSsIfI4ScQjxEwpB+jOOH8dOLax1+hy/Hw==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.22.tgz", + "integrity": "sha512-u33CO9zeNznlVSg9tWTCRYxaGkqr1ufU6qeClpmzAabXZa8RZxQoVXxL5T53oZJFzQYj+FImORCSsi7H7B77gQ==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", @@ -14451,17 +14452,17 @@ } }, "@aws-sdk/credential-provider-node": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.21.tgz", - "integrity": "sha512-hah8if3/B/Q+LBYN5FukyQ1Mym6PLPDsBOBsIgNEYD6wLyZg0UmUF/OKIVC3nX9XH8TfTPuITK+7N/jenVACWA==", + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.23.tgz", + "integrity": "sha512-U8tyLbLOZItuVWTH0ay9gWo4xMqZwqQbg1oMzdU4FQSkTpqXemm4X0uoKBR6llqAStgBp30ziKFJHTA43l4qMw==", "dev": true, "requires": { - "@aws-sdk/credential-provider-env": "^3.972.18", - "@aws-sdk/credential-provider-http": "^3.972.20", - "@aws-sdk/credential-provider-ini": "^3.972.20", - "@aws-sdk/credential-provider-process": "^3.972.18", - "@aws-sdk/credential-provider-sso": "^3.972.20", - "@aws-sdk/credential-provider-web-identity": "^3.972.20", + "@aws-sdk/credential-provider-env": "^3.972.20", + "@aws-sdk/credential-provider-http": "^3.972.22", + "@aws-sdk/credential-provider-ini": "^3.972.22", + "@aws-sdk/credential-provider-process": "^3.972.20", + "@aws-sdk/credential-provider-sso": "^3.972.22", + "@aws-sdk/credential-provider-web-identity": "^3.972.22", "@aws-sdk/types": "^3.973.6", "@smithy/credential-provider-imds": "^4.2.12", "@smithy/property-provider": "^4.2.12", @@ -14479,12 +14480,12 @@ } }, "@aws-sdk/credential-provider-process": { - "version": "3.972.18", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.18.tgz", - "integrity": "sha512-Tpl7SRaPoOLT32jbTWchPsn52hYYgJ0kpiFgnwk8pxTANQdUymVSZkzFvv1+oOgZm1CrbQUP9MBeoMZ9IzLZjA==", + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.20.tgz", + "integrity": "sha512-QRfk7GbA4/HDRjhP3QYR6QBr/QKreVoOzvvlRHnOuGgYJkeoPgPY3LAI1kK1ZMgZ4hH9KiGp757/ntol+INAig==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -14501,14 +14502,14 @@ } }, "@aws-sdk/credential-provider-sso": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.20.tgz", - "integrity": "sha512-p+R+PYR5Z7Gjqf/6pvbCnzEHcqPCpLzR7Yf127HjJ6EAb4hUcD+qsNRnuww1sB/RmSeCLxyay8FMyqREw4p1RA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.22.tgz", + "integrity": "sha512-4vqlSaUbBj4aNPVKfB6yXuIQ2Z2mvLfIGba2OzzF6zUkN437/PGWsxBU2F8QPSFHti6seckvyCXidU3H+R8NvQ==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", - "@aws-sdk/token-providers": "3.1009.0", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", + "@aws-sdk/token-providers": "3.1013.0", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -14525,13 +14526,13 @@ } }, "@aws-sdk/credential-provider-web-identity": { - "version": "3.972.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.20.tgz", - "integrity": "sha512-rWCmh8o7QY4CsUj63qopzMzkDq/yPpkrpb+CnjBEFSOg/02T/we7sSTVg4QsDiVS9uwZ8VyONhq98qt+pIh3KA==", + "version": "3.972.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.22.tgz", + "integrity": "sha512-/wN1CYg2rVLhW8/jLxMWacQrkpaynnL+4j/Z+e6X1PfoE6NiC0BeOw3i0JmtZrKun85wNV5GmspvuWJihfeeUw==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -14749,15 +14750,15 @@ } }, "@aws-sdk/middleware-user-agent": { - "version": "3.972.21", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.21.tgz", - "integrity": "sha512-62XRl1GDYPpkt7cx1AX1SPy9wgNE9Iw/NPuurJu4lmhCWS7sGKO+kS53TQ8eRmIxy3skmvNInnk0ZbWrU5Dpyg==", + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.23.tgz", + "integrity": "sha512-HQu8QoqGZZTvg0Spl9H39QTsSMFwgu+8yz/QGKndXFLk9FZMiCiIgBCVlTVKMDvVbgqIzD9ig+/HmXsIL2Rb+g==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", - "@smithy/core": "^3.23.11", + "@smithy/core": "^3.23.12", "@smithy/protocol-http": "^5.3.12", "@smithy/types": "^4.13.1", "@smithy/util-retry": "^4.2.12", @@ -14773,44 +14774,44 @@ } }, "@aws-sdk/nested-clients": { - "version": "3.996.10", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.10.tgz", - "integrity": "sha512-SlDol5Z+C7Ivnc2rKGqiqfSUmUZzY1qHfVs9myt/nxVwswgfpjdKahyTzLTx802Zfq0NFRs7AejwKzzzl5Co2w==", + "version": "3.996.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.12.tgz", + "integrity": "sha512-KLdQGJPSm98uLINolQ0Tol8OAbk7g0Y7zplHJ1K83vbMIH13aoCvR6Tho66xueW4l4aZlEgVGLWBnD8ifUMsGQ==", "dev": true, "requires": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.20", + "@aws-sdk/core": "^3.973.22", "@aws-sdk/middleware-host-header": "^3.972.8", "@aws-sdk/middleware-logger": "^3.972.8", "@aws-sdk/middleware-recursion-detection": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.21", + "@aws-sdk/middleware-user-agent": "^3.972.23", "@aws-sdk/region-config-resolver": "^3.972.8", "@aws-sdk/types": "^3.973.6", "@aws-sdk/util-endpoints": "^3.996.5", "@aws-sdk/util-user-agent-browser": "^3.972.8", - "@aws-sdk/util-user-agent-node": "^3.973.7", + "@aws-sdk/util-user-agent-node": "^3.973.9", "@smithy/config-resolver": "^4.4.11", - "@smithy/core": "^3.23.11", + "@smithy/core": "^3.23.12", "@smithy/fetch-http-handler": "^5.3.15", "@smithy/hash-node": "^4.2.12", "@smithy/invalid-dependency": "^4.2.12", "@smithy/middleware-content-length": "^4.2.12", - "@smithy/middleware-endpoint": "^4.4.25", - "@smithy/middleware-retry": "^4.4.42", - "@smithy/middleware-serde": "^4.2.14", + "@smithy/middleware-endpoint": "^4.4.26", + "@smithy/middleware-retry": "^4.4.43", + "@smithy/middleware-serde": "^4.2.15", "@smithy/middleware-stack": "^4.2.12", "@smithy/node-config-provider": "^4.3.12", - "@smithy/node-http-handler": "^4.4.16", + "@smithy/node-http-handler": "^4.5.0", "@smithy/protocol-http": "^5.3.12", - "@smithy/smithy-client": "^4.12.5", + "@smithy/smithy-client": "^4.12.6", "@smithy/types": "^4.13.1", "@smithy/url-parser": "^4.2.12", "@smithy/util-base64": "^4.3.2", "@smithy/util-body-length-browser": "^4.2.2", "@smithy/util-body-length-node": "^4.2.3", - "@smithy/util-defaults-mode-browser": "^4.3.41", - "@smithy/util-defaults-mode-node": "^4.2.44", + "@smithy/util-defaults-mode-browser": "^4.3.42", + "@smithy/util-defaults-mode-node": "^4.2.45", "@smithy/util-endpoints": "^3.3.3", "@smithy/util-middleware": "^4.2.12", "@smithy/util-retry": "^4.2.12", @@ -14870,13 +14871,13 @@ } }, "@aws-sdk/token-providers": { - "version": "3.1009.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1009.0.tgz", - "integrity": "sha512-KCPLuTqN9u0Rr38Arln78fRG9KXpzsPWmof+PZzfAHMMQq2QED6YjQrkrfiH7PDefLWEposY1o4/eGwrmKA4JA==", + "version": "3.1013.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1013.0.tgz", + "integrity": "sha512-IL1c54UvbuERrs9oLm5rvkzMciwhhpn1FL0SlC3XUMoLlFhdBsWJgQKK8O5fsQLxbFVqjbjFx9OBkrn44X9PHw==", "dev": true, "requires": { - "@aws-sdk/core": "^3.973.20", - "@aws-sdk/nested-clients": "^3.996.10", + "@aws-sdk/core": "^3.973.22", + "@aws-sdk/nested-clients": "^3.996.12", "@aws-sdk/types": "^3.973.6", "@smithy/property-provider": "^4.2.12", "@smithy/shared-ini-file-loader": "^4.4.7", @@ -14986,12 +14987,12 @@ } }, "@aws-sdk/util-user-agent-node": { - "version": "3.973.7", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.7.tgz", - "integrity": "sha512-Hz6EZMUAEzqUd7e+vZ9LE7mn+5gMbxltXy18v+YSFY+9LBJz15wkNZvw5JqfX3z0FS9n3bgUtz3L5rAsfh4YlA==", + "version": "3.973.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.9.tgz", + "integrity": "sha512-jeFqqp8KD/P5O+qeKxyGeu7WEVIZFNprnkaDjGmBOjwxYwafCBhpxTgV1TlW6L8e76Vh/siNylNmN/OmSIFBUQ==", "dev": true, "requires": { - "@aws-sdk/middleware-user-agent": "^3.972.21", + "@aws-sdk/middleware-user-agent": "^3.972.23", "@aws-sdk/types": "^3.973.6", "@smithy/node-config-provider": "^4.3.12", "@smithy/types": "^4.13.1", @@ -15008,13 +15009,13 @@ } }, "@aws-sdk/xml-builder": { - "version": "3.972.11", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.11.tgz", - "integrity": "sha512-iitV/gZKQMvY9d7ovmyFnFuTHbBAtrmLnvaSb/3X8vOKyevwtpmEtyc8AdhVWZe0pI/1GsHxlEvQeOePFzy7KQ==", + "version": "3.972.14", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.14.tgz", + "integrity": "sha512-G/Yd8Bnnyh8QrqLf8jWJbixEnScUFW24e/wOBGYdw1Cl4r80KX/DvHyM2GVZ2vTp7J4gTEr8IXJlTadA8+UfuQ==", "dev": true, "requires": { "@smithy/types": "^4.13.1", - "fast-xml-parser": "5.4.1", + "fast-xml-parser": "5.5.6", "tslib": "^2.6.2" }, "dependencies": { @@ -20216,12 +20217,13 @@ } }, "fast-xml-parser": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", - "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.6.tgz", + "integrity": "sha512-3+fdZyBRVg29n4rXP0joHthhcHdPUHaIC16cuyyd1iLsuaO6Vea36MPrxgAzbZna8lhvZeRL8Bc9GP56/J9xEw==", "dev": true, "requires": { - "fast-xml-builder": "^1.0.0", + "fast-xml-builder": "^1.1.4", + "path-expression-matcher": "^1.1.3", "strnum": "^2.1.2" } }, @@ -22688,9 +22690,9 @@ "dev": true }, "strnum": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", - "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.1.tgz", + "integrity": "sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==", "dev": true }, "strtok3": { diff --git a/package.json b/package.json index 856466cb8..d089b5792 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "test:browser": "vitest run --project browser", "test:unit": "vitest run --project node", "test:tasks": "vitest run --project tasks", + "test:publish": "npm run build && vitest run --project publish", "test:browser-smoke": "playwright test --config tests/browser/playwright.config.js", "test:serve": "npx serve -l 9999 .", "test:integration": "npm run build && ./tests/integration/run-integration-tests.sh", diff --git a/tasks/publish-to-aws.js b/tasks/publish-to-aws.js index 00cb9f693..80b2b5120 100644 --- a/tasks/publish-to-aws.js +++ b/tasks/publish-to-aws.js @@ -4,6 +4,13 @@ const { S3, PutObjectCommand } = require('@aws-sdk/client-s3'); const git = require('./util/git'); const semver = require('semver'); +const PUBLISHED_FILES = [ + 'handlebars.js', + 'handlebars.min.js', + 'handlebars.runtime.js', + 'handlebars.runtime.min.js', +]; + let s3Client; async function main() { @@ -13,24 +20,28 @@ async function main() { const commitInfo = await git.commitInfo(); console.log('tag: ', commitInfo.tagName); + const suffixes = buildSuffixes(commitInfo); + + if (suffixes.length > 0) { + validateS3Env(); + console.log('publishing file-suffixes: ' + JSON.stringify(suffixes)); + await publish(suffixes); + } +} + +function buildSuffixes(commitInfo) { const suffixes = []; - // Publish the master as "latest" and with the commit-id if (commitInfo.isMaster) { suffixes.push('-latest'); suffixes.push('-' + commitInfo.headSha); } - // Publish tags by their tag-name if (commitInfo.tagName != null && semver.valid(commitInfo.tagName)) { suffixes.push('-' + commitInfo.tagName); } - if (suffixes.length > 0) { - validateS3Env(); - console.log('publishing file-suffixes: ' + JSON.stringify(suffixes)); - await publish(suffixes); - } + return suffixes; } function validateS3Env() { @@ -44,33 +55,30 @@ function validateS3Env() { } } -async function publish(suffixes) { - const publishPromises = suffixes.map((suffix) => publishSuffix(suffix)); +async function publish(suffixes, overrides) { + const publishPromises = suffixes.map((suffix) => + publishSuffix(suffix, overrides) + ); return Promise.all(publishPromises); } -async function publishSuffix(suffix) { - const filenames = [ - 'handlebars.js', - 'handlebars.min.js', - 'handlebars.runtime.js', - 'handlebars.runtime.min.js', - ]; - const publishPromises = filenames.map(async (filename) => { +async function publishSuffix(suffix, overrides) { + const publishPromises = PUBLISHED_FILES.map(async (filename) => { const nameInBucket = getNameInBucket(filename, suffix); const localFile = getLocalFile(filename); - await uploadToBucket(localFile, nameInBucket); + await uploadToBucket(localFile, nameInBucket, overrides); console.log(`Published ${localFile} to build server (${nameInBucket})`); }); return Promise.all(publishPromises); } -async function uploadToBucket(localFile, nameInBucket) { - const s3 = getS3Client(); +async function uploadToBucket(localFile, nameInBucket, overrides) { + const s3 = overrides?.s3Client ?? getS3Client(); + const bucket = overrides?.bucket ?? process.env.S3_BUCKET_NAME; return s3.send( new PutObjectCommand({ - Bucket: process.env.S3_BUCKET_NAME, + Bucket: bucket, Key: nameInBucket, Body: fs.readFileSync(localFile, 'utf8'), }) @@ -98,6 +106,15 @@ function getLocalFile(filename) { return 'dist/' + filename; } +module.exports = { + PUBLISHED_FILES, + buildSuffixes, + validateS3Env, + publish, + getNameInBucket, + getLocalFile, +}; + if (require.main === module) { main().catch((err) => { console.error(err); diff --git a/tasks/tests/fake-s3.js b/tasks/tests/fake-s3.js new file mode 100644 index 000000000..a12cc26e6 --- /dev/null +++ b/tasks/tests/fake-s3.js @@ -0,0 +1,81 @@ +const http = require('http'); + +/** + * Minimal in-memory S3-compatible server for testing. + * Supports PutObject and GetObject via path-style requests. + */ +function createFakeS3() { + const buckets = new Map(); + + const server = http.createServer((req, res) => { + const { bucket, key } = parsePath(req.url); + + if (!bucket || !buckets.has(bucket)) { + res.writeHead(404, { 'Content-Type': 'application/xml' }); + res.end('NoSuchBucket'); + return; + } + + const store = buckets.get(bucket); + + if (req.method === 'PUT' && key) { + const chunks = []; + req.on('data', (chunk) => chunks.push(chunk)); + req.on('end', () => { + store.set(key, Buffer.concat(chunks)); + res.writeHead(200); + res.end(); + }); + } else if ((req.method === 'GET' || req.method === 'HEAD') && key) { + if (!store.has(key)) { + res.writeHead(404, { 'Content-Type': 'application/xml' }); + res.end('NoSuchKey'); + return; + } + const body = store.get(key); + res.writeHead(200, { + 'Content-Length': body.length, + 'Content-Type': 'application/octet-stream', + }); + res.end(req.method === 'HEAD' ? undefined : body); + } else { + res.writeHead(405); + res.end(); + } + }); + + return { + start() { + return new Promise((resolve) => { + server.listen(0, '127.0.0.1', () => { + const { port } = server.address(); + resolve({ + address: `http://127.0.0.1:${port}`, + createBucket(name) { + if (!buckets.has(name)) buckets.set(name, new Map()); + }, + reset() { + for (const store of buckets.values()) store.clear(); + }, + stop() { + return new Promise((r) => server.close(r)); + }, + }); + }); + }); + }, + }; +} + +function parsePath(url) { + // Path-style: // + const parts = new URL(url, 'http://localhost').pathname + .replace(/^\//, '') + .split('/'); + return { + bucket: parts[0] || null, + key: parts.slice(1).join('/') || null, + }; +} + +module.exports = { createFakeS3 }; diff --git a/tasks/tests/publish-to-aws.test.js b/tasks/tests/publish-to-aws.test.js new file mode 100644 index 000000000..70b5ce8fa --- /dev/null +++ b/tasks/tests/publish-to-aws.test.js @@ -0,0 +1,221 @@ +const fs = require('fs'); +const { S3, GetObjectCommand } = require('@aws-sdk/client-s3'); +const { createFakeS3 } = require('./fake-s3'); + +const BUCKET = 'test-bucket'; + +const { + PUBLISHED_FILES, + buildSuffixes, + validateS3Env, + publish, + getNameInBucket, + getLocalFile, +} = require('../publish-to-aws'); + +let server; +let s3Client; + +beforeAll(async () => { + server = await createFakeS3().start(); + server.createBucket(BUCKET); + + s3Client = new S3({ + endpoint: server.address, + region: 'us-east-1', + credentials: { accessKeyId: 'test', secretAccessKey: 'test' }, + forcePathStyle: true, + }); +}); + +afterAll(async () => { + await server?.stop(); +}); + +beforeEach(() => { + server.reset(); +}); + +async function getObjectBody(key) { + const response = await s3Client.send( + new GetObjectCommand({ Bucket: BUCKET, Key: key }) + ); + return response.Body.transformToString(); +} + +describe('buildSuffixes', () => { + it('should add -latest and commit sha for master', () => { + const result = buildSuffixes({ + isMaster: true, + headSha: 'abc123', + tagName: null, + }); + expect(result).toEqual(['-latest', '-abc123']); + }); + + it('should add tag suffix for valid semver tag', () => { + const result = buildSuffixes({ + isMaster: false, + headSha: 'abc123', + tagName: '4.7.0', + }); + expect(result).toEqual(['-4.7.0']); + }); + + it('should add both master and tag suffixes when on master with a tag', () => { + const result = buildSuffixes({ + isMaster: true, + headSha: 'abc123', + tagName: '4.7.0', + }); + expect(result).toEqual(['-latest', '-abc123', '-4.7.0']); + }); + + it('should return empty array for non-master with no valid tag', () => { + const result = buildSuffixes({ + isMaster: false, + headSha: 'abc123', + tagName: null, + }); + expect(result).toEqual([]); + }); + + it('should ignore invalid semver tags', () => { + const result = buildSuffixes({ + isMaster: false, + headSha: 'abc123', + tagName: 'not-semver', + }); + expect(result).toEqual([]); + }); +}); + +describe('getNameInBucket', () => { + it('should insert suffix before .js extension', () => { + expect(getNameInBucket('handlebars.js', '-latest')).toBe( + 'handlebars-latest.js' + ); + }); + + it('should handle .min.js files', () => { + expect(getNameInBucket('handlebars.min.js', '-4.7.0')).toBe( + 'handlebars.min-4.7.0.js' + ); + }); + + it('should handle runtime files', () => { + expect(getNameInBucket('handlebars.runtime.js', '-abc123')).toBe( + 'handlebars.runtime-abc123.js' + ); + }); +}); + +describe('getLocalFile', () => { + it('should prefix with dist/', () => { + expect(getLocalFile('handlebars.js')).toBe('dist/handlebars.js'); + }); +}); + +describe('validateS3Env', () => { + const S3_KEYS = [ + 'S3_BUCKET_NAME', + 'S3_REGION', + 'S3_ACCESS_KEY_ID', + 'S3_SECRET_ACCESS_KEY', + ]; + const saved = {}; + + beforeEach(() => { + for (const key of S3_KEYS) { + saved[key] = process.env[key]; + } + }); + + afterEach(() => { + for (const key of S3_KEYS) { + if (saved[key] === undefined) { + delete process.env[key]; + } else { + process.env[key] = saved[key]; + } + } + }); + + it('should throw when S3 env vars are missing', () => { + for (const key of S3_KEYS) { + delete process.env[key]; + } + + expect(() => validateS3Env()).toThrow('Missing S3 config values'); + }); + + it('should not throw when all S3 env vars are set', () => { + process.env.S3_BUCKET_NAME = 'test-bucket'; + process.env.S3_REGION = 'us-east-1'; + process.env.S3_ACCESS_KEY_ID = 'key'; + process.env.S3_SECRET_ACCESS_KEY = 'secret'; + + expect(() => validateS3Env()).not.toThrow(); + }); +}); + +describe('publish to S3', () => { + const overrides = {}; + + beforeAll(() => { + overrides.s3Client = s3Client; + overrides.bucket = BUCKET; + }); + + it('should upload all 4 files for a single suffix', async () => { + await publish(['-latest'], overrides); + + for (const filename of PUBLISHED_FILES) { + const key = getNameInBucket(filename, '-latest'); + const body = await getObjectBody(key); + const localContent = fs.readFileSync(getLocalFile(filename), 'utf8'); + expect(body).toBe(localContent); + } + }); + + it('should upload files for multiple suffixes', async () => { + await publish(['-latest', '-abc123'], overrides); + + for (const suffix of ['-latest', '-abc123']) { + for (const filename of PUBLISHED_FILES) { + const key = getNameInBucket(filename, suffix); + const body = await getObjectBody(key); + expect(body).toBeTruthy(); + } + } + }); + + it('should upload correct content from dist/', async () => { + await publish(['-v1.0.0'], overrides); + + const key = getNameInBucket('handlebars.js', '-v1.0.0'); + const uploaded = await getObjectBody(key); + const local = fs.readFileSync('dist/handlebars.js', 'utf8'); + expect(uploaded).toBe(local); + }); + + it('should produce correct keys for a version tag', async () => { + await publish(['-4.7.0'], overrides); + + const expectedKeys = PUBLISHED_FILES.map((f) => + getNameInBucket(f, '-4.7.0') + ); + + for (const key of expectedKeys) { + const body = await getObjectBody(key); + expect(body).toBeTruthy(); + } + + expect(expectedKeys).toEqual([ + 'handlebars-4.7.0.js', + 'handlebars.min-4.7.0.js', + 'handlebars.runtime-4.7.0.js', + 'handlebars.runtime.min-4.7.0.js', + ]); + }); +}); diff --git a/tasks/util/async-grunt-task.js b/tasks/util/async-grunt-task.js deleted file mode 100644 index 432d68afd..000000000 --- a/tasks/util/async-grunt-task.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { createRegisterAsyncTaskFn }; - -function createRegisterAsyncTaskFn(grunt) { - return function registerAsyncTask(name, asyncFunction) { - grunt.registerTask(name, function () { - asyncFunction() - .catch((error) => { - grunt.fatal(error); - }) - .finally(this.async()); - }); - }; -} diff --git a/tasks/version.js b/tasks/version.js index 4c7749873..39bf11da6 100644 --- a/tasks/version.js +++ b/tasks/version.js @@ -1,63 +1,68 @@ +const fs = require('fs'); const { execSync } = require('child_process'); const git = require('./util/git'); const semver = require('semver'); -const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); - -module.exports = function (grunt) { - const registerAsyncTask = createRegisterAsyncTaskFn(grunt); - - registerAsyncTask('version', async () => { - const pkg = grunt.config('pkg'); - const version = grunt.option('ver'); - if (!semver.valid(version)) { - throw new Error( - 'Must provide a version number (Ex: --ver=1.0.0):\n\t' + - version + - '\n\n' - ); - } - pkg.version = version; - grunt.config('pkg', pkg); - - const replaceSpec = [ - { - path: 'lib/handlebars/base.js', - regex: /const VERSION = ['"](.*)['"];/, - replacement: `const VERSION = '${version}';`, - }, - { - path: 'components/bower.json', - regex: /"version":.*/, - replacement: `"version": "${version}",`, - }, - { - path: 'components/package.json', - regex: /"version":.*/, - replacement: `"version": "${version}",`, - }, - { - path: 'components/handlebars.js.nuspec', - regex: /.*<\/version>/, - replacement: `${version}`, - }, - ]; - - await Promise.all( - replaceSpec.map((replaceSpec) => - replaceAndAdd( - replaceSpec.path, - replaceSpec.regex, - replaceSpec.replacement - ) - ) - ); - execSync('npm run build', { stdio: 'inherit' }); - }); - async function replaceAndAdd(path, regex, value) { - let content = grunt.file.read(path); - content = content.replace(regex, value); - grunt.file.write(path, content); - await git.add(path); +async function main() { + const version = process.argv[2]; + if (!semver.valid(version)) { + throw new Error( + 'Must provide a valid semver version as first argument (e.g.: node tasks/version.js 1.0.0):\n\t' + + version + + '\n\n' + ); } -}; + + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + pkg.version = version; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); + await git.add('package.json'); + + const replaceSpec = [ + { + path: 'lib/handlebars/base.js', + regex: /const VERSION = ['"](.*)['"];/, + replacement: `const VERSION = '${version}';`, + }, + { + path: 'components/bower.json', + regex: /"version":.*/, + replacement: `"version": "${version}",`, + }, + { + path: 'components/package.json', + regex: /"version":.*/, + replacement: `"version": "${version}",`, + }, + { + path: 'components/handlebars.js.nuspec', + regex: /.*<\/version>/, + replacement: `${version}`, + }, + ]; + + await Promise.all( + replaceSpec.map((spec) => + replaceAndAdd(spec.path, spec.regex, spec.replacement) + ) + ); + + execSync('npm run build', { stdio: 'inherit' }); +} + +async function replaceAndAdd(filePath, regex, value) { + let content = fs.readFileSync(filePath, 'utf8'); + content = content.replace(regex, value); + fs.writeFileSync(filePath, content); + await git.add(filePath); +} + +module.exports = { replaceAndAdd }; + +if (require.main === module) { + main().catch((err) => { + // eslint-disable-next-line no-console + console.error(err); + process.exit(1); + }); +} diff --git a/tests/browser/README.md b/tests/browser/README.md index 74d3d3c71..b04bc0ff7 100644 --- a/tests/browser/README.md +++ b/tests/browser/README.md @@ -8,7 +8,7 @@ Execute the following commands in the project root: ```bash npm install -npx grunt prepare +npm run build docker pull mcr.microsoft.com/playwright:focal docker run -it --rm --volume $(pwd):/srv/app --workdir /srv/app --ipc=host mcr.microsoft.com/playwright:focal npm run test:browser ``` diff --git a/vitest.config.js b/vitest.config.js index b475d4992..6cf88605b 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -17,6 +17,7 @@ export default defineConfig({ test: { name: 'tasks', include: ['tasks/tests/*.test.js'], + exclude: ['tasks/tests/publish-to-aws.test.js'], globals: true, pool: 'forks', }, @@ -28,6 +29,14 @@ export default defineConfig({ globals: true, }, }, + { + test: { + name: 'publish', + include: ['tasks/tests/publish-to-aws.test.js'], + globals: true, + pool: 'forks', + }, + }, { test: { name: 'browser',