diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e11790d..e1bc9e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,116 @@ +## [1.20.0-stage.16](https://github.com/aziontech/lib/compare/v1.20.0-stage.15...v1.20.0-stage.16) (2025-06-20) + + +### Bug Fixes + +* rename skipProjectBuild to skipFrameworkBuild in BuildContext (#180) ([5252f0a](https://github.com/aziontech/lib/commit/5252f0acfb43a296bcdd291524a5b62de01df75d)) + +## [1.20.0-stage.15](https://github.com/aziontech/lib/compare/v1.20.0-stage.14...v1.20.0-stage.15) (2025-06-20) + + +### Bug Fixes + +* **presets:** astro prebuild ([846990f](https://github.com/aziontech/lib/commit/846990f63f4b194e5f9b3e82c687be8f9ede1a65)) +* rm worker property ([8673494](https://github.com/aziontech/lib/commit/8673494eb1cf86de4544a7791db9524866b7ddbb)) + +## [1.20.0-stage.14](https://github.com/aziontech/lib/compare/v1.20.0-stage.13...v1.20.0-stage.14) (2025-06-20) + + +### Features + +* add OpenNextjs preset (#179) ([ca726ad](https://github.com/aziontech/lib/commit/ca726adc772783520e3fa9aa7f39b5beb812c8b1)) + +## [1.20.0-stage.13](https://github.com/aziontech/lib/compare/v1.20.0-stage.12...v1.20.0-stage.13) (2025-06-20) + + +### Bug Fixes + +* **preset:** update ruleset of html preset ([90b0def](https://github.com/aziontech/lib/commit/90b0def35c64370cc67c523f5ef95bb2979663b6)) + +## [1.20.0-stage.12](https://github.com/aziontech/lib/compare/v1.20.0-stage.11...v1.20.0-stage.12) (2025-06-18) + + +### Reverts + +* api v4 (#176) ([e93e073](https://github.com/aziontech/lib/commit/e93e07306609e3df88ffce7e4a56cf2f414f2640)) + +## [1.20.0-stage.11](https://github.com/aziontech/lib/compare/v1.20.0-stage.10...v1.20.0-stage.11) (2025-06-18) + + +### Bug Fixes + +* **presets:** add missing prebuild command in preact preset ([8674785](https://github.com/aziontech/lib/commit/86747855fc8f7297d9a937a3c1eff190eb8a5def)) + +## [1.20.0-stage.10](https://github.com/aziontech/lib/compare/v1.20.0-stage.9...v1.20.0-stage.10) (2025-06-09) + + +### Bug Fixes + +* add polyfill for clearInterval and update injection in unenv preset (#172) ([ea99874](https://github.com/aziontech/lib/commit/ea99874afcab25e0144b374938f704b2e9205987)) + +## [1.20.0-stage.9](https://github.com/aziontech/lib/compare/v1.20.0-stage.8...v1.20.0-stage.9) (2025-06-06) + + +### Bug Fixes + +* polyfills for Node.js compatibility (#170) ([329f4c4](https://github.com/aziontech/lib/commit/329f4c41af43f8bf9ccede25a14605a8f34bdc35)) + +## [1.20.0-stage.8](https://github.com/aziontech/lib/compare/v1.20.0-stage.7...v1.20.0-stage.8) (2025-06-03) + + +### Bug Fixes + +* api v4 (#168) ([dc33e5a](https://github.com/aziontech/lib/commit/dc33e5a9cfe9bd069d5bb5fd61fe026ddde53dcb)) + +## [1.20.0-stage.7](https://github.com/aziontech/lib/compare/v1.20.0-stage.6...v1.20.0-stage.7) (2025-06-02) + + +### Bug Fixes + +* streamline stream polyfills and enhance process, module, setInterval (#169) ([118f7bb](https://github.com/aziontech/lib/commit/118f7bb5ae501df4eb1c8e96fed7a976fcbb7f5d)) + +## [1.20.0-stage.6](https://github.com/aziontech/lib/compare/v1.20.0-stage.5...v1.20.0-stage.6) (2025-05-28) + + +### Features + +* purge api v4 (#167) ([f779d6a](https://github.com/aziontech/lib/commit/f779d6af4f2c9fd03fdce45d851f72347c21f3b9)) + +## [1.20.0-stage.5](https://github.com/aziontech/lib/compare/v1.20.0-stage.4...v1.20.0-stage.5) (2025-05-28) + + +### Bug Fixes + +* revert exported name (presets) ([94a1739](https://github.com/aziontech/lib/commit/94a173990515dc17fcc954baa3542c4645a6fb59)) + +## [1.20.0-stage.4](https://github.com/aziontech/lib/compare/v1.20.0-stage.3...v1.20.0-stage.4) (2025-05-27) + + +### Features + +* **config:** azion api v4 (#161) ([49c3f02](https://github.com/aziontech/lib/commit/49c3f02aa39d5e24eb2141db2370a26e63f8fe10)) + +## [1.20.0-stage.3](https://github.com/aziontech/lib/compare/v1.20.0-stage.2...v1.20.0-stage.3) (2025-05-15) + + +### Bug Fixes + +* wasm-image-processor resize wrapper (#164) ([a02d941](https://github.com/aziontech/lib/commit/a02d941c90360f1b8c10076ccb2b761f3ce62f2e)) + +## [1.20.0-stage.2](https://github.com/aziontech/lib/compare/v1.20.0-stage.1...v1.20.0-stage.2) (2025-05-13) + + +### Bug Fixes + +* add Azion.Storage to globalThis for polyfill (#163) ([cd659db](https://github.com/aziontech/lib/commit/cd659dbd9afbbe5a7ed45e0d89f59e0fb76792d5)) + +## [1.20.0-stage.1](https://github.com/aziontech/lib/compare/v1.19.1...v1.20.0-stage.1) (2025-05-05) + + +### Features + +* upgrade unenv 1.x to 2.x (#159) ([60ef725](https://github.com/aziontech/lib/commit/60ef7255d78c4f922b8d3efdc8cd4518a54ffaff)) + ### [1.19.1](https://github.com/aziontech/lib/compare/v1.19.0...v1.19.1) (2025-04-22) diff --git a/README.md b/README.md index 96a22a48..d5eaf324 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,6 @@ const config = { entry: './src/index.js', preset: 'react', polyfills: true, - worker: true, }, domain: { name: 'example.com', @@ -302,7 +301,6 @@ const config = defineConfig({ }, }, polyfills: true, - worker: true, extend: (config) => { // Customize bundler configuration return { @@ -394,7 +392,6 @@ export default defineConfig({ // Other build configurations entry: './src/index.ts', polyfills: true, - worker: true, memoryFS: { injectionDirs: ['./src/inject'], removePathPrefix: './src', diff --git a/package-lock.json b/package-lock.json index d98379ee..84963ea7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "azion", - "version": "1.19.0", + "version": "1.19.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "azion", - "version": "1.19.0", + "version": "1.19.1", "license": "MIT", "workspaces": [ "packages/*" @@ -21,6 +21,7 @@ "ajv": "^8.17.1", "ajv-errors": "^3.0.0", "ajv-keywords": "^5.1.0", + "assert-browserify": "^2.0.0", "babel-loader": "^9.2.1", "browserify-zlib": "^0.2.0", "chalk": "^5.3.0", @@ -39,20 +40,15 @@ "pcre-to-regexp": "^1.1.0", "progress": "^2.0.3", "signale": "^1.4.0", - "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "string_decoder": "^1.3.0", "timers-browserify": "^2.0.12", - "unenv": "^1.10.0", + "unenv": "^2.0.0-rc.15", "url": "^0.11.4", "util": "^0.12.5", "vm-browserify": "^1.1.2", "webpack": "^5.97.1" }, - "bin": { - "azion": "bin/azion", - "azlib": "bin/azion" - }, "devDependencies": { "@commitlint/cli": "^18.4.1", "@commitlint/config-conventional": "^18.4.0", @@ -5818,6 +5814,18 @@ "node": ">=12.0.0" } }, + "node_modules/assert-browserify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert-browserify/-/assert-browserify-2.0.0.tgz", + "integrity": "sha512-SJvtrHmyaOT57oKWIpzWZr2hLkFyXjg5ajNT+RHvd9fhpruhrJF0OYT0yy8rIgvSn3xQp/VpLQAOwO0KNVKrJw==", + "license": "MIT", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -6097,6 +6105,32 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -6220,6 +6254,27 @@ "node": ">= 0.12" } }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/browserify-sign/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6239,6 +6294,21 @@ } ] }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", @@ -6766,6 +6836,7 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.0.tgz", "integrity": "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==", + "dev": true, "engines": { "node": "^14.18.0 || >=16.10.0" } @@ -6888,7 +6959,8 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/cosmiconfig": { "version": "8.3.6", @@ -7383,6 +7455,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/defu": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", @@ -7514,6 +7603,32 @@ "readable-stream": "^2.0.2" } }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -7773,6 +7888,12 @@ "node": ">= 0.4" } }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", @@ -8140,6 +8261,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/exsolve": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", + "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8524,6 +8651,32 @@ "readable-stream": "^2.0.0" } }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -8671,6 +8824,22 @@ "traverse": "0.6.8" } }, + "node_modules/git-log-parser/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/git-log-parser/node_modules/split2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", @@ -8680,6 +8849,16 @@ "through2": "~2.0.0" } }, + "node_modules/git-log-parser/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/git-log-parser/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -9319,6 +9498,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -9429,7 +9624,8 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -11355,11 +11551,6 @@ "lodash": "^4.17.21" } }, - "node_modules/node-fetch-native": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz", - "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==" - }, "node_modules/node-inspect-extracted": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/node-inspect-extracted/-/node-inspect-extracted-1.1.0.tgz", @@ -14730,6 +14921,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -15091,9 +15313,10 @@ } }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" }, "node_modules/pbkdf2": { "version": "3.1.2", @@ -15423,7 +15646,8 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", @@ -15835,28 +16059,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -16936,6 +17138,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", "dependencies": { "inherits": "~2.0.4", "readable-stream": "^3.5.0" @@ -16964,10 +17167,37 @@ "readable-stream": "^2.0.2" } }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-combiner2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/stream-http": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "license": "MIT", "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.4", @@ -17259,6 +17489,32 @@ "node": ">= 0.8.0" } }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/temp-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", @@ -17925,6 +18181,12 @@ } } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz", @@ -17978,15 +18240,16 @@ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/unenv": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.10.0.tgz", - "integrity": "sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==", + "version": "2.0.0-rc.15", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.15.tgz", + "integrity": "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==", + "license": "MIT", "dependencies": { - "consola": "^3.2.3", "defu": "^6.1.4", - "mime": "^3.0.0", - "node-fetch-native": "^1.6.4", - "pathe": "^1.1.2" + "exsolve": "^1.0.4", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "ufo": "^1.5.4" } }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -18542,7 +18805,7 @@ "string_decoder": "^1.3.0", "timers-browserify": "^2.0.12", "ts-loader": "^9.5.2", - "unenv": "^1.10.0", + "unenv": "^2.0.0-rc.15", "url": "^0.11.4", "util": "^0.12.5", "vm-browserify": "^1.1.2", diff --git a/package.json b/package.json index 2f3e72b2..c7a80965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "azion", - "version": "1.19.1", + "version": "1.20.0-stage.16", "description": "Azion Packages for Edge Computing.", "scripts": { "prepare": "husky", @@ -231,6 +231,7 @@ "ajv": "^8.17.1", "ajv-errors": "^3.0.0", "ajv-keywords": "^5.1.0", + "assert-browserify": "^2.0.0", "babel-loader": "^9.2.1", "browserify-zlib": "^0.2.0", "chalk": "^5.3.0", @@ -249,11 +250,10 @@ "pcre-to-regexp": "^1.1.0", "progress": "^2.0.3", "signale": "^1.4.0", - "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "string_decoder": "^1.3.0", "timers-browserify": "^2.0.12", - "unenv": "^1.10.0", + "unenv": "^2.0.0-rc.15", "url": "^0.11.4", "util": "^0.12.5", "vm-browserify": "^1.1.2", diff --git a/packages/bundler/package.json b/packages/bundler/package.json index 62b892c4..bceb6300 100644 --- a/packages/bundler/package.json +++ b/packages/bundler/package.json @@ -46,7 +46,7 @@ "string_decoder": "^1.3.0", "timers-browserify": "^2.0.12", "ts-loader": "^9.5.2", - "unenv": "^1.10.0", + "unenv": "^2.0.0-rc.15", "url": "^0.11.4", "util": "^0.12.5", "vm-browserify": "^1.1.2", diff --git a/packages/bundler/src/bundlers/esbuild/esbuild.config.ts b/packages/bundler/src/bundlers/esbuild/esbuild.config.ts index 61e233a9..5c03279e 100644 --- a/packages/bundler/src/bundlers/esbuild/esbuild.config.ts +++ b/packages/bundler/src/bundlers/esbuild/esbuild.config.ts @@ -6,6 +6,8 @@ export default { platform: 'browser', mainFields: ['browser', 'module', 'main'], target: 'es2022', + keepNames: true, + allowOverwrite: true, loader: { '.js': 'js', }, diff --git a/packages/bundler/src/bundlers/esbuild/esbuild.ts b/packages/bundler/src/bundlers/esbuild/esbuild.ts index 68cb16a4..9dad3384 100644 --- a/packages/bundler/src/bundlers/esbuild/esbuild.ts +++ b/packages/bundler/src/bundlers/esbuild/esbuild.ts @@ -32,12 +32,19 @@ const bundlerPlugins = createBundlerPlugins + (config: ESBuildConfig, ctx: BuildContext) => (content: string | undefined): ESBuildConfig => { if (!content) return config; - config.banner = config.banner || {}; + config.banner.js = config.banner.js ? `${config.banner.js} ${content}` : content; + if (ctx.production) { + config.banner.js += ` +// This file is generated by Azion. Do not edit it manually. +// Dynamic require is not supported in production mode. +import { createRequire as _createRequire } from "node:module"; +const require = _createRequire(import.meta.url);`; + } return config; }; @@ -66,7 +73,7 @@ export const createAzionESBuildConfig = (buildConfig: BuildConfiguration, ctx: B flow([ () => bundlerPlugins.applyPolyfills(ctx)(config)(buildConfig), () => bundlerPlugins.applyAzionModule(ctx)(config), - () => applyContentInjection(config)(buildConfig?.setup?.contentToInject), + () => applyContentInjection(config, ctx)(buildConfig?.setup?.contentToInject), () => applyDefineVars(config, 'esbuild')(buildConfig?.setup?.defineVars), () => extendConfig(config)(buildConfig.extend as (config: ESBuildConfiguration) => ESBuildConfiguration), ])(config), diff --git a/packages/bundler/src/bundlers/esbuild/plugins/node-polyfills/node-polyfills.ts b/packages/bundler/src/bundlers/esbuild/plugins/node-polyfills/node-polyfills.ts index eac748b5..49164a76 100644 --- a/packages/bundler/src/bundlers/esbuild/plugins/node-polyfills/node-polyfills.ts +++ b/packages/bundler/src/bundlers/esbuild/plugins/node-polyfills/node-polyfills.ts @@ -5,12 +5,20 @@ import fs from 'fs'; import { createRequire } from 'module'; import { builtinModules } from 'node:module'; import path from 'path'; -import { env, nodeless } from 'unenv'; +import { defineEnv } from 'unenv'; import helper from './helper/index'; const requireCustom = createRequire(import.meta.url); -const { alias, inject, polyfill, external } = env(nodeless, unenvPresetAzion); +const { env } = defineEnv({ + nodeCompat: true, + resolve: false, + overrides: { + ...unenvPresetAzion, + }, +}); + +const { alias, inject, polyfill, external } = env; interface BuildOptions { define?: Record; @@ -21,14 +29,12 @@ interface GlobalInjectResult { exportName: string; } -type GlobalInjectValue = string | string[] | [string, string]; - /** * Get global inject * @param {*} globalInject Global inject * @returns {*} Return import statement and export name */ -function getGlobalInject(globalInject: GlobalInjectValue): GlobalInjectResult { +function getGlobalInject(globalInject: string | string[]): GlobalInjectResult { if (typeof globalInject === 'string') { return { importStatement: `import globalVar from "${globalInject}";`, @@ -128,7 +134,7 @@ function nodeBuiltInModules( // if polyfill is not found, check if the module is external if (!polyfillResult && externalModule) { return { - path: args.path, + path: args.path.startsWith('node:') ? args.path : `node:${args.path}`, external: externalModule.includes(args.path), }; } @@ -186,7 +192,8 @@ function handleNodeJSGlobals(build: PluginBuild, getAbsolutePath: (moving: strin if (!match?.[1]) throw new Error(`Invalid global name: ${args.path}`); const globalName = match[1]; - const { importStatement, exportName } = getGlobalInject(inject[globalName]); + + const { importStatement, exportName } = getGlobalInject(inject[globalName] as string | string[]); return { contents: ` @@ -259,7 +266,7 @@ function defineNextJsRuntime(options: BuildOptions) { // eslint-disable-next-line no-param-reassign options.define = { ...options.define, - 'process.env.NEXT_RUNTIME': '"edge"', + 'process.env.NEXT_RUNTIME': options.define?.['process.env.NEXT_RUNTIME'] || '"edge"', 'process.env.NEXT_COMPUTE_JS': 'true', 'process.env.__NEXT_BUILD_ID': `"${buildId}"`, }; diff --git a/packages/bundler/src/bundlers/webpack/plugins/node-polyfills/node-polyfills.ts b/packages/bundler/src/bundlers/webpack/plugins/node-polyfills/node-polyfills.ts index f36a200c..dff9c656 100644 --- a/packages/bundler/src/bundlers/webpack/plugins/node-polyfills/node-polyfills.ts +++ b/packages/bundler/src/bundlers/webpack/plugins/node-polyfills/node-polyfills.ts @@ -3,12 +3,20 @@ import { getAbsoluteDirPath } from 'azion/utils/node'; import fs from 'fs'; import { createRequire } from 'module'; import path from 'path'; -import { env, nodeless } from 'unenv'; +import { defineEnv } from 'unenv'; import { Compiler, WebpackPluginInstance } from 'webpack'; const require = createRequire(import.meta.url); -const { alias, inject, polyfill, external } = env(nodeless, unenvPresetAzion); +const { env } = defineEnv({ + nodeCompat: true, + resolve: false, + overrides: { + ...unenvPresetAzion, + }, +}); + +const { alias, inject, polyfill, external } = env; class NodePolyfillPlugin implements WebpackPluginInstance { private INTERNAL_POLYFILL_PATH = '/polyfills'; diff --git a/packages/bundler/src/helpers/azion-local-polyfills.ts b/packages/bundler/src/helpers/azion-local-polyfills.ts index 4f015522..d5dd149c 100644 --- a/packages/bundler/src/helpers/azion-local-polyfills.ts +++ b/packages/bundler/src/helpers/azion-local-polyfills.ts @@ -13,5 +13,6 @@ export default { ['azion:storage', `${externalPolyfillsPath}/storage/storage.polyfills.js`], ['Azion.env', `${externalPolyfillsPath}/env-vars/env-vars.polyfills.js`], ['Azion.networkList', `${externalPolyfillsPath}/network-list/network-list.polyfills.js`], + ['Azion.Storage', `${externalPolyfillsPath}/storage/storage.polyfills.js`], ]), }; diff --git a/packages/bundler/src/polyfills/azion/storage/storage.polyfills.js b/packages/bundler/src/polyfills/azion/storage/storage.polyfills.js index c1893280..d067959b 100644 --- a/packages/bundler/src/polyfills/azion/storage/storage.polyfills.js +++ b/packages/bundler/src/polyfills/azion/storage/storage.polyfills.js @@ -197,3 +197,6 @@ export class StorageObjectList { this.entries = list; } } + +globalThis.Azion = globalThis.Azion || {}; +globalThis.Azion.Storage = Storage; diff --git a/packages/bundler/src/polyfills/crypto/context/crypto.context.js b/packages/bundler/src/polyfills/crypto/context/crypto.context.js new file mode 100644 index 00000000..1e023541 --- /dev/null +++ b/packages/bundler/src/polyfills/crypto/context/crypto.context.js @@ -0,0 +1,68 @@ +/* eslint-disable */ +import * as crypto from 'node:crypto'; + +export var { Cipher } = crypto; +export var { Decipher } = crypto; +export var { DiffieHellman } = crypto; +export var { DiffieHellmanGroup } = crypto; +export var { Hash } = crypto; +export var { Hmac } = crypto; +export var { Sign } = crypto; +export var { Verify } = crypto; +export var { constants } = crypto; +export var { createCipheriv } = crypto; +export var { createDecipheriv } = crypto; +export var { createDiffieHellman } = crypto; +export var { createDiffieHellmanGroup } = crypto; +export var { createECDH } = crypto; +export var { createHash } = crypto; +export var { createHmac } = crypto; +export var { createSign } = crypto; +export var { createVerify } = crypto; +export var { getCiphers } = crypto; +export var { getDiffieHellman } = crypto; +export var { getHashes } = crypto; +export var { pbkdf2 } = crypto; +export var { pbkdf2Sync } = crypto; +export var { privateDecrypt } = crypto; +export var { privateEncrypt } = crypto; +export var { pseudoRandomBytes } = crypto; +export var { publicDecrypt } = crypto; +export var { publicEncrypt } = crypto; +export var { randomBytes } = crypto; +export var { randomFill } = crypto; +export var { randomFillSync } = crypto; + +export default { + Cipher, + Decipher, + DiffieHellman, + DiffieHellmanGroup, + Hash, + Hmac, + Sign, + Verify, + constants, + createCipheriv, + createDecipheriv, + createDiffieHellman, + createDiffieHellmanGroup, + createECDH, + createHash, + createHmac, + createSign, + createVerify, + getCiphers, + getDiffieHellman, + getHashes, + pbkdf2, + pbkdf2Sync, + privateDecrypt, + privateEncrypt, + pseudoRandomBytes, + publicDecrypt, + publicEncrypt, + randomBytes, + randomFill, + randomFillSync, +}; diff --git a/packages/bundler/src/polyfills/crypto/context/index.js b/packages/bundler/src/polyfills/crypto/context/index.js new file mode 100644 index 00000000..b25ab622 --- /dev/null +++ b/packages/bundler/src/polyfills/crypto/context/index.js @@ -0,0 +1,3 @@ +import cryptoContext from './crypto.context.js'; + +export default cryptoContext; diff --git a/packages/bundler/src/polyfills/crypto/crypto.polyfills.js b/packages/bundler/src/polyfills/crypto/crypto.polyfills.js new file mode 100644 index 00000000..53215496 --- /dev/null +++ b/packages/bundler/src/polyfills/crypto/crypto.polyfills.js @@ -0,0 +1,73 @@ +/* eslint-disable */ +/** This polyfill is referenced in #build/bundlers/polyfills/polyfills-manager.js + * + * CRYPTO_CONTEXT is defined in runtime.env.js for use on the local server + */ + +/* eslint-disable */ + +export var { Cipher } = CRYPTO_CONTEXT.cryptoContext; +export var { Decipher } = CRYPTO_CONTEXT.cryptoContext; +export var { DiffieHellman } = CRYPTO_CONTEXT.cryptoContext; +export var { DiffieHellmanGroup } = CRYPTO_CONTEXT.cryptoContext; +export var { Hash } = CRYPTO_CONTEXT.cryptoContext; +export var { Hmac } = CRYPTO_CONTEXT.cryptoContext; +export var { Sign } = CRYPTO_CONTEXT.cryptoContext; +export var { Verify } = CRYPTO_CONTEXT.cryptoContext; +export var { constants } = CRYPTO_CONTEXT.cryptoContext; +export var { createCipheriv } = CRYPTO_CONTEXT.cryptoContext; +export var { createDecipheriv } = CRYPTO_CONTEXT.cryptoContext; +export var { createDiffieHellman } = CRYPTO_CONTEXT.cryptoContext; +export var { createDiffieHellmanGroup } = CRYPTO_CONTEXT.cryptoContext; +export var { createECDH } = CRYPTO_CONTEXT.cryptoContext; +export var { createHash } = CRYPTO_CONTEXT.cryptoContext; +export var { createHmac } = CRYPTO_CONTEXT.cryptoContext; +export var { createSign } = CRYPTO_CONTEXT.cryptoContext; +export var { createVerify } = CRYPTO_CONTEXT.cryptoContext; +export var { getCiphers } = CRYPTO_CONTEXT.cryptoContext; +export var { getDiffieHellman } = CRYPTO_CONTEXT.cryptoContext; +export var { getHashes } = CRYPTO_CONTEXT.cryptoContext; +export var { pbkdf2 } = CRYPTO_CONTEXT.cryptoContext; +export var { pbkdf2Sync } = CRYPTO_CONTEXT.cryptoContext; +export var { privateDecrypt } = CRYPTO_CONTEXT.cryptoContext; +export var { privateEncrypt } = CRYPTO_CONTEXT.cryptoContext; +export var { pseudoRandomBytes } = CRYPTO_CONTEXT.cryptoContext; +export var { publicDecrypt } = CRYPTO_CONTEXT.cryptoContext; +export var { publicEncrypt } = CRYPTO_CONTEXT.cryptoContext; +export var { randomBytes } = CRYPTO_CONTEXT.cryptoContext; +export var { randomFill } = CRYPTO_CONTEXT.cryptoContext; +export var { randomFillSync } = CRYPTO_CONTEXT.cryptoContext; + +export default { + Cipher, + Decipher, + DiffieHellman, + DiffieHellmanGroup, + Hash, + Hmac, + Sign, + Verify, + constants, + createCipheriv, + createDecipheriv, + createDiffieHellman, + createDiffieHellmanGroup, + createECDH, + createHash, + createHmac, + createSign, + createVerify, + getCiphers, + getDiffieHellman, + getHashes, + pbkdf2, + pbkdf2Sync, + privateDecrypt, + privateEncrypt, + pseudoRandomBytes, + publicDecrypt, + publicEncrypt, + randomBytes, + randomFill, + randomFillSync, +}; diff --git a/packages/bundler/src/polyfills/crypto/index.js b/packages/bundler/src/polyfills/crypto/index.js new file mode 100644 index 00000000..5c6a2584 --- /dev/null +++ b/packages/bundler/src/polyfills/crypto/index.js @@ -0,0 +1,7 @@ +/** + * We are not exporting the crypto.polyfill.js from this structure due to the context definition in runtime.env.js. + * As we are proxying the Node.js crypto lib, it is not possible to export the crypto.polyfill.js file. + */ +import cryptoContext from './context/index.js'; + +export default { cryptoContext }; diff --git a/packages/bundler/src/polyfills/fs/context/fs.context.js b/packages/bundler/src/polyfills/fs/context/fs.context.js index d5d0afe6..641eb49e 100644 --- a/packages/bundler/src/polyfills/fs/context/fs.context.js +++ b/packages/bundler/src/polyfills/fs/context/fs.context.js @@ -9,6 +9,7 @@ export const { openSync, close, closeSync, + existsSync, stat, statSync, lstat, @@ -55,6 +56,7 @@ localFs.open = open; localFs.openSync = openSync; localFs.close = close; localFs.closeSync = closeSync; +localFs.existsSync = existsSync; localFs.stat = stat; localFs.statSync = statSync; localFs.lstat = lstat; diff --git a/packages/bundler/src/polyfills/fs/fs.polyfills.js b/packages/bundler/src/polyfills/fs/fs.polyfills.js index b990b379..1f171332 100644 --- a/packages/bundler/src/polyfills/fs/fs.polyfills.js +++ b/packages/bundler/src/polyfills/fs/fs.polyfills.js @@ -24,6 +24,11 @@ function closeSync(...args) { return FS_CONTEXT.closeSync(...args); } +function existsSync(path) { + path = join(BUILD_PATH_PREFIX, path); + return FS_CONTEXT.existsSync(path); +} + function stat(path, ...args) { path = join(BUILD_PATH_PREFIX, path); return FS_CONTEXT.stat(path, ...args); @@ -157,28 +162,16 @@ const W_OK = 2; const X_OK = 1; export { - promises, - open, - openSync, close, closeSync, - stat, - statSync, - lstat, - lstatSync, - readFile, - readFileSync, - readdir, - readdirSync, - mkdir, - rmdir, + constants, copyFile, cp, - writeFile, - rename, - realpath, - constants, + existsSync, F_OK, + lstat, + lstatSync, + mkdir, O_APPEND, O_CREAT, O_DIRECTORY, @@ -193,8 +186,21 @@ export { O_SYNC, O_TRUNC, O_WRONLY, + open, + openSync, + promises, R_OK, + readdir, + readdirSync, + readFile, + readFileSync, + realpath, + rename, + rmdir, + stat, + statSync, W_OK, + writeFile, X_OK, }; @@ -204,6 +210,7 @@ localFs.open = open; localFs.openSync = openSync; localFs.close = close; localFs.closeSync = closeSync; +localFs.existsSync = existsSync; localFs.stat = stat; localFs.statSync = statSync; localFs.lstat = lstat; diff --git a/packages/bundler/src/polyfills/index.d.ts b/packages/bundler/src/polyfills/index.d.ts index 778f22d8..7b43519e 100644 --- a/packages/bundler/src/polyfills/index.d.ts +++ b/packages/bundler/src/polyfills/index.d.ts @@ -11,4 +11,7 @@ declare module 'azion/bundler/polyfills' { export const NetworkListContext: any; export const fsContext: any; export const FirewallEventContext: any; + export const streamContext: any; + export const cryptoContext: any; + export const promisesContext: any; } diff --git a/packages/bundler/src/polyfills/index.js b/packages/bundler/src/polyfills/index.js index 733d853d..26131e71 100644 --- a/packages/bundler/src/polyfills/index.js +++ b/packages/bundler/src/polyfills/index.js @@ -5,17 +5,23 @@ import fetchContext from './azion/fetch/index.js'; import FirewallEventContext from './azion/firewall-event/index.js'; import NetworkListContext from './azion/network-list/index.js'; import { StorageContext } from './azion/storage/index.js'; +import cryptoContext from './crypto/index.js'; import { fsContext } from './fs/index.js'; +import promisesContext from './promises/index.js'; +import { streamContext } from './stream/index.js'; // TODO: transform polyfills to TypeScript export { AsyncHooksContext, + cryptoContext, EnvVarsContext, fetchContext, FetchEventContext, FirewallEventContext, fsContext, NetworkListContext, + promisesContext, StorageContext, + streamContext, }; diff --git a/packages/bundler/src/polyfills/promises/context/index.js b/packages/bundler/src/polyfills/promises/context/index.js new file mode 100644 index 00000000..4c68a3f6 --- /dev/null +++ b/packages/bundler/src/polyfills/promises/context/index.js @@ -0,0 +1,3 @@ +import promisesContext from './promises.context.js'; + +export default promisesContext; diff --git a/packages/bundler/src/polyfills/promises/context/promises.context.js b/packages/bundler/src/polyfills/promises/context/promises.context.js new file mode 100644 index 00000000..b8a8e0df --- /dev/null +++ b/packages/bundler/src/polyfills/promises/context/promises.context.js @@ -0,0 +1,13 @@ +globalThis.Promise = Promise || globalThis.Promise; + +globalThis.Promise.withResolvers = function () { + let resolve; + let reject; + const promise = new globalThis.Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve: resolve, reject: reject }; +}; + +export default globalThis.Promise.withResolvers; diff --git a/packages/bundler/src/polyfills/promises/index.js b/packages/bundler/src/polyfills/promises/index.js new file mode 100644 index 00000000..ce97339c --- /dev/null +++ b/packages/bundler/src/polyfills/promises/index.js @@ -0,0 +1,7 @@ +/** + * We are not exporting the promises.polyfill.js from this structure due to the context definition in runtime.env.js. + * As we are proxying the Node.js promises lib, it is not possible to export the promises.polyfill.js file. + */ +import promisesContext from './context/index.js'; + +export default promisesContext; diff --git a/packages/bundler/src/polyfills/stream/context/index.js b/packages/bundler/src/polyfills/stream/context/index.js new file mode 100644 index 00000000..d453fb08 --- /dev/null +++ b/packages/bundler/src/polyfills/stream/context/index.js @@ -0,0 +1,3 @@ +import streamContext from './stream.context.js'; + +export default streamContext; diff --git a/packages/bundler/src/polyfills/stream/context/stream.context.js b/packages/bundler/src/polyfills/stream/context/stream.context.js new file mode 100644 index 00000000..787a6f7b --- /dev/null +++ b/packages/bundler/src/polyfills/stream/context/stream.context.js @@ -0,0 +1,16 @@ +/* eslint-disable */ +import stream from 'node:stream'; + +const localStream = {}; +export const { Duplex, Writable, Readable, Transform, PassThrough, Stream } = stream; +export const { prototype } = stream; + +localStream.Duplex = Duplex; +localStream.Writable = Writable; +localStream.Readable = Readable; +localStream.Transform = Transform; +localStream.PassThrough = PassThrough; +localStream.Stream = Stream; +localStream.prototype = prototype; + +export default localStream; diff --git a/packages/bundler/src/polyfills/stream/index.js b/packages/bundler/src/polyfills/stream/index.js new file mode 100644 index 00000000..1be5acd7 --- /dev/null +++ b/packages/bundler/src/polyfills/stream/index.js @@ -0,0 +1,7 @@ +/** + * We are not exporting the async_hooks.polyfill.js from this structure due to the context definition in runtime.env.js. + * As we are proxying the Node.js async_hooks lib, it is not possible to export the async_hooks.polyfill.js file. + */ +import streamContext from './context/index.js'; + +export { streamContext }; diff --git a/packages/bundler/src/polyfills/stream/stream.polyfills.js b/packages/bundler/src/polyfills/stream/stream.polyfills.js new file mode 100644 index 00000000..a6e836da --- /dev/null +++ b/packages/bundler/src/polyfills/stream/stream.polyfills.js @@ -0,0 +1,129 @@ +/* eslint-disable */ +/** + * STREAM_CONTEXT is defined in runtime.env.js for use on the local server + */ + +const localStream = {}; +const { Duplex, Writable, Readable, Transform, PassThrough, Stream } = STREAM_CONTEXT; +export const { prototype } = STREAM_CONTEXT; + +localStream.Duplex = Duplex; +localStream.Writable = Writable; +localStream.Readable = Readable; +localStream.Transform = Transform; +localStream.PassThrough = PassThrough; +localStream.Stream = Stream; +localStream.prototype = prototype; + +Readable.toWeb = function (readable) { + let onData, onEnd, onError; + let closed = false; + const stream = new ReadableStream({ + start(controller) { + onData = (chunk) => { + if (!closed) controller.enqueue(chunk); + }; + onEnd = () => { + if (!closed) { + closed = true; + controller.close(); + } + }; + onError = (error) => { + if (!closed) { + closed = true; + controller.error(error); + } + }; + + readable.on('data', onData); + readable.on('end', onEnd); + readable.on('error', onError); + + readable.on('close', () => { + if (!closed) { + closed = true; + controller.close(); + } + }); + }, + cancel(reason) { + readable.off('data', onData); + readable.off('end', onEnd); + readable.off('error', onError); + if (typeof readable.destroy === 'function') { + readable.destroy(reason); + } + }, + }); + return stream; +}; + +Readable.fromWeb = function (webStream) { + const reader = webStream.getReader(); + return new Readable({ + async read(size) { + const { done, value } = await reader.read(); + if (done) { + return { done: true }; + } + return { done: false, value }; + }, + async destroy(error) { + await reader.cancel(error); + }, + }); +}; + +Writable.fromWeb = function (webStream) { + const writer = webStream.getWriter(); + + writer.closed.catch((error) => { + if (error) { + console.error('WritableStream closed with error:', error); + console.error('Error details:', error?.message, error?.stack); + } + }); + + return new Writable({ + write(chunk, encoding, callback) { + if (writer.desiredSize === null) { + const err = new Error('WritableStream is not writable or has been closed.'); + console.error(err.message); + callback(err); + return; + } + + writer + .write(chunk) + .then(() => callback(undefined)) + .catch((err) => { + callback(err); + }); + }, + final(callback) { + writer.ready + .then(() => { + return writer.close(); + }) + .then(() => callback(undefined)) + .catch((err) => { + callback(err); + }); + }, + destroy(error, callback) { + writer + .abort(error) + .then(() => { + callback(undefined); + }) + .catch((err) => { + callback(err); + }); + }, + }); +}; + +export { Duplex, PassThrough, Readable, Stream, Transform, Writable }; + +export default localStream; diff --git a/packages/config/README.md b/packages/config/README.md index 4561312d..a92d5119 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -304,15 +304,17 @@ Converts a Azion JSON configuration object to a AzionConfig object. Type definition for the build configuration. +> ⚠️ \*Deprecation Notice: +> Support for the webpack bundler will be discontinued in future releases. While it is still available for now, new features, fixes, and improvements will be focused exclusively on esbuild. We recommend migrating to esbuild as soon as possible to ensure compatibility and better performance in upcoming versions. + **Properties:** -- `bundler?: 'esbuild' | 'webpack'` - O empacotador a ser usado. -- `preset?: string | AzionBuildPreset` - O preset a ser usado, pode ser uma string ou um objeto AzionBuildPreset. -- `entry?: string | string[] | Record` - O arquivo de entrada, pode ser uma string, array de strings ou um objeto. -- `polyfills?: boolean` - Se deve incluir polyfills. -- `worker?: boolean` - Se deve construir um worker. -- `extend?: (context: T) => T` - Função para estender a configuração do bundler. -- `memoryFS?: { injectionDirs: string[], removePathPrefix: string }` - Configuração do sistema de arquivos em memória. +- \*`bundler?: 'esbuild' | 'webpack'` - The bundler to be used. Default is 'esbuild'. +- `preset?: string | AzionBuildPreset` - The preset to be used, can be a string or an AzionBuildPreset object. +- `entry?: string | string[] | Record` - The entry file, can be a string, an array of strings, or an object. +- `polyfills?: boolean` - Whether to include polyfills. +- `extend?: (context: T) => T` - Function to extend the bundler configuration. +- `memoryFS?: { injectionDirs: string[], removePathPrefix: string }` - In-memory file system configuration. ### `AzionBuildPreset` @@ -320,14 +322,14 @@ Type definition for the build preset. **Properties:** -- `config: AzionConfig` - A configuração do Azion. -- `handler?: (event: FetchEvent) => Promise` - Manipulador de eventos opcional. -- `prebuild?: (config: BuildConfiguration, ctx: BuildContext) => Promise` - Hook executado antes da construção. -- `postbuild?: (config: BuildConfiguration, ctx: BuildContext) => Promise` - Hook executado após a construção. -- `metadata: PresetMetadata` - Metadados do preset. - - `name: string` - Nome do preset. - - `registry?: string` - Registro do preset. - - `ext?: string` - Extensão do arquivo. +- `config: AzionConfig` - The Azion configuration. +- `handler?: (event: FetchEvent) => Promise` - Optional event handler. +- `prebuild?: (config: BuildConfiguration, ctx: BuildContext) => Promise` - Hook executed before the build process. +- `postbuild?: (config: BuildConfiguration, ctx: BuildContext) => Promise` - Hook executed after the build process. +- `metadata: PresetMetadata` - Preset metadata. + - `name: string` - Preset name. + - `registry?: string` - Preset registry. + - `ext?: string` - File extension. ### `AzionPrebuildResult` @@ -335,14 +337,14 @@ Type definition for the prebuild result. **Properties:** -- `filesToInject: string[]` - Arquivos a serem injetados na memória durante o processo de construção. -- `injection: object` - Configurações de injeção de código. - - `globals: object` - Variáveis globais a serem injetadas. - - `entry?: string` - Código no início do worker. - - `banner?: string` - Código no topo do worker. -- `bundler: object` - Configurações do empacotador. - - `defineVars: object` - Variáveis a serem definidas. - - `plugins: (EsbuildPlugin | WebpackPlugin)[]` - Plugins a serem usados. +- `filesToInject: string[]` - Files to be injected into memory during the build process. +- `injection: object` - Code injection settings. + - `globals: object` - Global variables to be injected. + - `entry?: string` - Code to run at the start of the worker. + - `banner?: string` - Code to place at the top of the worker. +- `bundler: object` - Bundler configuration. + - `defineVars: object` - Variables to be defined. + - `plugins: (EsbuildPlugin | WebpackPlugin)[]` - Plugins to be used. ### `BuildContext` @@ -350,24 +352,26 @@ Type definition for the build context. **Properties:** -- `production: boolean` - Se está em modo de produção. -- `handler: BuildEntryPoint` - O ponto de entrada da construção. +- `production: boolean` - Whether it is in production mode. +- `handler: BuildEntryPoint` - The build entry point. ### `BuildConfiguration` Type definition for the build configuration. +> ⚠️ \*Deprecation Notice: +> Support for the webpack bundler will be discontinued in future releases. While it is still available for now, new features, fixes, and improvements will be focused exclusively on esbuild. We recommend migrating to esbuild as soon as possible to ensure compatibility and better performance in upcoming versions. + **Properties:** -- `entry: Record` - Os pontos de entrada. -- `baseOutputDir?: string` - Diretório base de saída. -- `preset: AzionBuildPreset` - O preset a ser usado. -- `setup: BundlerSetup` - Configuração do empacotador. -- `bundler?: 'webpack' | 'esbuild'` - O empacotador a ser usado. -- `polyfills?: boolean` - Se deve incluir polyfills. -- `worker?: boolean` - Se deve construir um worker. -- `extend?: (context: T) => T` - Função para estender a configuração do bundler. -- `memoryFS?: { injectionDirs: string[], removePathPrefix: string }` - Configuração do sistema de arquivos em memória. +- `entry: Record` - The entry points. +- `baseOutputDir?: string` - Base output directory. +- `preset: AzionBuildPreset` - The preset to be used. +- `setup: BundlerSetup` - Bundler configuration. +- \*`bundler?: 'webpack' | 'esbuild'` - The bundler to be used. +- `polyfills?: boolean` - Whether to include polyfills. +- `extend?: (context: T) => T` - Function to extend the bundler configuration. +- `memoryFS?: { injectionDirs: string[], removePathPrefix: string }` - In-memory file system configuration. ### `BundlerSetup` @@ -375,8 +379,8 @@ Type definition for the bundler setup. **Properties:** -- `contentToInject?: string` - Conteúdo a ser injetado. -- `defineVars?: Record` - Variáveis a serem definidas. +- `contentToInject?: string` - Content to be injected. +- `defineVars?: Record` - Variables to be defined. ### `PresetMetadata` @@ -384,9 +388,9 @@ Type definition for the preset metadata. **Properties:** -- `name: string` - Nome do preset. -- `registry?: string` - Registro do preset. -- `ext?: string` - Extensão do arquivo. +- `name: string` - Preset name. +- `registry?: string` - Preset registry. +- `ext?: string` - File extension. ### `AzionDomain` diff --git a/packages/config/src/configProcessor/helpers/schema.ts b/packages/config/src/configProcessor/helpers/schema.ts index 4880d56c..cdd292e9 100644 --- a/packages/config/src/configProcessor/helpers/schema.ts +++ b/packages/config/src/configProcessor/helpers/schema.ts @@ -492,10 +492,6 @@ const azionConfigSchema = { type: 'boolean', errorMessage: "The 'build.polyfills' must be a boolean", }, - worker: { - type: 'boolean', - errorMessage: "The 'build.worker' must be a boolean", - }, extend: { instanceof: 'Function', errorMessage: "The 'build.extend' must be a function", diff --git a/packages/config/src/types.ts b/packages/config/src/types.ts index 9095200c..6541e039 100644 --- a/packages/config/src/types.ts +++ b/packages/config/src/types.ts @@ -321,7 +321,6 @@ export interface AzionBuild T; memoryFS?: { injectionDirs: string[]; @@ -543,6 +542,7 @@ export interface BundlerSetup { export interface BuildContext { production: boolean; handler: BuildEntryPoint; + skipFrameworkBuild?: boolean; } export type PresetMetadata = { diff --git a/packages/presets/src/index.ts b/packages/presets/src/index.ts index 9debfb3b..186df063 100644 --- a/packages/presets/src/index.ts +++ b/packages/presets/src/index.ts @@ -11,6 +11,7 @@ export * from './presets/javascript'; export * from './presets/jekyll'; export * from './presets/next'; export * from './presets/nuxt'; +export * from './presets/opennextjs'; export * from './presets/preact'; export * from './presets/qwik'; export * from './presets/react'; diff --git a/packages/presets/src/presets/astro/prebuild.ts b/packages/presets/src/presets/astro/prebuild.ts index 17633194..798f11eb 100644 --- a/packages/presets/src/presets/astro/prebuild.ts +++ b/packages/presets/src/presets/astro/prebuild.ts @@ -1,27 +1,46 @@ import { copyDirectory, exec, getPackageManager } from 'azion/utils/node'; -import { readFile } from 'fs/promises'; - -/** - * Runs custom prebuild actions for Astro - */ -async function prebuild() { - const packageManager = await getPackageManager(); - const newOutDir = '.edge/storage'; - let outDir = 'dist'; - - // check if an output path is specified in config file - const configFileContent = await readFile('./astro.config.mjs', 'utf-8'); - const attributeMatch = Array.from(configFileContent.matchAll(/outDir:(.*)\n/g), (match) => match)[0]; - if (attributeMatch) { - outDir = attributeMatch[1].trim(); +import { constants } from 'fs'; +import { access, readFile } from 'fs/promises'; + +const CONFIG_FILES = ['astro.config.ts', 'astro.config.mjs', 'astro.config.js', 'astro.config.cjs'] as const; + +async function getAstroOutDir(): Promise { + for (const configFile of CONFIG_FILES) { + try { + await access(configFile, constants.F_OK); + const configContent = await readFile(configFile, 'utf-8'); + + // Regex supports: outDir: 'path', outDir:"path", outDir: `path` + const outDirMatch = configContent.match(/outDir\s*:\s*['"`]([^'"`]+)['"`]/); + + if (outDirMatch && outDirMatch[1]) { + return outDirMatch[1].trim(); + } + + break; + } catch { + continue; + } } - await exec(`${packageManager} run build`, { - scope: 'Astro', - verbose: true, - }); + return 'dist'; // Default Astro output directory +} + +async function prebuild(): Promise { + try { + const [packageManager, outDir] = await Promise.all([getPackageManager(), getAstroOutDir()]); + + const newOutDir = '.edge/storage'; - copyDirectory(outDir, newOutDir); + await exec(`${packageManager} run build`, { + scope: 'Astro', + verbose: true, + }); + + copyDirectory(outDir, newOutDir); + } catch (error) { + throw new Error(`Error during Astro prebuild: ${error instanceof Error ? error.message : String(error)}`); + } } export default prebuild; diff --git a/packages/presets/src/presets/html/config.ts b/packages/presets/src/presets/html/config.ts index 00f79162..8088c189 100644 --- a/packages/presets/src/presets/html/config.ts +++ b/packages/presets/src/presets/html/config.ts @@ -24,6 +24,31 @@ export default defineConfig({ }, }, }, + { + name: 'Deliver Static Assets', + match: '.(css|js|ttf|woff|woff2|pdf|svg|jpg|jpeg|gif|bmp|png|ico|mp4|json|xml|html)$', + behavior: { + setOrigin: { + name: 'origin-storage-default', + type: 'object_storage', + }, + deliver: true, + }, + }, + { + name: 'Redirect to index.html', + match: '.*/$', + behavior: { + rewrite: '${uri}index.html', + }, + }, + { + name: 'Redirect to index.html for Subpaths', + match: '^(?!.*\\/$)(?![\\s\\S]*\\.[a-zA-Z0-9]+$).*', + behavior: { + rewrite: '${uri}/index.html', + }, + }, ], }, }); diff --git a/packages/presets/src/presets/next/node/custom-server/12.3.x/server/next.js b/packages/presets/src/presets/next/node/custom-server/12.3.x/server/next.js index 1624a85c..dc2b1175 100644 --- a/packages/presets/src/presets/next/node/custom-server/12.3.x/server/next.js +++ b/packages/presets/src/presets/next/node/custom-server/12.3.x/server/next.js @@ -56,6 +56,29 @@ export class NextServer { async handleFetchEvent(event) { const { req, res } = toReqRes(event.request); + // Consume the ReadableStream (req._stream) and populate req.body + if (req._stream) { + // Determine Content-Type + const contentType = req.headers['content-type'] || req.headers['Content-Type']; + + if (contentType === 'application/json') { + try { + req.body = await event.request.json(); // Parse JSON if Content-Type is application/json + } catch (error) { + console.error('Invalid JSON body:', error); + req.body = null; // Handle invalid JSON gracefully + } + } else if (contentType === 'application/x-www-form-urlencoded') { + req.body = new URLSearchParams(await event.request.text()).toString(); // Parse URL-encoded data + } else if (contentType === 'text/plain' || !contentType) { + req.body = await event.request.text(); // Handle plain text or no Content-Type + } else { + console.warn(`Unhandled Content-Type: ${contentType}`); + req.body = event.request.body; // Default fallback: raw string + } + } else { + req.body = JSON.stringify({}); // Handle cases where there is no body + } const nextRequest = new ComputeJsNextRequest(req, event.client); const nextResponse = new ComputeJsNextResponse(res); diff --git a/packages/presets/src/presets/next/node/prebuild/index.js b/packages/presets/src/presets/next/node/prebuild/index.js index e5493417..23b838f7 100644 --- a/packages/presets/src/presets/next/node/prebuild/index.js +++ b/packages/presets/src/presets/next/node/prebuild/index.js @@ -4,21 +4,6 @@ import path, { join } from 'path'; import { copyDirectory, feedback, getAbsoluteDirPath } from 'azion/utils/node'; import BuildStatic from './statics/index.js'; -/** - * If a relative path exists, copy public path to root - * @param {string} pathPrefix - prefix - * @param {string} rootDir - application root dir - */ -function handlePublicDir(pathPrefix, rootDir) { - const validPathPrefix = pathPrefix && typeof pathPrefix === 'string' && pathPrefix !== ''; - - if (validPathPrefix) { - const srcPublicDir = path.resolve(pathPrefix, 'public'); - const destPublicDir = path.resolve(rootDir, 'public'); - copyDirectory(srcPublicDir, destPublicDir); - } -} - /** * Run actions to build next for node runtime. * @param {string} nextVersion - project next version in package.json @@ -47,12 +32,6 @@ async function run(nextVersion, buildContext) { process.exit(1); } - // STATICS - // copy to root public dir if necessary - if (buildContext.memoryFS) { - handlePublicDir(buildContext.memoryFS.removePathPrefix, rootDir); - } - // It is necessary to replace the static directories for the .vercel output, // which has the _next pattern and the public folder does not exist // as the files are in the root (.vercel/output/static). diff --git a/packages/presets/src/presets/opennextjs/config.ts b/packages/presets/src/presets/opennextjs/config.ts new file mode 100644 index 00000000..b6fdccce --- /dev/null +++ b/packages/presets/src/presets/opennextjs/config.ts @@ -0,0 +1,58 @@ +import type { AzionBuild, AzionConfig } from 'azion/config'; + +const config: AzionConfig = { + build: { + entry: '.open-next/worker.js', + polyfills: true, + bundler: 'esbuild', + preset: 'opennextjs', + } as AzionBuild, + origin: [ + { + name: 'origin-storage-default', + type: 'object_storage', + }, + ], + functions: [ + { + name: 'handler', + path: '.edge/functions/handler.js', + }, + ], + rules: { + request: [ + { + name: 'Set storage origin for all requests _next_static', + match: '^\\/_next\\/static\\/', // starts with '/_next/static/' + behavior: { + setOrigin: { + name: 'origin-storage-default', + type: 'object_storage', + }, + deliver: true, + }, + }, + { + name: 'Deliver Static Assets', + match: '.(css|js|ttf|woff|woff2|pdf|svg|jpg|jpeg|gif|bmp|png|ico|mp4|json)$', + behavior: { + setOrigin: { + name: 'origin-storage-default', + type: 'object_storage', + }, + deliver: true, + }, + }, + { + name: 'Execute Edge Function', + match: '^/', + behavior: { + runFunction: 'handler', + forwardCookies: true, + }, + }, + ], + }, +}; + +export default config; diff --git a/packages/presets/src/presets/opennextjs/index.ts b/packages/presets/src/presets/opennextjs/index.ts new file mode 100644 index 00000000..5495a0b8 --- /dev/null +++ b/packages/presets/src/presets/opennextjs/index.ts @@ -0,0 +1,6 @@ +import type { AzionBuildPreset } from 'azion/config'; +import config from './config'; +import metadata from './metadata'; +import prebuild from './prebuild'; + +export const opennextjs: AzionBuildPreset = { config, metadata, prebuild }; diff --git a/packages/presets/src/presets/opennextjs/metadata.ts b/packages/presets/src/presets/opennextjs/metadata.ts new file mode 100644 index 00000000..c75857ae --- /dev/null +++ b/packages/presets/src/presets/opennextjs/metadata.ts @@ -0,0 +1,7 @@ +import type { PresetMetadata } from 'azion/config'; + +const metadata: PresetMetadata = { + name: 'opennextjs', +}; + +export default metadata; diff --git a/packages/presets/src/presets/opennextjs/prebuild.ts b/packages/presets/src/presets/opennextjs/prebuild.ts new file mode 100644 index 00000000..c686e2a9 --- /dev/null +++ b/packages/presets/src/presets/opennextjs/prebuild.ts @@ -0,0 +1,80 @@ +import { BuildConfiguration, BuildContext } from 'azion/config'; +import { exec } from 'azion/utils/node'; +import { readFile } from 'fs/promises'; +import path from 'path'; + +/** + * Runs custom prebuild actions for OpenNextjs + */ +async function prebuild(buildConfig: BuildConfiguration, ctx: BuildContext): Promise { + const pkgOpenNextjsName = '@aziontech/opennextjs-azion'; + const openNextjsCommand = 'npm exec opennextjs-azion'; + + // Check if the OpenNextjs Azion is installed + const isOpenNextjsInstalled = await checkIfOpenNextjsIsInstalled(); + if (!isOpenNextjsInstalled) { + const packageManager = await indentifyPackageManager(); + const execCommand = + packageManager === 'yarn' + ? `yarn add -D ${pkgOpenNextjsName}` + : packageManager === 'pnpm' + ? `pnpm add -D ${pkgOpenNextjsName}` + : `npm i -D ${pkgOpenNextjsName}`; + await exec(execCommand, { + scope: 'OpenNextjs', + verbose: true, + interactive: true, + }); + } + // Run OpenNextjs command build + if (ctx.production || !ctx.skipFrameworkBuild) { + const skipBuild = ctx.skipFrameworkBuild ? '--skipBuild' : ''; + await exec(`${openNextjsCommand} build -- ${skipBuild}`, { + scope: 'OpenNextjs', + verbose: true, + interactive: true, + }); + } + + // Run OpenNextjs commands to populate assets + if (ctx.production) { + await exec(`${openNextjsCommand} populateAssets`, { + scope: 'OpenNextjs', + verbose: true, + }); + } + + // Run OpenNextjs commands to populate cache + if (ctx.production) { + await exec(`${openNextjsCommand} populateCache`, { + scope: 'OpenNextjs', + verbose: true, + }); + } +} + +async function checkIfOpenNextjsIsInstalled(): Promise { + const packageJsonPath = path.resolve(process.cwd(), 'package.json'); + const packageJson = await readFile(packageJsonPath, 'utf-8'); + const packageJsonObj = JSON.parse(packageJson); + if (!packageJsonObj.devDependencies || !packageJsonObj.devDependencies['@aziontech/opennextjs-azion']) { + return false; + } + return true; +} + +async function indentifyPackageManager(): Promise { + const lockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']; + for (const lockFile of lockFiles) { + const filePath = path.resolve(process.cwd(), lockFile); + try { + await readFile(filePath, 'utf-8'); + return lockFile.includes('yarn') ? 'yarn' : lockFile.includes('pnpm') ? 'pnpm' : 'npm'; + } catch (error) { + // File not found, continue to the next one + } + } + return 'npm'; // Default to npm if no lock file is found +} + +export default prebuild; diff --git a/packages/presets/src/presets/preact/index.ts b/packages/presets/src/presets/preact/index.ts index 6766e028..38b0132d 100644 --- a/packages/presets/src/presets/preact/index.ts +++ b/packages/presets/src/presets/preact/index.ts @@ -2,7 +2,6 @@ import type { AzionBuildPreset } from 'azion/config'; import config from './config'; import handler from './handler'; import metadata from './metadata'; -// import prebuild from './prebuild'; -// import postbuild from './postbuild'; +import prebuild from './prebuild'; -export const preact: AzionBuildPreset = { config, metadata, handler }; +export const preact: AzionBuildPreset = { config, metadata, handler, prebuild }; diff --git a/packages/presets/src/presets/preact/prebuild.ts b/packages/presets/src/presets/preact/prebuild.ts new file mode 100644 index 00000000..1426fb16 --- /dev/null +++ b/packages/presets/src/presets/preact/prebuild.ts @@ -0,0 +1,87 @@ +import { copyDirectory, exec, getPackageManager } from 'azion/utils/node'; +import { lstat, readFile, rm } from 'fs/promises'; +import { join } from 'path'; + +const packageManager = await getPackageManager(); +const edgeStorageDir = '.edge/storage'; +const defaultViteOutDir = 'dist'; + +/** + * Check if the vite.config file exists. + * @returns {boolean} True if the file exists, false otherwise. + */ +async function viteConfigExists() { + const files = ['./vite.config.js', './vite.config.ts']; + const checks = files.map(async (file) => { + try { + await lstat(file); + return true; + } catch (err) { + return false; + } + }); + + const results = await Promise.all(checks); + return results.includes(true); +} + +/** + * Read vite.config build output + * @returns {object} The parsed configuration object or null if the file doesn't exist. + */ +async function readViteBuildOutput() { + try { + const isTypescript = await lstat('./vite.config.ts').then( + () => true, + () => false, + ); + const pathConfigFile = join(process.cwd(), isTypescript ? 'vite.config.ts' : 'vite.config.js'); + const configFileContent = await readFile(pathConfigFile, 'utf-8'); + const defineConfig = configFileContent.match(/defineConfig\(([\s\S]*)\)/); + + if (!defineConfig) { + throw new Error('defineConfig not found'); + } + + const buildConfig = defineConfig[1].match(/build: *({[\s\S]*?}),/); + + if (!buildConfig) { + throw new Error('build config not found'); + } + + const buildConfigObject = JSON.parse(buildConfig[1].replace(/(\w+):/g, '"$1":').replace(/'/g, '"')); + + return Promise.resolve({ build: buildConfigObject }); + } catch (err) { + return null; + } +} + +/** + * Runs custom prebuild actions + */ +async function prebuild() { + const npmArgsForward = packageManager === 'npm' ? '--' : ''; + + let outDir = defaultViteOutDir; + const destPath = edgeStorageDir; + + const isViteProject = await viteConfigExists(); + + if (isViteProject) { + await exec(`${packageManager} run build ${npmArgsForward}`, 'Preact', true); + + const config = await readViteBuildOutput(); + + if (config?.build?.outDir) { + outDir = config.build.outDir; + } + + copyDirectory(outDir, destPath); + rm(outDir, { recursive: true, force: true }); + } else { + await exec(`BUILD_PATH="./.edge/storage" ${packageManager} run build`, 'Preact', true); + } +} + +export default prebuild; diff --git a/packages/unenv-preset/src/index.ts b/packages/unenv-preset/src/index.ts index dac95cde..45db6209 100644 --- a/packages/unenv-preset/src/index.ts +++ b/packages/unenv-preset/src/index.ts @@ -5,7 +5,6 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const getAbsolutePath = () => path.resolve(__dirname, '../../', 'unenv-preset', 'src'); -const nextNodePresetPath = `${getAbsolutePath()}/polyfills/node/frameworks/next`; const polyfillsPath = `${getAbsolutePath()}/polyfills`; export default { @@ -13,34 +12,30 @@ export default { __dirname: `${polyfillsPath}/node/globals/path-dirname.js`, __filename: `${polyfillsPath}/node/globals/path-filename.js`, process: `${polyfillsPath}/node/globals/process.cjs`, - performance: `${polyfillsPath}/node/globals/performance.js`, - navigator: `${polyfillsPath}/node/globals/navigator.js`, + performance: `unenv/polyfill/performance`, + setInterval: `${polyfillsPath}/node/globals/set-interval.js`, + clearInterval: `${polyfillsPath}/node/globals/clear-interval.js`, }, alias: { 'azion/utils': 'azion/utils', 'azion/utils/edge': 'azion/utils/edge', 'azion/utils/node': 'azion/utils/node', '@fastly/http-compute-js': '@fastly/http-compute-js', - 'next/dist/compiled/etag': `${nextNodePresetPath}/custom-server/12.3.x/util/etag.js`, accepts: 'accepts', - crypto: `${polyfillsPath}/node/crypto.js`, - events: 'events/events.js', - http: 'stream-http', + assert: 'assert-browserify', + https: `${polyfillsPath}/node/https.js`, module: `${polyfillsPath}/node/module.js`, - stream: 'stream-browserify/', string_decoder: 'string_decoder/lib/string_decoder.js', - url: 'url/url.js', - util: 'util/util.js', timers: 'timers-browserify/', - inherits: 'inherits/inherits_browser.js', - vm: 'vm-browserify/', - zlib: 'browserify-zlib', + util: `${polyfillsPath}/node/util.js`, }, - external: ['node:async_hooks', 'node:fs/promises'], + external: ['node:async_hooks', 'node:fs/promises', 'node:stream', 'node:crypto'], polyfill: [ 'aziondev:async_hooks:/async-hooks/async-hooks.polyfills.js', 'aziondev:fs:/fs/fs.polyfills.js', 'aziondev:fs/promises:/fs/promises/promises.polyfills.js', + 'aziondev:stream:/stream/stream.polyfills.js', + 'aziondev:crypto:/crypto/crypto.polyfills.js', `azionprd:fs:/fs.js`, ], }; diff --git a/packages/unenv-preset/src/polyfills/node/crypto.js b/packages/unenv-preset/src/polyfills/node/crypto.js index ade2fe3e..dfb0d273 100644 --- a/packages/unenv-preset/src/polyfills/node/crypto.js +++ b/packages/unenv-preset/src/polyfills/node/crypto.js @@ -65,3 +65,20 @@ export var randomUUID = function () { return (c ^ (getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16); }); }; + +export var generateKeyPair = function (type, options, callback) { + if (typeof options === 'function') { + callback = options; + options = undefined; + } + if (typeof type === 'function') { + callback = type; + type = undefined; + } + + if (type === 'rsa') { + return crypto.generateKeyPair('rsa', options, callback); + } else { + throw new Error('Unsupported key type'); + } +}; diff --git a/packages/unenv-preset/src/polyfills/node/empty.js b/packages/unenv-preset/src/polyfills/node/empty.js new file mode 100644 index 00000000..89f4afba --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/empty.js @@ -0,0 +1,3 @@ +export function loadEnvConfig() {} + +export default {}; diff --git a/packages/unenv-preset/src/polyfills/node/fs.js b/packages/unenv-preset/src/polyfills/node/fs.js index 6e97dc17..14a70956 100644 --- a/packages/unenv-preset/src/polyfills/node/fs.js +++ b/packages/unenv-preset/src/polyfills/node/fs.js @@ -4,7 +4,7 @@ import bPath from 'path'; /* eslint-disable */ -const MEM_FILES = globalThis.bundler.__FILES__; +var MEM_FILES = globalThis.bundler.__FILES__; globalThis.bundler.FS_PATHS_CHANGED = false; @@ -13,12 +13,13 @@ globalThis.bundler.FS_PATHS_CHANGED = false; */ function fixMappedFilesPaths() { const prefix = globalThis.bundler.FS_PATH_PREFIX_TO_REMOVE; - if (!globalThis.bundler.FS_PATHS_CHANGED && prefix !== '') { + if (!globalThis.bundler.FS_PATHS_CHANGED && (prefix !== undefined || prefix !== '""')) { + let CHANGED_PATHS = {}; Object.keys(MEM_FILES).forEach((e) => { const newKey = e.replace(prefix, ''); - MEM_FILES[newKey] = MEM_FILES[e]; - delete MEM_FILES[e]; + CHANGED_PATHS[newKey] = MEM_FILES[e]; }); + MEM_FILES = CHANGED_PATHS; } globalThis.bundler.FS_PATHS_CHANGED = true; @@ -381,6 +382,17 @@ function readdirSync(path, options = {}) { return result; } +function existsSync(path) { + path = getValidatedPath(path); + const filesInfos = getFilesInfos(); + + if (filesInfos.paths.includes(path)) { + return true; + } + + return false; +} + // Use Cells node:fs API const fsPolyfill = Object.create(SRC_NODE_FS); fsPolyfill.close = close; @@ -390,10 +402,11 @@ fsPolyfill.statSync = statSync; fsPolyfill.lstatSync = statSync; fsPolyfill.readFileSync = readFileSync; fsPolyfill.readdirSync = readdirSync; +fsPolyfill.existsSync = existsSync; export default fsPolyfill; -export { close, closeSync, statSync as lstatSync, openSync, readdirSync, readFileSync, statSync }; +export { close, closeSync, existsSync, statSync as lstatSync, openSync, readdirSync, readFileSync, statSync }; export const { access, @@ -414,7 +427,6 @@ export const { Dir, Dirent, exists, - existsSync, F_OK, fdatasync, fdatasyncSync, diff --git a/packages/unenv-preset/src/polyfills/node/globals/clear-interval.js b/packages/unenv-preset/src/polyfills/node/globals/clear-interval.js new file mode 100644 index 00000000..43f91f61 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/globals/clear-interval.js @@ -0,0 +1,19 @@ +const _clearInterval = globalThis.clearInterval; + +globalThis.clearInterval = (interval) => { + let idToClear = interval; + if (interval && typeof interval === 'object') { + if ('id' in interval) { + idToClear = interval.id; + } else if ('_id' in interval) { + idToClear = interval._id; + } + } + if (typeof idToClear === 'number' && Number.isFinite(idToClear)) { + _clearInterval(idToClear); + } else if (interval && typeof interval.close === 'function') { + interval.close(); + } +}; + +export default globalThis.clearInterval; diff --git a/packages/unenv-preset/src/polyfills/node/globals/process.cjs b/packages/unenv-preset/src/polyfills/node/globals/process.cjs index 5a691ee3..7be5f3ed 100644 --- a/packages/unenv-preset/src/polyfills/node/globals/process.cjs +++ b/packages/unenv-preset/src/polyfills/node/globals/process.cjs @@ -1,5 +1,7 @@ /* eslint-disable */ // shim for using process in browser +globalThis.startTime = globalThis.startTime || Date.now(); + var processShim = (module.exports = {}); /* @@ -154,8 +156,25 @@ Item.prototype.run = function () { }; processShim.title = 'browser'; processShim.browser = true; -processShim.env = processShim.env = - typeof globalThis.process !== 'undefined' && globalThis.process.env ? globalThis.process.env : {}; +const initialValues = globalThis.process !== 'undefined' && globalThis.process?.env ? globalThis.process.env : {}; +Object.defineProperty(processShim, 'env', { + value: new Proxy( + { ...initialValues }, + { + get(target, prop) { + return target[prop] || undefined; + }, + set(target, prop, value) { + target[prop] = value; + return true; + }, + }, + ), + writable: true, + enumerable: true, + configurable: true, +}); + processShim.argv = []; processShim.version = ''; // empty string to avoid regexp issues processShim.versions = { node: '18.3.1' }; @@ -172,6 +191,10 @@ processShim.emit = noop; processShim.prependListener = noop; processShim.prependOnceListener = noop; +processShim.uptime = function () { + return (Date.now() - globalThis.startTime) / 1000; +}; + processShim.listeners = function (name) { return []; }; @@ -185,11 +208,12 @@ processShim.cwd = function () { }; processShim.chdir = function (dir) { - throw new Error('process.chdir is not supported'); + return dir ?? '/'; }; processShim.umask = function () { return 0; }; globalThis.process = processShim; -globalThis.process.env = processShim.env; + +module.exports = processShim; diff --git a/packages/unenv-preset/src/polyfills/node/globals/set-interval.js b/packages/unenv-preset/src/polyfills/node/globals/set-interval.js new file mode 100644 index 00000000..ac4a6aca --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/globals/set-interval.js @@ -0,0 +1,21 @@ +const _setInterval = globalThis.setInterval; +const _clearInterval = globalThis.clearInterval; + +globalThis.setInterval = (...args) => { + const id = _setInterval(...args); + if (typeof id === 'object' && id !== null) { + // this is necessary for compatibility with the Sentry library and node's timers + if (typeof id.unref !== 'function') { + id.unref = () => {}; + } + return id; + } + return { + id, + unref: () => {}, + ref: () => {}, + clear: () => _clearInterval(id), + }; +}; + +export default globalThis.setInterval; diff --git a/packages/unenv-preset/src/polyfills/node/https.js b/packages/unenv-preset/src/polyfills/node/https.js new file mode 100644 index 00000000..20ff93fd --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/https.js @@ -0,0 +1,248 @@ +/* eslint-disable */ +// https://nodejs.org/api/https.html +import { EventEmitter } from 'node:events'; + +function notImplementedClass(name) { + return class { + __unenv__ = true; + constructor() { + throw new Error(`[unenv] ${name} is not implemented yet!`); + } + }; +} +function createNotImplementedError(name) { + return new Error(`[unenv] ${name} is not implemented yet!`); +} + +function notImplemented(name) { + const fn = () => { + throw createNotImplementedError(name); + }; + return Object.assign(fn, { __unenv__: true }); +} + +class HttpAgent extends EventEmitter { + __unenv__ = {}; + maxFreeSockets = 256; + maxSockets = Infinity; + maxTotalSockets = Infinity; + freeSockets = {}; + sockets = {}; + requests = {}; + destroy() {} +} + +export const Server = notImplementedClass('https.Server'); + +export const Agent = HttpAgent; + +export const globalAgent = new Agent(); + +export const get = notImplemented('https.get'); + +export const createServer = notImplemented('https.createServer'); + +export const request = (urlOrOptions, optionsOrCallback, maybeCallback) => { + let url, options, callback; + if (typeof urlOrOptions === 'string' || urlOrOptions instanceof URL) { + url = urlOrOptions; + if (typeof optionsOrCallback === 'object' && optionsOrCallback !== null) { + options = optionsOrCallback; + callback = maybeCallback; + } else { + options = {}; + callback = optionsOrCallback; + } + } else { + url = undefined; + options = urlOrOptions || {}; + callback = optionsOrCallback; + } + + let fullUrl, headers, method, body; + if (url) { + fullUrl = url.toString(); + headers = { ...(options.headers || {}) }; + method = (options.method || 'GET').toUpperCase(); + body = options.body; + } else { + const protocol = options.protocol || 'https:'; + const hostname = options.hostname || 'localhost'; + const port = options.port ? `:${options.port}` : ''; + const path = options.path || '/'; + body = options.body; + const queryParams = options.query ? new URLSearchParams(options.query).toString() : ''; + const queryString = queryParams ? `?${queryParams}` : ''; + fullUrl = `${protocol}//${hostname}${port}${path}${queryString}`; + headers = { ...(options.headers || {}) }; + method = (options.method || 'GET').toUpperCase(); + } + + let formattedBody; + if (headers['Content-Type'] === 'application/json') { + formattedBody = body ? JSON.stringify(body) : undefined; + if (!options.method && body) method = 'POST'; + } else if (headers['Content-Type'] === 'application/x-www-form-urlencoded') { + formattedBody = body ? new URLSearchParams(body).toString() : undefined; + if (!options.method && body) method = 'POST'; + } else { + formattedBody = body; + if (!options.method && body) method = 'POST'; + } + + const controller = new AbortController(); + const signal = controller.signal; + + let timeoutId; + if (options.timeout) { + timeoutId = setTimeout(() => { + controller.abort(); + reqEvents.emit('error', new Error('Request timed out')); + }, options.timeout); + } + + const reqEvents = new EventEmitter(); + + let endCalled = false; + + const req = { + _bodyBuffer: [], + removeHeader: (name) => { + if (headers && typeof name === 'string') { + delete headers[name]; + delete headers[name.toLowerCase()]; + } + }, + setHeader: (name, value) => { + if (headers && typeof name === 'string') { + headers[name] = value; + headers[name.toLowerCase()] = value; + } + }, + write: (chunk) => { + if (typeof chunk === 'string' || chunk instanceof Buffer) { + req._bodyBuffer.push(chunk); + } else { + throw new Error('Invalid chunk type. Expected string or Buffer.'); + } + }, + on: (event, listener) => { + reqEvents.on(event, listener); + return req; + }, + once: (event, listener) => { + reqEvents.once(event, listener); + return req; + }, + abort: () => { + clearTimeout(timeoutId); + controller.abort(); + }, + end: () => { + if (endCalled) { + console.error('end() called multiple times'); + return; + } + endCalled = true; + + let bodyFinal; + if (req._bodyBuffer.length > 0) { + if (Buffer.isBuffer(req._bodyBuffer[0])) { + bodyFinal = Buffer.concat(req._bodyBuffer).toString(); + } else { + bodyFinal = req._bodyBuffer.join(''); + } + } else { + bodyFinal = formattedBody; + } + + const fetchOptions = { + method, + headers, + signal, + }; + + if (method !== 'GET' && method !== 'HEAD' && bodyFinal !== undefined) { + fetchOptions.body = bodyFinal; + } + + fetch(fullUrl, fetchOptions) + .then(async (response) => { + clearTimeout(timeoutId); + const res = new EventEmitter(); + res.statusCode = response.status; + res.headers = Object.fromEntries(response.headers.entries()); + + const chunks = []; + res[Symbol.asyncIterator] = async function* () { + let ended = false; + this.on('end', () => { + ended = true; + }); + let idx = 0; + while (!ended || idx < chunks.length) { + if (idx < chunks.length) { + yield chunks[idx++]; + } else { + await new Promise((resolve) => this.once('data', resolve)); + } + } + }; + + const reader = response.body?.getReader(); + + const processStream = async () => { + try { + if (!reader) { + res.emit('end'); + return; + } + while (true) { + const { done, value } = await reader.read(); + if (done) { + res.emit('end'); + break; + } + const buf = Buffer.from(value); + chunks.push(buf); + res.emit('data', buf); + } + } catch (err) { + res.emit('error', err); + } + }; + + if (reader) { + if (!reader.locked) { + processStream(); + } else { + res.emit('error', new Error('Stream is already locked')); + } + } else { + res.emit('end'); + } + + reqEvents.emit('response', res); + + if (typeof callback === 'function') { + callback(res); + } + }) + .catch((err) => { + clearTimeout(timeoutId); + reqEvents.emit('error', err); + }); + }, + }; + + return req; +}; + +export default { + Server, + Agent, + globalAgent, + get, + createServer, + request, +}; diff --git a/packages/unenv-preset/src/polyfills/node/internal/_internal.js b/packages/unenv-preset/src/polyfills/node/internal/_internal.js new file mode 100644 index 00000000..81023975 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/_internal.js @@ -0,0 +1,11 @@ +/* eslint-disable */ +export function notImplemented(name) { + const fn = () => { + throw createNotImplementedError(name); + }; + return Object.assign(fn, { __unenv__: true }); +} + +export function createNotImplementedError(name) { + return new Error(`[unenv] ${name} is not implemented yet!`); +} diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/inherits.js b/packages/unenv-preset/src/polyfills/node/internal/util/inherits.js new file mode 100644 index 00000000..a8897e7d --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/inherits.js @@ -0,0 +1,15 @@ +/* eslint-disable */ +export function inherits(ctor, superCtor) { + if (!superCtor) { + return; + } + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true, + }, + }); +} diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/legacy-types.js b/packages/unenv-preset/src/polyfills/node/internal/util/legacy-types.js new file mode 100644 index 00000000..6e1a87c8 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/legacy-types.js @@ -0,0 +1,51 @@ +/* eslint-disable */ +export const isRegExp = (val) => val instanceof RegExp; + +export const isDate = (val) => val instanceof Date; + +export const isArray = (val) => Array.isArray(val); + +export const isBoolean = (val) => typeof val === 'boolean'; + +export const isNull = (val) => val === null; + +export const isNullOrUndefined = (val) => val === null || val === undefined; + +export const isNumber = (val) => typeof val === 'number'; + +export const isString = (val) => typeof val === 'string'; + +export const isSymbol = (val) => typeof val === 'symbol'; + +export const isUndefined = (val) => val === undefined; + +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +export const isFunction = (val) => typeof val === 'function'; + +export const isBuffer = (val) => { + return ( + val && + typeof val === 'object' && + typeof val.copy === 'function' && + typeof val.fill === 'function' && + typeof val.readUInt8 === 'function' + ); +}; + +export const isDeepStrictEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b); + +export const isObject = (val) => + val !== null && + typeof val === 'object' && + // eslint-disable-next-line no-prototype-builtins + Object.getPrototypeOf(val).isPrototypeOf(Object); + +export const isError = (val) => val instanceof Error; + +// Source https://github.com/jonschlinkert/is-primitive/blob/b22c524da5cbac075f14145780ec4b3637afd7dc/index.js +export const isPrimitive = (val) => { + if (typeof val === 'object') { + return val === null; + } + return typeof val !== 'function'; +}; diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/log.js b/packages/unenv-preset/src/polyfills/node/internal/util/log.js new file mode 100644 index 00000000..926cc546 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/log.js @@ -0,0 +1,64 @@ +/* eslint-disable */ +export const log = (...args) => { + console.log(...args); +}; + +export const debuglog = (section, _cb) => { + const fn = (msg, ...params) => { + if (fn.enabled) { + console.debug(`[${section}] ${msg}`, ...params); + } + }; + fn.enabled = true; + return fn; +}; + +export const debug = debuglog; + +export const inspect = (object) => JSON.stringify(object, null, 2); + +export const format = (...args) => _format(...args); + +export const formatWithOptions = (_options, ...args) => _format(...args); + +// Source: https://github.com/tmpfs/format-util/blob/0c989942c959b179eec294a4e725afd63e743f18/format.js +function _format(fmt, ...args) { + const re = /(%?)(%([djos]))/g; + if (args.length > 0) { + fmt = fmt.replace(re, (match, escaped, ptn, flag) => { + let arg = args.shift(); + switch (flag) { + case 'o': + if (Array.isArray(arg)) { + arg = JSON.stringify(arg); + break; + } + break; + case 's': + arg = '' + arg; + break; + case 'd': + arg = Number(arg); + break; + case 'j': + arg = JSON.stringify(arg); + break; + } + if (!escaped) { + return arg; + } + args.unshift(arg); + return match; + }); + } + + // arguments remain after formatting + if (args.length > 0) { + fmt += ' ' + args.join(' '); + } + + // update escaped %% values + fmt = fmt.replace(/%{2}/g, '%'); + + return '' + fmt; +} diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/mime.js b/packages/unenv-preset/src/polyfills/node/internal/util/mime.js new file mode 100644 index 00000000..9a7097d3 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/mime.js @@ -0,0 +1,45 @@ +/* eslint-disable */ +// https://nodejs.org/api/util.html#class-utilmimetype + +export class MIMEType { + __unenv__ = true; + + params = new MIMEParams(); + type; + subtype; + + constructor(input) { + const [essence = '', ...params] = String(input).split(';'); + const [type = '', subtype = ''] = essence.split('/'); + this.type = type; + this.subtype = subtype; + this.params = new MIMEParams(); + for (const param of params) { + const [name, value] = param.split('='); + this.params.set(name, value); + } + } + + get essence() { + return this.type + '/' + this.subtype; + } + + toString() { + const paramsStr = this.params.toString(); + return this.essence + (paramsStr ? `;${paramsStr}` : ''); + } +} + +// https://nodejs.org/api/util.html#util_class_util_mimeparams + +export class MIMEParams extends Map { + __unenv__ = true; + + get(name) { + return super.get(name) || null; + } + + toString() { + return [...this.entries()].map(([name, value]) => `${name}=${value}`).join('&'); + } +} diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/promisify.js b/packages/unenv-preset/src/polyfills/node/internal/util/promisify.js new file mode 100644 index 00000000..e5091ed2 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/promisify.js @@ -0,0 +1,25 @@ +/* eslint-disable */ +const customSymbol = Symbol.for('nodejs.util.promisify.custom'); + +function _promisify(fn) { + if (fn[customSymbol]) { + return fn[customSymbol]; + } + return function (...args) { + return new Promise((resolve, reject) => { + try { + fn.call(this, ...args, (err, val) => { + if (err) { + return reject(err); + } + resolve(val); + }); + } catch (error) { + console.error('Error in promisified function:', error.stack); + reject(error); + } + }); + }; +} + +export const promisify = Object.assign(_promisify, { custom: customSymbol }); diff --git a/packages/unenv-preset/src/polyfills/node/internal/util/types.js b/packages/unenv-preset/src/polyfills/node/internal/util/types.js new file mode 100644 index 00000000..09090c11 --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/internal/util/types.js @@ -0,0 +1,131 @@ +/* eslint-disable */ +import { notImplemented } from '../_internal.js'; + +export const isExternal = (_obj) => false; + +export const isDate = (val) => val instanceof Date; + +export const isArgumentsObject = /*@__PURE__*/ notImplemented('util.types.isArgumentsObject'); + +export const isBigIntObject = (val) => val instanceof BigInt; + +export const isBooleanObject = (val) => val instanceof Boolean; + +export const isNumberObject = (val) => val instanceof Number; + +export const isStringObject = (val) => val instanceof String; + +export const isSymbolObject = (val) => val instanceof Symbol; + +export const isNativeError = /*@__PURE__*/ notImplemented('util.types.isNativeError'); + +export const isRegExp = (val) => val instanceof RegExp; + +export const isAsyncFunction = /*@__PURE__*/ notImplemented('util.types.isAsyncFunction'); + +export const isGeneratorFunction = /*@__PURE__*/ notImplemented('util.types.isGeneratorFunction'); + +export const isGeneratorObject = /*@__PURE__*/ notImplemented('util.types.isGeneratorObject'); + +export const isPromise = (val) => val instanceof Promise; + +export const isMap = (val) => val instanceof Map; + +export const isSet = (val) => val instanceof Set; + +export const isMapIterator = /*@__PURE__*/ notImplemented('util.types.isMapIterator'); + +export const isSetIterator = /*@__PURE__*/ notImplemented('util.types.isSetIterator'); + +export const isWeakMap = (val) => val instanceof WeakMap; + +export const isWeakSet = (val) => val instanceof WeakSet; + +export const isArrayBuffer = (val) => val instanceof ArrayBuffer; + +export const isDataView = (val) => val instanceof DataView; + +export const isSharedArrayBuffer = (val) => val instanceof SharedArrayBuffer; + +export const isProxy = /*@__PURE__*/ notImplemented('util.types.isProxy'); + +export const isModuleNamespaceObject = /*@__PURE__*/ notImplemented('util.types.isModuleNamespaceObject'); + +export const isAnyArrayBuffer = /*@__PURE__*/ notImplemented('util.types.isAnyArrayBuffer'); + +export const isBoxedPrimitive = /*@__PURE__*/ notImplemented('util.types.isBoxedPrimitive'); + +export const isArrayBufferView = /*@__PURE__*/ notImplemented('util.types.isArrayBufferView'); + +export const isTypedArray = /*@__PURE__*/ notImplemented('util.types.isTypedArray'); + +export const isUint8Array = /*@__PURE__*/ notImplemented('util.types.isUint8Array'); + +export const isUint8ClampedArray = /*@__PURE__*/ notImplemented('util.types.isUint8ClampedArray'); + +export const isUint16Array = /*@__PURE__*/ notImplemented('util.types.isUint16Array'); + +export const isUint32Array = /*@__PURE__*/ notImplemented('util.types.isUint32Array'); + +export const isInt8Array = /*@__PURE__*/ notImplemented('util.types.isInt8Array'); + +export const isInt16Array = /*@__PURE__*/ notImplemented('util.types.isInt16Array'); + +export const isInt32Array = /*@__PURE__*/ notImplemented('util.types.isInt32Array'); + +export const isFloat32Array = /*@__PURE__*/ notImplemented('util.types.isFloat32Array'); + +export const isFloat64Array = /*@__PURE__*/ notImplemented('util.types.isFloat64Array'); + +export const isBigInt64Array = /*@__PURE__*/ notImplemented('util.types.isBigInt64Array'); + +export const isBigUint64Array = /*@__PURE__*/ notImplemented('util.types.isBigUint64Array'); + +export const isKeyObject = /*@__PURE__*/ notImplemented('util.types.isKeyObject'); + +// export const isCryptoKey = /*@__PURE__*/ notImplemented('util.types.isCryptoKey'); +export const isCryptoKey = (val) => typeof CryptoKey !== 'undefined' && val instanceof CryptoKey; + +export default { + isExternal, + isDate, + isArgumentsObject, + isBigIntObject, + isBooleanObject, + isNumberObject, + isStringObject, + isSymbolObject, + isNativeError, + isRegExp, + isAsyncFunction, + isGeneratorFunction, + isGeneratorObject, + isPromise, + isMap, + isSet, + isMapIterator, + isSetIterator, + isWeakMap, + isWeakSet, + isArrayBuffer, + isDataView, + isSharedArrayBuffer, + isProxy, + isModuleNamespaceObject, + isAnyArrayBuffer, + isBoxedPrimitive, + isArrayBufferView, + isTypedArray, + isUint8Array, + isUint8ClampedArray, + isUint16Array, + isUint32Array, + isInt8Array, + isInt16Array, + isInt32Array, + isFloat32Array, + isFloat64Array, + isBigInt64Array, + isBigUint64Array, + isKeyObject, // CryptoKey +}; diff --git a/packages/unenv-preset/src/polyfills/node/module.js b/packages/unenv-preset/src/polyfills/node/module.js index 31569dce..35c2b9ea 100644 --- a/packages/unenv-preset/src/polyfills/node/module.js +++ b/packages/unenv-preset/src/polyfills/node/module.js @@ -88,51 +88,68 @@ function _resolveFilename(...args) { /* EMPTY */ } -export default { - builtinModules: builtinModules, - _cache: null, - _pathCache: null, - _extensions: null, - globalPaths: null, - _debug: unimplemented, - _findPath: unimplemented, - _nodeModulePaths: _nodeModulePaths, - _resolveLookupPaths: unimplemented, - _load: _load, - _resolveFilename: _resolveFilename, - createRequireFromPath: unimplemented, - createRequire: createRequire, - _initPaths: unimplemented, - _preloadModules: unimplemented, - syncBuiltinESMExports: unimplemented, - Module: unimplemented, - runMain: unimplemented, - findSourceMap: unimplemented, - SourceMap: unimplemented, +const Module = {}; + +// Adicione as propriedades estáticas esperadas +Module.builtinModules = builtinModules; +Module._cache = null; +Module._pathCache = null; +Module._extensions = null; +Module.globalPaths = null; +Module._debug = unimplemented; +Module._findPath = unimplemented; +Module._nodeModulePaths = _nodeModulePaths; +Module._resolveLookupPaths = unimplemented; +Module._load = _load; +Module._resolveFilename = _resolveFilename; +Module.createRequireFromPath = unimplemented; +Module.createRequire = createRequire; +Module._initPaths = unimplemented; +Module._preloadModules = unimplemented; +Module.syncBuiltinESMExports = unimplemented; +Module.runMain = unimplemented; +Module.findSourceMap = unimplemented; +Module.SourceMap = unimplemented; +Module.require = unimplemented; +const _prototype = { + require: unimplemented, + resolve: unimplemented, + paths: [], + id: '', + filename: '', + loaded: false, + children: [], + exports: {}, + _compile: unimplemented, + _resolveFilename: unimplemented, }; +export default Module; + export var _cache = null, _pathCache = null, _extensions = null, globalPaths = null; export { - builtinModules, unimplemented as _debug, unimplemented as _findPath, - unimplemented as _nodeModulePaths, - unimplemented as _resolveLookupPaths, + unimplemented as _initPaths, unimplemented as _load, + unimplemented as _nodeModulePaths, + unimplemented as _preloadModules, unimplemented as _resolveFilename, - createRequire as createRequireFromPath, + unimplemented as _resolveLookupPaths, + builtinModules, createRequire as createRequire, - unimplemented as _initPaths, - unimplemented as _preloadModules, - unimplemented as syncBuiltinESMExports, - unimplemented as Module, - unimplemented as runMain, + createRequire as createRequireFromPath, unimplemented as findSourceMap, + Module, + _prototype as prototype, + unimplemented as require, + unimplemented as runMain, unimplemented as SourceMap, + unimplemented as syncBuiltinESMExports, }; /* eslint-enable */ diff --git a/packages/unenv-preset/src/polyfills/node/util.js b/packages/unenv-preset/src/polyfills/node/util.js new file mode 100644 index 00000000..00df1acb --- /dev/null +++ b/packages/unenv-preset/src/polyfills/node/util.js @@ -0,0 +1,130 @@ +/* eslint-disable */ +// https://nodejs.org/api/util.html +import types from 'node:util/types'; +import { notImplemented } from './internal/_internal.js'; +import { inherits } from './internal/util/inherits.js'; +import { + isArray, + isBoolean, + isBuffer, + isDate, + isDeepStrictEqual, + isError, + isFunction, + isNull, + isNullOrUndefined, + isNumber, + isObject, + isPrimitive, + isRegExp, + isString, + isSymbol, + isUndefined, +} from './internal/util/legacy-types.js'; +import { debug, debuglog, format, formatWithOptions, inspect, log } from './internal/util/log.js'; +import { MIMEParams, MIMEType } from './internal/util/mime.js'; +import { promisify } from './internal/util/promisify.js'; + +export { MIMEParams, MIMEType } from './internal/util/mime.js'; + +export * from './internal/util/legacy-types.js'; + +export * from './internal/util/log.js'; + +export { inherits } from './internal/util/inherits.js'; + +export { promisify }; + +export { default as types } from './internal/util/types.js'; + +export const TextDecoder = globalThis.TextDecoder; + +export const TextEncoder = globalThis.TextEncoder; + +export const deprecate = (fn) => fn; + +export const _errnoException = notImplemented('util._errnoException'); + +export const _exceptionWithHostPort = notImplemented('util._exceptionWithHostPort'); + +export const _extend = notImplemented('util._extend'); + +export const aborted = notImplemented('util.aborted'); + +export const callbackify = notImplemented('util.callbackify'); + +export const getSystemErrorMap = notImplemented('util.getSystemErrorMap'); + +export const getSystemErrorName = notImplemented('util.getSystemErrorName'); + +export const toUSVString = notImplemented('util.toUSVString'); + +export const stripVTControlCharacters = notImplemented('util.stripVTControlCharacters'); + +export const transferableAbortController = notImplemented('util.transferableAbortController'); + +export const transferableAbortSignal = notImplemented('util.transferableAbortSignal'); + +export const parseArgs = notImplemented('util.parseArgs'); + +export const parseEnv = notImplemented('util.parseEnv'); + +export const styleText = notImplemented('util.styleText'); + +/** @deprecated */ +export const getCallSite = notImplemented('util.getCallSite'); + +export const getCallSites = notImplemented('util.getCallSites'); + +export const getSystemErrorMessage = notImplemented('util.getSystemErrorMessage'); + +export default { + // @ts-expect-error + _errnoException, + _exceptionWithHostPort, + _extend, + aborted, + callbackify, + deprecate, + getCallSite, + getCallSites, + getSystemErrorMessage, + getSystemErrorMap, + getSystemErrorName, + inherits, + promisify, + stripVTControlCharacters, + toUSVString, + TextDecoder, + TextEncoder, + types, + transferableAbortController, + transferableAbortSignal, + parseArgs, + parseEnv, + styleText, + MIMEParams, + MIMEType, + isArray, + isBoolean, + isBuffer, + isDate, + isDeepStrictEqual, + isError, + isFunction, + isNull, + isNullOrUndefined, + isNumber, + isObject, + isPrimitive, + isRegExp, + isString, + isSymbol, + isUndefined, + debug, + debuglog, + format, + formatWithOptions, + inspect, + log, +}; diff --git a/packages/wasm-image-processor/src/index.ts b/packages/wasm-image-processor/src/index.ts index 54c170d5..8b71d9fa 100644 --- a/packages/wasm-image-processor/src/index.ts +++ b/packages/wasm-image-processor/src/index.ts @@ -13,7 +13,10 @@ function resize(image: photon.PhotonImage, width: number, height: number, usePer const widthPercent = usePercent ? width : (width * 100.0) / imageWidth; const heightPercent = usePercent ? height : (height * 100.0) / imageHeight; - return photon.resize(image, (imageWidth * widthPercent) / 100, (imageHeight * heightPercent) / 100, 1); + const newWidth = (imageWidth * widthPercent) / 100; + const newHeight = (imageHeight * heightPercent) / 100; + + return photon.resize(image, newWidth, newHeight, 1); } /** @@ -105,7 +108,9 @@ async function loadImage(pathOrURL: string): Promise { * Get the width of the image. * @returns {number} The width of the image in pixels. */ - width: (): number => image.get_width(), + width: (): number => { + return image.get_width(); + }, /** * Get the height of the image. * @returns {number} The height of the image in pixels. @@ -120,9 +125,26 @@ async function loadImage(pathOrURL: string): Promise { */ resize: (width: number, height: number, usePercent = true): WasmImage => { const resizedImage = resize(image, width, height, usePercent); + return { - ...wrapper, image: resizedImage, + width: (): number => resizedImage.get_width(), + height: (): number => resizedImage.get_height(), + resize: (w: number, h: number, up = true): WasmImage => { + const newResizedImage = resize(resizedImage, w, h, up); + return { + image: newResizedImage, + width: (): number => newResizedImage.get_width(), + height: (): number => newResizedImage.get_height(), + resize: wrapper.resize, + getImageResponse: (format: SupportedImageFormat, quality = 100.0): Response => + getImageResponse(newResizedImage, format, quality), + clean: () => clean(newResizedImage), + }; + }, + getImageResponse: (format: SupportedImageFormat, quality = 100.0): Response => + getImageResponse(resizedImage, format, quality), + clean: () => clean(resizedImage), }; }, /**