diff --git a/package.json b/package.json index 85f2df6..9adf7fa 100644 --- a/package.json +++ b/package.json @@ -68,19 +68,27 @@ "directories": { "lib": "dist" }, + "peerDependencies": { + "esbuild": "^0.28.0" + }, + "peerDependenciesMeta": { + "esbuild": { + "optional": true + } + }, "dependencies": { "@fluent/syntax": "^0.19.0", "@octokit/rest": "^22.0.1", - "@swc/core": "^1.15.24", - "adm-zip": "^0.5.17", - "bumpp": "^11.0.1", - "c12": "4.0.0-beta.4", + "adm-zip": "^0.5.16", + "bumpp": "^10.4.1", + "c12": "4.0.0-beta.3", "chokidar": "^5.0.0", "commander": "^14.0.3", "es-toolkit": "^1.45.1", - "esbuild": "^0.28.0", + "esrap": "^2.2.3", "fs-extra": "^11.3.4", "hookable": "^6.1.0", + "rolldown": "1.0.0-rc.3", "std-env": "^4.0.0", "tiny-update-notifier": "^2.0.2", "tinyglobby": "^0.2.16", @@ -89,6 +97,7 @@ "devDependencies": { "@antfu/eslint-config": "^7.7.3", "@commander-js/extra-typings": "^14.0.0", + "@oxc-project/types": "^0.112.0", "@types/adm-zip": "^0.5.8", "@types/fs-extra": "^11.0.4", "@types/node": "^25.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ccd22e8..2fca49a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,18 +17,15 @@ importers: '@octokit/rest': specifier: ^22.0.1 version: 22.0.1 - '@swc/core': - specifier: ^1.15.24 - version: 1.15.24 adm-zip: - specifier: ^0.5.17 + specifier: ^0.5.16 version: 0.5.17 bumpp: - specifier: ^11.0.1 - version: 11.0.1 + specifier: ^10.4.1 + version: 10.4.1 c12: - specifier: 4.0.0-beta.4 - version: 4.0.0-beta.4(chokidar@5.0.0)(dotenv@17.4.1)(giget@3.2.0)(jiti@2.6.1) + specifier: 4.0.0-beta.3 + version: 4.0.0-beta.3(chokidar@5.0.0)(dotenv@17.4.1)(giget@3.2.0)(jiti@2.6.1) chokidar: specifier: ^5.0.0 version: 5.0.0 @@ -41,12 +38,18 @@ importers: esbuild: specifier: ^0.28.0 version: 0.28.0 + esrap: + specifier: ^2.2.3 + version: 2.2.3 fs-extra: specifier: ^11.3.4 version: 11.3.4 hookable: specifier: ^6.1.0 version: 6.1.0 + rolldown: + specifier: 1.0.0-rc.3 + version: 1.0.0-rc.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) std-env: specifier: ^4.0.0 version: 4.0.0 @@ -66,6 +69,9 @@ importers: '@commander-js/extra-typings': specifier: ^14.0.0 version: 14.0.0(commander@14.0.3) + '@oxc-project/types': + specifier: ^0.112.0 + version: 0.112.0 '@types/adm-zip': specifier: ^0.5.8 version: 0.5.8 @@ -912,6 +918,9 @@ packages: cpu: [x64] os: [win32] + '@oxc-project/types@0.112.0': + resolution: {integrity: sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==} + '@oxc-project/types@0.122.0': resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} @@ -1059,6 +1068,12 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1071,6 +1086,12 @@ packages: cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.12': resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1083,6 +1104,12 @@ packages: cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.3': + resolution: {integrity: sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1095,6 +1122,12 @@ packages: cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.0-rc.3': + resolution: {integrity: sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1107,6 +1140,12 @@ packages: cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': + resolution: {integrity: sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1121,6 +1160,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': + resolution: {integrity: sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1135,6 +1181,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': + resolution: {integrity: sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1177,6 +1230,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': + resolution: {integrity: sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1191,6 +1251,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': + resolution: {integrity: sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1203,6 +1270,12 @@ packages: cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==} engines: {node: '>=14.0.0'} @@ -1213,6 +1286,11 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': + resolution: {integrity: sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1225,6 +1303,12 @@ packages: cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': + resolution: {integrity: sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1237,6 +1321,12 @@ packages: cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': + resolution: {integrity: sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0-rc.12': resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==} @@ -1246,6 +1336,9 @@ packages: '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + '@shikijs/core@3.23.0': resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} @@ -1321,99 +1414,6 @@ packages: peerDependencies: eslint: ^9.0.0 || ^10.0.0 - '@swc/core-darwin-arm64@1.15.24': - resolution: {integrity: sha512-uM5ZGfFXjtvtJ+fe448PVBEbn/CSxS3UAyLj3O9xOqKIWy3S6hPTXSPbszxkSsGDYKi+YFhzAsR4r/eXLxEQ0g==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - - '@swc/core-darwin-x64@1.15.24': - resolution: {integrity: sha512-fMIb/Zfn929pw25VMBhV7Ji2Dl+lCWtUPNdYJQYOke+00E5fcQ9ynxtP8+qhUo/HZc+mYQb1gJxwHM9vty+lXg==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - - '@swc/core-linux-arm-gnueabihf@1.15.24': - resolution: {integrity: sha512-vOkjsyjjxnoYx3hMEWcGxQrMgnNrRm6WAegBXrN8foHtDAR+zpdhpGF5a4lj1bNPgXAvmysjui8cM1ov/Clkaw==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.15.24': - resolution: {integrity: sha512-h/oNu+upkXJ6Cicnq7YGVj9PkdfarLCdQa8l/FlHYvfv8CEiMaeeTnpLU7gSBH/rGxosM6Qkfa/J9mThGF9CLA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@swc/core-linux-arm64-musl@1.15.24': - resolution: {integrity: sha512-ZpF/pRe1guk6sKzQI9D1jAORtjTdNlyeXn9GDz8ophof/w2WhojRblvSDJaGe7rJjcPN8AaOkhwdRUh7q8oYIg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@swc/core-linux-ppc64-gnu@1.15.24': - resolution: {integrity: sha512-QZEsZfisHTSJlmyChgDFNmKPb3W6Lhbfo/O76HhIngfEdnQNmukS38/VSe1feho+xkV5A5hETyCbx3sALBZKAQ==} - engines: {node: '>=10'} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@swc/core-linux-s390x-gnu@1.15.24': - resolution: {integrity: sha512-DLdJKVsJgglqQrJBuoUYNmzm3leI7kUZhLbZGHv42onfKsGf6JDS3+bzCUQfte/XOqDjh/tmmn1DR/CF/tCJFw==} - engines: {node: '>=10'} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@swc/core-linux-x64-gnu@1.15.24': - resolution: {integrity: sha512-IpLYfposPA/XLxYOKpRfeccl1p5dDa3+okZDHHTchBkXEaVCnq5MADPmIWwIYj1tudt7hORsEHccG5no6IUQRw==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@swc/core-linux-x64-musl@1.15.24': - resolution: {integrity: sha512-JHy3fMSc0t/EPWgo74+OK5TGr51aElnzqfUPaiRf2qJ/BfX5CUCfMiWVBuhI7qmVMBnk1jTRnL/xZnOSHDPLYg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@swc/core-win32-arm64-msvc@1.15.24': - resolution: {integrity: sha512-Txj+qUH1z2bUd1P3JvwByfjKFti3cptlAxhWgmunBUUxy/IW3CXLZ6l6Gk4liANadKkU71nIU1X30Z5vpMT3BA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@swc/core-win32-ia32-msvc@1.15.24': - resolution: {integrity: sha512-15D/nl3XwrhFpMv+MADFOiVwv3FvH9j8c6Rf8EXBT3Q5LoMh8YnDnSgPYqw1JzPnksvsBX6QPXLiPqmcR/Z4qQ==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - - '@swc/core-win32-x64-msvc@1.15.24': - resolution: {integrity: sha512-PR0PlTlPra2JbaDphrOAzm6s0v9rA0F17YzB+XbWD95B4g2cWcZY9LAeTa4xll70VLw9Jr7xBrlohqlQmelMFQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@swc/core@1.15.24': - resolution: {integrity: sha512-5Hj8aNasue7yusUt8LGCUe/AjM7RMAce8ZoyDyiFwx7Al+GbYKL+yE7g4sJk8vEr1dKIkTRARkNIJENc4CjkBQ==} - engines: {node: '>=10'} - peerDependencies: - '@swc/helpers': '>=0.5.17' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/types@0.1.26': - resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} - '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -1833,9 +1833,9 @@ packages: resolution: {integrity: sha512-c5JxaDrzwRjq3WyJkI1AGR5xy6Gr6udlt7sQPbl09+3ckB+Zo2qqQ2KhCTBr7Q8dHB43bENGYEk4xddrFH/b7A==} engines: {node: '>=18.20'} - bumpp@11.0.1: - resolution: {integrity: sha512-X0ti27I/ewsx/u0EJSyl0IZWWOE95q+wIpAG/60kc5gqMNR4a23YJdd3lL7JsBN11TgLbCM4KpfGMuFfdigb4g==} - engines: {node: '>=20.19.0'} + bumpp@10.4.1: + resolution: {integrity: sha512-X/bwWs5Gbb/D7rN4aHLB7zdjiA6nGdjckM1sTHhI9oovIbEw2L5pw5S4xzk8ZTeOZ8EnwU/Ze4SoZ6/Vr3pM2Q==} + engines: {node: '>=18'} hasBin: true bundle-name@4.1.0: @@ -1850,8 +1850,8 @@ packages: magicast: optional: true - c12@4.0.0-beta.4: - resolution: {integrity: sha512-gcWQAloC/SwGx4U7l3iQdalUQQLLXwYS1d3SqIwFj4UUrTXh8L9yGkBcA00B0gxELMwbxtsrt6VrAxtSgqZZoA==} + c12@4.0.0-beta.3: + resolution: {integrity: sha512-15pHxeM4kKKnF1zPgvXq/ETPhf9DRLGg0Id3GAyQhQqYxt8WkUCbo0NipHjQUUNC5VPP8TQA32pGPDUZmAi/3g==} peerDependencies: chokidar: ^5 dotenv: '*' @@ -1870,6 +1870,10 @@ packages: magicast: optional: true + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + cac@7.0.0: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} @@ -2285,6 +2289,9 @@ packages: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} + esrap@2.2.3: + resolution: {integrity: sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==} + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -3059,6 +3066,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.0.0-rc.3: + resolution: {integrity: sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + run-applescript@7.1.0: resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} engines: {node: '>=18'} @@ -3285,9 +3297,6 @@ packages: unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} - unconfig@7.5.0: - resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} - undici-types@7.19.2: resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} @@ -4098,6 +4107,8 @@ snapshots: '@oxc-minify/binding-win32-x64-msvc@0.124.0': optional: true + '@oxc-project/types@0.112.0': {} + '@oxc-project/types@0.122.0': {} '@oxc-project/types@0.124.0': {} @@ -4171,42 +4182,63 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-android-arm64@1.0.0-rc.3': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': optional: true '@rolldown/binding-darwin-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.3': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.12': optional: true '@rolldown/binding-darwin-x64@1.0.0-rc.15': optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.3': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': optional: true '@rolldown/binding-freebsd-x64@1.0.0-rc.15': optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.3': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': optional: true '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': optional: true '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': optional: true @@ -4225,18 +4257,27 @@ snapshots: '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': optional: true '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': optional: true '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) @@ -4252,24 +4293,40 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': optional: true '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': + optional: true + '@rolldown/pluginutils@1.0.0-rc.12': {} '@rolldown/pluginutils@1.0.0-rc.15': {} '@rolldown/pluginutils@1.0.0-rc.2': {} + '@rolldown/pluginutils@1.0.0-rc.3': {} + '@shikijs/core@3.23.0': dependencies: '@shikijs/types': 3.23.0 @@ -4389,66 +4446,6 @@ snapshots: estraverse: 5.3.0 picomatch: 4.0.4 - '@swc/core-darwin-arm64@1.15.24': - optional: true - - '@swc/core-darwin-x64@1.15.24': - optional: true - - '@swc/core-linux-arm-gnueabihf@1.15.24': - optional: true - - '@swc/core-linux-arm64-gnu@1.15.24': - optional: true - - '@swc/core-linux-arm64-musl@1.15.24': - optional: true - - '@swc/core-linux-ppc64-gnu@1.15.24': - optional: true - - '@swc/core-linux-s390x-gnu@1.15.24': - optional: true - - '@swc/core-linux-x64-gnu@1.15.24': - optional: true - - '@swc/core-linux-x64-musl@1.15.24': - optional: true - - '@swc/core-win32-arm64-msvc@1.15.24': - optional: true - - '@swc/core-win32-ia32-msvc@1.15.24': - optional: true - - '@swc/core-win32-x64-msvc@1.15.24': - optional: true - - '@swc/core@1.15.24': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.26 - optionalDependencies: - '@swc/core-darwin-arm64': 1.15.24 - '@swc/core-darwin-x64': 1.15.24 - '@swc/core-linux-arm-gnueabihf': 1.15.24 - '@swc/core-linux-arm64-gnu': 1.15.24 - '@swc/core-linux-arm64-musl': 1.15.24 - '@swc/core-linux-ppc64-gnu': 1.15.24 - '@swc/core-linux-s390x-gnu': 1.15.24 - '@swc/core-linux-x64-gnu': 1.15.24 - '@swc/core-linux-x64-musl': 1.15.24 - '@swc/core-win32-arm64-msvc': 1.15.24 - '@swc/core-win32-ia32-msvc': 1.15.24 - '@swc/core-win32-x64-msvc': 1.15.24 - - '@swc/counter@0.1.3': {} - - '@swc/types@0.1.26': - dependencies: - '@swc/counter': 0.1.3 - '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -4921,17 +4918,21 @@ snapshots: builtin-modules@5.1.0: {} - bumpp@11.0.1: + bumpp@10.4.1: dependencies: + ansis: 4.2.0 args-tokenizer: 0.3.0 - cac: 7.0.0 + c12: 3.3.4 + cac: 6.7.14 + escalade: 3.2.0 jsonc-parser: 3.3.1 package-manager-detector: 1.6.0 semver: 7.7.4 tinyexec: 1.1.1 tinyglobby: 0.2.16 - unconfig: 7.5.0 yaml: 2.8.3 + transitivePeerDependencies: + - magicast bundle-name@4.1.0: dependencies: @@ -4952,7 +4953,7 @@ snapshots: pkg-types: 2.3.0 rc9: 3.0.1 - c12@4.0.0-beta.4(chokidar@5.0.0)(dotenv@17.4.1)(giget@3.2.0)(jiti@2.6.1): + c12@4.0.0-beta.3(chokidar@5.0.0)(dotenv@17.4.1)(giget@3.2.0)(jiti@2.6.1): dependencies: confbox: 0.2.4 defu: 6.1.7 @@ -4966,6 +4967,8 @@ snapshots: giget: 3.2.0 jiti: 2.6.1 + cac@6.7.14: {} + cac@7.0.0: {} caniuse-lite@1.0.30001787: {} @@ -5471,6 +5474,10 @@ snapshots: dependencies: estraverse: 5.3.0 + esrap@2.2.3: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -6434,6 +6441,28 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 + rolldown@1.0.0-rc.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + dependencies: + '@oxc-project/types': 0.112.0 + '@rolldown/pluginutils': 1.0.0-rc.3 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.3 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.3 + '@rolldown/binding-darwin-x64': 1.0.0-rc.3 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.3 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.3 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.3 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.3 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.3 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.3 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + run-applescript@7.1.0: {} scslre@0.3.0: @@ -6655,14 +6684,6 @@ snapshots: '@quansync/fs': 1.0.0 quansync: 1.0.0 - unconfig@7.5.0: - dependencies: - '@quansync/fs': 1.0.0 - defu: 6.1.7 - jiti: 2.6.1 - quansync: 1.0.0 - unconfig-core: 7.5.0 - undici-types@7.19.2: {} unist-util-is@6.0.1: diff --git a/src/config.ts b/src/config.ts index 4b94e89..768574c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -110,6 +110,7 @@ const defaultConfig = { dts: "typings/prefs.d.ts", }, esbuildOptions: [], + bundle: [], makeManifest: { enable: true, template: { diff --git a/src/core/builder/esbuild.ts b/src/core/builder/esbuild.ts index 0c806f2..569edb9 100644 --- a/src/core/builder/esbuild.ts +++ b/src/core/builder/esbuild.ts @@ -1,7 +1,7 @@ import type { BuildOptions, BuildResult } from "esbuild"; import type { BuildConfig } from "../../types/config.js"; import { resolve } from "node:path"; -import { build as buildAsync } from "esbuild"; + import { logger } from "../../utils/logger.js"; export function resolveConfig(dist: string, esbuildOptions: BuildConfig["esbuildOptions"]): BuildOptions[] { @@ -27,6 +27,8 @@ export default async function esbuild(dist: string, esbuildOptions: BuildConfig[ const options = resolveConfig(dist, esbuildOptions); + const { build: buildAsync } = await import("esbuild"); + return await Promise.all( options.map(esbuildOption => buildAsync(esbuildOption), diff --git a/src/core/builder/index.ts b/src/core/builder/index.ts index 278a6dc..30cc27c 100644 --- a/src/core/builder/index.ts +++ b/src/core/builder/index.ts @@ -11,6 +11,7 @@ import buildLocale from "./fluent.js"; import buildManifest from "./manifest.js"; import buildPrefs from "./prefs.js"; import replaceDefine from "./replace.js"; +import rolldownBuild from "./rolldown.js"; import buildUpdateJson from "./update-json.js"; import pack from "./zip.js"; @@ -72,8 +73,11 @@ export default class Build extends Base { } async bundle(): Promise { - const { dist, build: { esbuildOptions } } = this.ctx; - await esbuild(dist, esbuildOptions); + const { dist, build: { esbuildOptions, bundle } } = this.ctx; + if (esbuildOptions.length !== 0) + await esbuild(dist, esbuildOptions); + + await rolldownBuild(dist, bundle); await this.ctx.hooks.callHook("build:bundle", this.ctx); } diff --git a/src/core/builder/rolldown.ts b/src/core/builder/rolldown.ts new file mode 100644 index 0000000..a337a1c --- /dev/null +++ b/src/core/builder/rolldown.ts @@ -0,0 +1,66 @@ +import type { RolldownOptions } from "rolldown"; +import type { BuildConfig, BundleItem, Config } from "../../types/config.js"; +import { resolve } from "node:path"; +import process from "node:process"; +import { rolldown } from "rolldown"; +import { toArray } from "../../utils/string.js"; + +export function resolveConfig(dist: Config["dist"], configs: BundleItem[]): RolldownOptions[] { + const distAbsolute = resolve(dist); + + // ensure output.file and output.dir are in dist folder + return configs.map((config) => { + // Extract config fields from new format with proper typing + const { input, minify, rolldown: rolldownInputConfig } = config; + + // Normalize output directory path + const outputDir = `${dist}/addon`; + const resolvedDir = resolve(outputDir).startsWith(distAbsolute) + ? outputDir + : `${dist}/${outputDir}`; + + return { + ...rolldownInputConfig, + input, + transform: { + ...rolldownInputConfig?.transform, + target: "firefox140", + define: { + __env__: `"${process.env.NODE_ENV || "production"}"`, + ...(rolldownInputConfig?.transform?.define), + }, + }, + output: { + dir: resolvedDir, + format: "iife", + // format: "esm", + // Since the Zotero sandbox environment does not support loading subpackages, + // we hope to output a single file + // Error: export declarations may only appear at top level of a module + // codeSplitting: false, + minify, + }, + }; + }); +} + +export default async function rolldownBuild(dist: string, bundleConfigs: BuildConfig["bundle"]): Promise { + const configs = toArray(bundleConfigs); + + if (configs.length === 0) + return; + + const options = resolveConfig(dist, configs); + + await Promise.all( + options.map(async (rolldownOption) => { + const { output, ...inputOptions } = rolldownOption; + const bundle = await rolldown(inputOptions); + if (output) { + const outputConfig = Array.isArray(output) ? output : [output]; + await bundle.write(outputConfig[0]); + } + await bundle.close(); + }), + ); +} diff --git a/src/core/tester/test-bundler-template/index.ts b/src/core/tester/test-bundler-template/index.ts index 8c5d147..f0cbb14 100644 --- a/src/core/tester/test-bundler-template/index.ts +++ b/src/core/tester/test-bundler-template/index.ts @@ -27,7 +27,7 @@ export function generateHtml( setupCode: string, testFiles: string[], ): string { - const tests = testFiles.map(f => ``).join("\n "); + const tests = testFiles.map(f => ``).join("\n "); return htmlRaw .replaceAll("__TEST_FILES__", tests) diff --git a/src/core/tester/test-bundler.test.ts b/src/core/tester/test-bundler.test.ts index 1a3f4a6..4acaa28 100644 --- a/src/core/tester/test-bundler.test.ts +++ b/src/core/tester/test-bundler.test.ts @@ -1,52 +1,43 @@ -import type { Metafile } from "esbuild"; +import type { MetaData } from "./test-bundler.js"; import { describe, expect, it } from "vitest"; import { findImpactedTests } from "./test-bundler.js"; describe("findImpactedTests", () => { - const mockMetafileOutputs = { - outputs: { - ".scaffold/test/resource/content/units/test1.spec.js": { - entryPoint: "test/test1.spec.ts", - inputs: { - "test/test1.spec.ts": {}, - "src/moduleA.ts": {}, - "src/moduleB.ts": {}, - }, - }, - ".scaffold/test/resource/content/units/test2.spec.js": { - entryPoint: "test/test2.spec.ts", - inputs: { - "test/test2.spec.ts": {}, - "src/moduleC.ts": {}, - }, - }, - ".scaffold/test/resource/content/units/test3.spec.js": { - entryPoint: "test/test3.spec.ts", - inputs: { - "test/test3.spec.ts": {}, - "src/moduleC.ts": {}, - }, - }, + const mockBuildMetadata: MetaData = [ + { + fileName: "test1.spec.js", + name: "", + moduleIds: ["src/moduleA.ts", "src/moduleB.ts", "test/test1.spec.ts"], }, - } as unknown as Metafile; + { + fileName: "test2.spec.js", + name: "", + moduleIds: ["test/test2.spec.ts", "src/moduleC.ts"], + }, + { + fileName: "test3.spec.js", + name: "", + moduleIds: ["test/test3.spec.ts", "src/moduleC.ts"], + }, + ]; it("returns affected test file when a test file itself is changed", () => { - const result = findImpactedTests("test/test1.spec.ts", mockMetafileOutputs); - expect(result).toEqual(["units/test1.spec.js"]); + const result = findImpactedTests("test/test1.spec.ts", mockBuildMetadata); + expect(result).toEqual(["test1.spec.js"]); }); it("returns affected test files when a source file is changed", () => { - const result = findImpactedTests("src/moduleA.ts", mockMetafileOutputs); - expect(result).toEqual(["units/test1.spec.js"]); + const result = findImpactedTests("src/moduleA.ts", mockBuildMetadata); + expect(result).toEqual(["test1.spec.js"]); }); it("returns multiple affected test files when multiple tests depend on the changed file", () => { - const result = findImpactedTests("src/moduleC.ts", mockMetafileOutputs); - expect(result).toEqual(["units/test2.spec.js", "units/test3.spec.js"]); + const result = findImpactedTests("src/moduleC.ts", mockBuildMetadata); + expect(result).toEqual(["test2.spec.js", "test3.spec.js"]); }); it("returns an empty array if no test file is affected", () => { - const result = findImpactedTests("src/unrelated.ts", mockMetafileOutputs); + const result = findImpactedTests("src/unrelated.ts", mockBuildMetadata); expect(result).toEqual([]); }); }); diff --git a/src/core/tester/test-bundler.ts b/src/core/tester/test-bundler.ts index fb0841c..4f5daa0 100644 --- a/src/core/tester/test-bundler.ts +++ b/src/core/tester/test-bundler.ts @@ -1,17 +1,18 @@ -import type { BuildContext, BuildResult } from "esbuild"; +import type { InputOptions, OutputChunk, OutputOptions, RolldownOutput } from "rolldown"; import type { Context } from "../../types/index.js"; -import { resolve } from "node:path"; -import { context } from "esbuild"; +import { relative, resolve } from "node:path"; +import { cwd } from "node:process"; import { copy, outputFile, outputJSON, pathExists } from "fs-extra/esm"; +import { rolldown } from "rolldown"; import { glob } from "tinyglobby"; -import { CACHE_DIR, TESTER_PLUGIN_DIR } from "../../constant.js"; +import { CACHE_DIR, TESTER_PLUGIN_DIR, TESTER_PLUGIN_TESTS_DIR } from "../../constant.js"; import { saveResource } from "../../utils/file.js"; import { logger } from "../../utils/logger.js"; -import { toArray } from "../../utils/string.js"; +import { normalizePath, toArray } from "../../utils/string.js"; import { generateBootstrap, generateHtml, generateManifest, generateMochaSetup } from "./test-bundler-template/index.js"; export class TestBundler { - private esbuildContext?: BuildContext; + private rolldownOutput?: RolldownOutput; constructor( private ctx: Context, private port: number, @@ -35,10 +36,11 @@ export class TestBundler { async regenerate(changedFile: string): Promise { // re-bundle tests - const esbuildResult = await this.esbuildContext?.rebuild(); + await this.bundleTests(); - // get affected tests - const tests = findImpactedTests(changedFile, esbuildResult?.metafile); + // get affected tests based on changed file + const metadata = transformRolldownOutputToMetafile(this.rolldownOutput?.output); + const tests = findImpactedTests(changedFile, metadata); // this.generateTestPage // mocha setup @@ -110,21 +112,28 @@ export class TestBundler { private async bundleTests() { const testDirs = toArray(this.ctx.test.entries); - // Because esbuild only support `*` and `**`, - // so we need glob ourselves. - // https://esbuild.github.io/api/#glob-style-entry-points + // Find all test files const entryPoints = (await Promise.all(testDirs.map(dir => glob(`${dir}/**/*.{spec,test}.[jt]s`)))) .flat(); - // Bundle all test files, including both JavaScript and TypeScript - this.esbuildContext = await context({ - entryPoints, - outdir: `${TESTER_PLUGIN_DIR}/content/units`, - bundle: true, - target: "firefox115", - metafile: true, - }); - await this.esbuildContext.rebuild(); + // configure rolldown options + const rolldownInputOptions: InputOptions = { + input: entryPoints, + treeshake: false, + preserveEntrySignatures: "allow-extension", + }; + + const outputOptions: OutputOptions = { + dir: `${TESTER_PLUGIN_DIR}/content/units`, + format: "esm", + sourcemap: true, + codeSplitting: false, + }; + + const rolldownBuild = await rolldown(rolldownInputOptions); + this.rolldownOutput = await rolldownBuild.write(outputOptions); + + await rolldownBuild.close(); } private async createTestHtml(tests: string[] = []) { @@ -139,38 +148,55 @@ export class TestBundler { // html let testFiles = tests; if (testFiles.length === 0) { - testFiles = (await glob(`**/*.{spec,test}.js`, { cwd: `${TESTER_PLUGIN_DIR}/content` })).sort(); + testFiles = (await glob(`**/*.{spec,test}.js`, { cwd: `${TESTER_PLUGIN_TESTS_DIR}` })).sort(); } const html = generateHtml(setupCode, testFiles); await outputFile(`${TESTER_PLUGIN_DIR}/content/index.xhtml`, html); } } +interface _MetaData extends Pick {} +export type MetaData = _MetaData[]; + +function transformRolldownOutputToMetafile(output?: RolldownOutput["output"]): MetaData { + if (!output) + return []; + + return output + .flat() + .filter(r => r.type === "chunk") + .map(r => ({ + fileName: normalizePath(r.fileName), + name: r.name, + moduleIds: r.moduleIds.map(id => relative(cwd(), id)).map(normalizePath), + })); +} + /** - * Determines which test files are impacted by a given changed file based on the esbuild metafile. + * Determines which test files are impacted by a given changed file based on rolldown build output. * * This function analyzes the build metadata to find test files that depend on the changed file - * either directly as an entry point or indirectly as an input. It is useful in a watch mode setup - * to selectively rerun only the affected tests. + * either directly as an entry point or indirectly as an input. * * @param {string} changedFilePath - The file path of the changed source file. - * @param {BuildResult["metafile"]} buildMetadata - The esbuild metafile containing dependency information. - * @returns {string[]} An array of impacted test file paths that need to be re-executed. + * @param {MetaData} buildMetadata - The transfromed rolldown build outputs. + * @returns {string[]} An array of impacted test file names that need to be re-executed. */ -export function findImpactedTests(changedFilePath: string, buildMetadata: BuildResult["metafile"]): string[] { - if (!buildMetadata) - return []; - - const resolvedChangedFile = resolve(changedFilePath); +export function findImpactedTests( + changedFilePath: string, + buildMetadata: MetaData, +): string[] { + const normalizedChangedFile = resolve(changedFilePath); const impactedTestFiles = new Set(); - for (const [outputFilePath, outputInfo] of Object.entries(buildMetadata.outputs)) { - const testFilePath = outputFilePath.replace(`${TESTER_PLUGIN_DIR}/content/`, ""); - // const resolvedEntryPoint = outputInfo.entryPoint ? resolve(outputInfo.entryPoint) : null; - - if (Object.keys(outputInfo.inputs).some(inputPath => resolve(inputPath) === resolvedChangedFile)) { - impactedTestFiles.add(testFilePath); + for (const { fileName, moduleIds } of buildMetadata) { + for (const moduleId of moduleIds) { + const normalizedModuleId = resolve(moduleId); + if (normalizedModuleId === normalizedChangedFile) { + impactedTestFiles.add(fileName); + } } } + return [...impactedTestFiles]; } diff --git a/src/types/config.ts b/src/types/config.ts index 444f294..de950f9 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,9 +1,12 @@ import type { GitCommit } from "changelogen"; -import type { BuildOptions } from "esbuild"; +import type { BuildOptions as esbuildConfig } from "esbuild"; +import type { InputOptions, RolldownPluginOption, TransformOptions } from "rolldown"; +import type { MinifyOptions } from "rolldown/experimental"; import type { LogLevelType } from "../utils/logger.js"; import type { Context } from "./index.js"; import type { Manifest } from "./manifest.js"; import type { UpdateJSON } from "./update-json.js"; +import type { Arrayable } from "./utils.js"; export interface Config { /** @@ -174,6 +177,58 @@ export interface Config { logLevel: LogLevelType; } +export interface BundleItem { + /** + * + * @example + * + * ```ts + * // Single entry + * entries: "src/index.ts" // -> outDir/index.js + * + * // Multiple entries + * entries: [ + * "src/index.ts", // -> outDir/index.js + * "src/another-entry.ts" // -> outDir/another-entry.js + * ] + * + * // Named multiple entries + * entries: { + * bootstrap: "src/bootstrap.ts", // -> outDir/bootstrap.js + * content: "src/content.ts", // -> outDir/content.js + * 'components/Foo': 'src/components/Foo.js', // -> outDir/components/Foo.js + * } + * ``` + * + * The outDir is based on {@linkcode Config.dist | dist/build/addon }. + * + * @see https://rolldown.rs/reference/InputOptions.input + */ + input: InputOptions["input"]; + + /** + * Replace global variables or [property accessors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors) with the provided values. + * + * See Oxc's [`define` option](https://oxc.rs/docs/guide/usage/transformer/global-variable-replacement.html#define) for more details. + * + */ + define?: TransformOptions["define"]; + + /** + * Minify the output using rolldown. + * + * Defaults to `false` if not provided. + */ + minify?: boolean | "dce-only" | MinifyOptions; + + /** + * Options passed to rolldown. + * + * See [rolldown config options](https://rolldown.rs/reference/config-options) for more details. + */ + rolldown?: Omit & { plugins?: RolldownPluginOption[] }; +} + export interface BuildConfig { /** * The static assets. @@ -294,22 +349,42 @@ export interface BuildConfig { dts: false | string; }; /** - * Configurations of esbuild. + * Configurations for code bundler (rolldown). + * + * Paths should be relative to the root directory of the project. + * And if `output.file` and `output.dir` not start with `dist`, + * `dist/` will be automatically added as a prefix. + * + * 代码捆绑器(rolldown)的配置。 + * + * 路径应相对于项目根目录。 + * 其中"output.file"和"output.dir"若不以 `dist` 开头, + * 则会自动添加 `dist/` 前缀。 + * + * @default [] + * + * @deprecated Use `build.bundle` instead. + * + */ + esbuildOptions: esbuildConfig[]; + /** + * Configurations for code bundler (rolldown). * * Paths should be relative to the root directory of the project. - * And if `outfile` and `outdir` not start with `dist`, + * And if `output.file` and `output.dir` not start with `dist`, * `dist/` will be automatically added as a prefix. * - * esbuild 配置。 + * 代码捆绑器(rolldown)的配置。 * * 路径应相对于项目根目录。 - * 其中“outfile”和“outdir”若不以 `dist` 开头, + * 其中"output.file"和"output.dir"若不以 `dist` 开头, * 则会自动添加 `dist/` 前缀。 * * @default [] * */ - esbuildOptions: BuildOptions[]; + bundle: Arrayable; + /** * Make manifest.json. * diff --git a/src/types/index.ts b/src/types/index.ts index c27b823..3e9f38d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -4,6 +4,7 @@ import type { Config, Hooks } from "./config.js"; import type { RecursivePartial } from "./utils.js"; export { Config, Hooks }; +export type { BuildConfig } from "./config.js"; /** * User config diff --git a/src/types/utils.ts b/src/types/utils.ts index 9b46c1f..f4fa1e2 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -23,3 +23,6 @@ type RecursiveOptionalKeys = { export type RecursivePickOptional = { [K in keyof T as K extends RecursiveOptionalKeys ? K : never]?: T[K] extends object ? RecursivePickOptional : T[K]; }; + +export type Awaitable = T | Promise; +export type Arrayable = T | T[]; diff --git a/src/utils/prefs-manager.test.ts b/src/utils/prefs-manager.test.ts index c142e79..6f867ef 100644 --- a/src/utils/prefs-manager.test.ts +++ b/src/utils/prefs-manager.test.ts @@ -205,14 +205,13 @@ pref("test.boolean.true", true); }); const result = [ - "pref(\"test.string\", \"hello\");", - "pref(\"test.quote\", '{\"key\": \"value\"}');", - "pref(\"test.singleQuote\", \"{key: value}\");", - "pref(\"test.path\", \"C:\\\\path\\\\to\\\\file\");", - "pref(\"test.number\", 42);", - "pref(\"test.-1\", -1);", - "pref(\"test.boolean\", true);", - "", + `pref(\"test.string\", \"hello\");`, + `pref(\"test.quote\", "{\\"key\\": \\"value\\"}");`, + `pref(\"test.singleQuote\", \"{key: value}\");`, + `pref(\"test.path\", \"C:\\\\path\\\\to\\\\file\");`, + `pref(\"test.number\", 42);`, + `pref(\"test.-1\", -1);`, + `pref(\"test.boolean\", true);`, ].join("\n"); expect(prefsManager.render()).toBe(result); @@ -239,9 +238,8 @@ describe("prefs-manager (user_pref)", () => { }); const result = [ - "user_pref(\"test.string\", \"hello\");", - "user_pref(\"test.number\", 42);", - "", + `user_pref(\"test.string\", \"hello\");`, + `user_pref(\"test.number\", 42);`, ].join("\n"); expect(prefsManager.render()).toBe(result); diff --git a/src/utils/prefs-manager.ts b/src/utils/prefs-manager.ts index 2fa2012..3ca9d2e 100644 --- a/src/utils/prefs-manager.ts +++ b/src/utils/prefs-manager.ts @@ -1,9 +1,19 @@ -import type { Program } from "@swc/core"; +import type { BooleanLiteral, NumericLiteral, StringLiteral, UnaryExpression } from "@oxc-project/types"; +import type { ParseResult } from "rolldown/experimental"; import { readFile } from "node:fs/promises"; -import { parseSync, printSync } from "@swc/core"; +import { print } from "esrap"; +import ts from "esrap/languages/ts"; import { outputFile } from "fs-extra/esm"; +import { parseSync } from "rolldown/experimental"; import { logger } from "./logger.js"; +class PrefFileError extends Error { + constructor(message: string) { + super(); + this.message = `Invalid prefs.js file - ${message}`; + } +} + /** * type of pref value only supports string (Char, String), number (Int), and boolean (Boolean) * @@ -25,54 +35,61 @@ export class PrefsManager { */ parse(content: string): Prefs { const _map: Prefs = {}; - const ast = parseSync(content, { syntax: "ecmascript" }); - for (const node of ast.body) { + const { program, errors } = parseSync("prefs.js", content); + if (errors.length) + throw new PrefFileError(errors.map(e => e.message).join("\n")); + + for (const node of program.body) { if ( node.type !== "ExpressionStatement" || node.expression.type !== "CallExpression" || node.expression.callee.type !== "Identifier" - || node.expression.callee.value !== this.namespace + || node.expression.callee.name !== this.namespace || node.expression.arguments.length !== 2 ) { - throw new Error("Invalid prefs.js file."); + throw new PrefFileError(`No ${this.namespace} callee found`); } const [arg1, arg2] = node.expression.arguments; - if (arg1.expression.type !== "StringLiteral") { - throw new Error("Invalid prefs.js file - unsupported key type."); + if (arg1.type !== "Literal" || typeof arg1.value !== "string") { + throw new PrefFileError(`Unsupported key type for ${arg1}`); } - const key = arg1.expression.value.trim(); + const key = arg1.value?.trim(); let value: PrefValue; - switch (arg2.expression.type) { - // https://babeljs.io/docs/babel-parser#output - case "StringLiteral": - case "NumericLiteral": - case "BooleanLiteral": - value = arg2.expression.value; + switch (arg2.type) { + case "Literal": + if ( + typeof arg2.value !== "boolean" + && typeof arg2.value !== "string" + && typeof arg2.value !== "number" + ) { + throw new PrefFileError(`Unsupported value type for ${arg2}`); + } + value = arg2.value; break; // https://github.com/estree/estree/blob/master/es5.md#unaryexpression // https://github.com/northword/zotero-plugin-scaffold/issues/98 case "UnaryExpression": - if (arg2.expression.argument.type !== "NumericLiteral") - throw new Error("Invalid prefs.js file - unsupported value type."); + if (arg2.argument.type !== "Literal" || typeof arg2.argument.value !== "number") + throw new PrefFileError(`Unsupported value type for ${arg2}`); - if (arg2.expression.operator === "-") - value = -arg2.expression.argument.value; - else if (arg2.expression.operator === "+") - value = arg2.expression.argument.value; + if (arg2.operator === "-") + value = -arg2.argument.value; + else if (arg2.operator === "+") + value = arg2.argument.value; else - throw new Error("Invalid prefs.js file - unsupported value type."); + throw new PrefFileError(`Unsupported value type for ${arg2}`); break; case "TemplateLiteral": - value = arg2.expression.quasis[0]?.cooked ?? ""; + value = arg2.quasis[0]?.value.cooked ?? ""; break; default: - throw new Error("Invalid prefs.js file - unsupported value type."); + throw new PrefFileError(`Unsupported value type for ${arg2}`); } _map[key] = value; @@ -133,69 +150,68 @@ export class PrefsManager { render(): string { const span = { start: 0, end: 0, ctxt: 0 }; - function getExpression(value: unknown) { + function getExpression(value: unknown): StringLiteral | NumericLiteral | BooleanLiteral | UnaryExpression { switch (typeof value) { case "string": - return { - type: "StringLiteral", - span, - value, - }; case "boolean": return { - type: "BooleanLiteral", - span, + type: "Literal", + ...span, value, - }; + raw: null, + } satisfies StringLiteral | BooleanLiteral; case "number": if (value < 0) { return { type: "UnaryExpression", - span, + ...span, operator: "-", argument: { - type: "NumericLiteral", - span, + type: "Literal", + ...span, value: Math.abs(value), + raw: null, }, - }; + prefix: true, + } satisfies UnaryExpression; } return { - type: "NumericLiteral", - span, + type: "Literal", + ...span, value, - }; + raw: null, + } satisfies NumericLiteral; default: throw new Error(`Unsupported value type: ${typeof value}`); } } - const ast: Program = { - type: "Module", - span, - // @ts-expect-error no raw property + const program: ParseResult["program"] = { + type: "Program", + sourceType: "script", + hashbang: null, + ...span, body: Object.entries(this.prefs).map(([key, value]) => ({ type: "ExpressionStatement", - span, + ...span, expression: { type: "CallExpression", - span, - ctxt: 0, + ...span, + optional: false, callee: { type: "Identifier", - span, - ctxt: 0, - value: this.namespace, - optional: false, + name: this.namespace, + ...span, }, arguments: [ - { expression: getExpression(key) }, - { expression: getExpression(value) }, + getExpression(key), + getExpression(value), ], }, })), }; - const { code } = printSync(ast); + // @ts-expect-error no comments, loc, token + const { code } = print(program, ts({ quotes: "double" })); return code; } @@ -298,124 +314,84 @@ export class PrefsManager { * pref("key1", -1) */ const _ast_example = { - type: "Module", - span: { - start: 0, - end: 39, - }, + type: "Program", body: [ { type: "ExpressionStatement", - span: { - start: 0, - end: 21, - }, expression: { type: "CallExpression", - span: { - start: 0, - end: 21, - }, - ctxt: 0, callee: { type: "Identifier", - span: { - start: 0, - end: 4, - }, - ctxt: 1, - value: "pref", - optional: false, + name: "pref", + start: 0, + end: 4, }, arguments: [ { - spread: null, - expression: { - type: "StringLiteral", - span: { - start: 5, - end: 11, - }, - value: "key2", - raw: "\"key2\"", - }, + type: "Literal", + value: "key2", + raw: "\"key2\"", + start: 5, + end: 11, }, { - spread: null, - expression: { - type: "StringLiteral", - span: { - start: 13, - end: 20, - }, - value: "value", - raw: "\"value\"", - }, + type: "Literal", + value: "value", + raw: "\"value\"", + start: 13, + end: 20, }, ], - typeArguments: null, + optional: false, + start: 0, + end: 21, }, + start: 0, + end: 21, }, { type: "ExpressionStatement", - span: { - start: 23, - end: 39, - }, expression: { type: "CallExpression", - span: { - start: 23, - end: 39, - }, - ctxt: 0, callee: { type: "Identifier", - span: { - start: 23, - end: 27, - }, - ctxt: 1, - value: "pref", - optional: false, + name: "pref", + start: 22, + end: 26, }, arguments: [ { - spread: null, - expression: { - type: "StringLiteral", - span: { - start: 28, - end: 34, - }, - value: "key1", - raw: "\"key1\"", - }, + type: "Literal", + value: "key1", + raw: "\"key1\"", + start: 27, + end: 33, }, { - spread: null, - expression: { - type: "UnaryExpression", - span: { - start: 36, - end: 38, - }, - operator: "-", - argument: { - type: "NumericLiteral", - span: { - start: 37, - end: 38, - }, - value: 1, - raw: "1", - }, + type: "UnaryExpression", + operator: "-", + argument: { + type: "Literal", + value: 1, + raw: "1", + start: 36, + end: 37, }, + prefix: true, + start: 35, + end: 37, }, ], - typeArguments: null, + optional: false, + start: 22, + end: 38, }, + start: 22, + end: 38, }, ], - interpreter: null, + sourceType: "script", + hashbang: null, + start: 0, + end: 38, }; diff --git a/src/utils/string.ts b/src/utils/string.ts index 20f7af0..b3406f6 100644 --- a/src/utils/string.ts +++ b/src/utils/string.ts @@ -53,3 +53,7 @@ export function parseRepoUrl(url?: string): { const [, owner, repo] = match; return { owner, repo }; } + +export function normalizePath(path: string): string { + return path.replace(/\\/g, "/"); +} diff --git a/test/e2e/snap/dist/addon/prefs.js b/test/e2e/snap/dist/addon/prefs.js index 6773a32..5bc088a 100644 --- a/test/e2e/snap/dist/addon/prefs.js +++ b/test/e2e/snap/dist/addon/prefs.js @@ -3,5 +3,5 @@ pref("extensions.testplugin.boolean", true); pref("extensions.testplugin.number", 123); pref("extensions.testplugin.break-line", "123"); pref("extensions.testplugin.fake-number", "123"); -pref("extensions.testplugin.templateLiteral", '{\n "key": "value" \n}'); -pref("extensions.testplugin.long-number", 2222222222222222); +pref("extensions.testplugin.templateLiteral", "{\n \"key\": \"value\" \n}"); +pref("extensions.testplugin.long-number", 2222222222222222); \ No newline at end of file