.:
devDependencies:
+ '@posva/prompts':
+ specifier: ^2.4.4
+ version: 2.4.4
'@vitejs/plugin-vue':
specifier: ^6.0.1
version: 6.0.1(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(terser@5.43.1)(yaml@2.8.1))(vue@3.6.0-alpha.2(typescript@5.9.3))
chalk:
specifier: ^5.6.2
version: 5.6.2
- enquirer:
- specifier: ^2.4.1
- version: 2.4.1
execa:
specifier: ^9.6.0
version: 9.6.0
globby:
- specifier: ^14.1.0
- version: 14.1.0
+ specifier: ^15.0.0
+ version: 15.0.0
lint-staged:
- specifier: ^15.5.2
- version: 15.5.2
+ specifier: ^16.2.4
+ version: 16.2.4
minimist:
specifier: ^1.2.8
version: 1.2.8
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
+ '@posva/prompts@2.4.4':
+ resolution: {integrity: sha512-8aPwklhbSV2VN/NQMBNFkuo8+hlJVdcFRXp4NCIfdcahh3qNEcaSoD8qXjru0OlN1sONJ7le7p6+YUbALaG6Mg==}
+ engines: {node: '>= 14'}
+
'@quansync/fs@0.1.5':
resolution: {integrity: sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==}
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
- '@sindresorhus/merge-streams@2.3.0':
- resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
- engines: {node: '>=18'}
-
'@sindresorhus/merge-streams@4.0.0':
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
engines: {node: '>=18'}
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
engines: {node: '>=6'}
- ansi-colors@4.1.3:
- resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
- engines: {node: '>=6'}
-
- ansi-escapes@7.0.0:
- resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==}
+ ansi-escapes@7.1.1:
+ resolution: {integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==}
engines: {node: '>=18'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
engines: {node: '>=10'}
- ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
engines: {node: '>=12'}
ansi-to-html@0.7.2:
resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
engines: {node: 10.* || >= 12.*}
- cli-truncate@4.0.0:
- resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
- engines: {node: '>=18'}
+ cli-truncate@5.1.0:
+ resolution: {integrity: sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==}
+ engines: {node: '>=20'}
cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
- commander@13.1.0:
- resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
- engines: {node: '>=18'}
+ commander@14.0.1:
+ resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==}
+ engines: {node: '>=20'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
emoji-regex-xs@1.0.0:
resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
- emoji-regex@10.4.0:
- resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
+ emoji-regex@10.6.0:
+ resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
- enquirer@2.4.1:
- resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
- engines: {node: '>=8.6'}
-
entities@2.2.0:
resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
- execa@8.0.1:
- resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
- engines: {node: '>=16.17'}
-
execa@9.6.0:
resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==}
engines: {node: ^18.19.0 || >=20.5.0}
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
- get-east-asian-width@1.3.0:
- resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
+ get-east-asian-width@1.4.0:
+ resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'}
get-func-name@2.0.2:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
- get-stream@8.0.1:
- resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
- engines: {node: '>=16'}
-
get-stream@9.0.1:
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
engines: {node: '>=18'}
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'}
- globby@14.1.0:
- resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
- engines: {node: '>=18'}
+ globby@15.0.0:
+ resolution: {integrity: sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==}
+ engines: {node: '>=20'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
- human-signals@5.0.0:
- resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
- engines: {node: '>=16.17.0'}
-
human-signals@8.0.1:
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
engines: {node: '>=18.18.0'}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
- ignore@7.0.4:
- resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==}
+ ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
immediate@3.0.6:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
- is-fullwidth-code-point@4.0.0:
- resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
- engines: {node: '>=12'}
-
- is-fullwidth-code-point@5.0.0:
- resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==}
+ is-fullwidth-code-point@5.1.0:
+ resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
engines: {node: '>=18'}
is-glob@4.0.3:
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'}
- is-stream@3.0.0:
- resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
kolorist@1.8.0:
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
- lint-staged@15.5.2:
- resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
- engines: {node: '>=18.12.0'}
+ lint-staged@16.2.4:
+ resolution: {integrity: sha512-Pkyr/wd90oAyXk98i/2KwfkIhoYQUMtss769FIT9hFM5ogYZwrk+GRE46yKXSg2ZGhcJ1p38Gf5gmI5Ohjg2yg==}
+ engines: {node: '>=20.17'}
hasBin: true
- listr2@8.3.2:
- resolution: {integrity: sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==}
- engines: {node: '>=18.0.0'}
+ listr2@9.0.4:
+ resolution: {integrity: sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==}
+ engines: {node: '>=20.0.0'}
load-json-file@4.0.0:
resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==}
engines: {node: '>=10'}
- merge-stream@2.0.0:
- resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
-
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
- mimic-fn@4.0.0:
- resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
- engines: {node: '>=12'}
-
mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
engines: {node: '>=18'}
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ nano-spawn@2.0.0:
+ resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==}
+ engines: {node: '>=20.17'}
+
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
- npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
npm-run-path@6.0.0:
resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
engines: {node: '>=18'}
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
- onetime@6.0.0:
- resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
- engines: {node: '>=12'}
-
onetime@7.0.0:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
slash@5.1.0:
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
engines: {node: '>=14.16'}
- slice-ansi@5.0.0:
- resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
- engines: {node: '>=12'}
-
- slice-ansi@7.1.0:
- resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
+ slice-ansi@7.1.2:
+ resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
engines: {node: '>=18'}
smart-buffer@4.2.0:
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
engines: {node: '>=18'}
+ string-width@8.1.0:
+ resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==}
+ engines: {node: '>=20'}
+
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
- strip-final-newline@3.0.0:
- resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
- engines: {node: '>=12'}
-
strip-final-newline@4.0.0:
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
engines: {node: '>=18'}
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
- wrap-ansi@9.0.0:
- resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
+ wrap-ansi@9.0.2:
+ resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
engines: {node: '>=18'}
wrappy@1.0.2:
'@polka/url@1.0.0-next.29': {}
+ '@posva/prompts@2.4.4':
+ dependencies:
+ kleur: 4.1.5
+ sisteransi: 1.0.5
+
'@quansync/fs@0.1.5':
dependencies:
quansync: 0.2.11
'@shikijs/vscode-textmate@10.0.2': {}
- '@sindresorhus/merge-streams@2.3.0': {}
-
'@sindresorhus/merge-streams@4.0.0': {}
'@testim/chrome-version@1.1.4': {}
ansi-colors@4.1.1: {}
- ansi-colors@4.1.3: {}
-
- ansi-escapes@7.0.0:
+ ansi-escapes@7.1.1:
dependencies:
environment: 1.1.0
ansi-styles@5.2.0: {}
- ansi-styles@6.2.1: {}
+ ansi-styles@6.2.3: {}
ansi-to-html@0.7.2:
dependencies:
optionalDependencies:
'@colors/colors': 1.5.0
- cli-truncate@4.0.0:
+ cli-truncate@5.1.0:
dependencies:
- slice-ansi: 5.0.0
- string-width: 7.2.0
+ slice-ansi: 7.1.2
+ string-width: 8.1.0
cliui@7.0.4:
dependencies:
commander@10.0.1: {}
- commander@13.1.0: {}
+ commander@14.0.1: {}
commander@2.20.3: {}
emoji-regex-xs@1.0.0: {}
- emoji-regex@10.4.0: {}
+ emoji-regex@10.6.0: {}
emoji-regex@8.0.0: {}
dependencies:
once: 1.4.0
- enquirer@2.4.1:
- dependencies:
- ansi-colors: 4.1.3
- strip-ansi: 6.0.1
-
entities@2.2.0: {}
entities@4.5.0: {}
eventemitter3@5.0.1: {}
- execa@8.0.1:
- dependencies:
- cross-spawn: 7.0.6
- get-stream: 8.0.1
- human-signals: 5.0.0
- is-stream: 3.0.0
- merge-stream: 2.0.0
- npm-run-path: 5.3.0
- onetime: 6.0.0
- signal-exit: 4.1.0
- strip-final-newline: 3.0.0
-
execa@9.6.0:
dependencies:
'@sindresorhus/merge-streams': 4.0.0
get-caller-file@2.0.5: {}
- get-east-asian-width@1.3.0: {}
+ get-east-asian-width@1.4.0: {}
get-func-name@2.0.2: {}
dependencies:
pump: 3.0.3
- get-stream@8.0.1: {}
-
get-stream@9.0.1:
dependencies:
'@sec-ant/readable-stream': 0.4.1
globals@15.15.0: {}
- globby@14.1.0:
+ globby@15.0.0:
dependencies:
- '@sindresorhus/merge-streams': 2.3.0
+ '@sindresorhus/merge-streams': 4.0.0
fast-glob: 3.3.3
- ignore: 7.0.4
+ ignore: 7.0.5
path-type: 6.0.0
slash: 5.1.0
unicorn-magic: 0.3.0
transitivePeerDependencies:
- supports-color
- human-signals@5.0.0: {}
-
human-signals@8.0.1: {}
iconv-lite@0.6.3:
ieee754@1.2.1: {}
- ignore@7.0.4: {}
+ ignore@7.0.5: {}
immediate@3.0.6: {}
is-fullwidth-code-point@3.0.0: {}
- is-fullwidth-code-point@4.0.0: {}
-
- is-fullwidth-code-point@5.0.0:
+ is-fullwidth-code-point@5.1.0:
dependencies:
- get-east-asian-width: 1.3.0
+ get-east-asian-width: 1.4.0
is-glob@4.0.3:
dependencies:
dependencies:
call-bound: 1.0.4
- is-stream@3.0.0: {}
-
is-stream@4.0.1: {}
is-string@1.1.1:
kind-of@6.0.3: {}
+ kleur@4.1.5: {}
+
kolorist@1.8.0: {}
lazystream@1.0.1:
dependencies:
uc.micro: 2.1.0
- lint-staged@15.5.2:
+ lint-staged@16.2.4:
dependencies:
- chalk: 5.6.2
- commander: 13.1.0
- debug: 4.4.3
- execa: 8.0.1
- lilconfig: 3.1.3
- listr2: 8.3.2
+ commander: 14.0.1
+ listr2: 9.0.4
micromatch: 4.0.8
+ nano-spawn: 2.0.0
pidtree: 0.6.0
string-argv: 0.3.2
yaml: 2.8.1
- transitivePeerDependencies:
- - supports-color
- listr2@8.3.2:
+ listr2@9.0.4:
dependencies:
- cli-truncate: 4.0.0
+ cli-truncate: 5.1.0
colorette: 2.0.20
eventemitter3: 5.0.1
log-update: 6.1.0
rfdc: 1.4.1
- wrap-ansi: 9.0.0
+ wrap-ansi: 9.0.2
load-json-file@4.0.0:
dependencies:
log-update@6.1.0:
dependencies:
- ansi-escapes: 7.0.0
+ ansi-escapes: 7.1.1
cli-cursor: 5.0.0
- slice-ansi: 7.1.0
+ slice-ansi: 7.1.2
strip-ansi: 7.1.2
- wrap-ansi: 9.0.0
+ wrap-ansi: 9.0.2
loglevel-plugin-prefix@0.8.4: {}
type-fest: 0.18.1
yargs-parser: 20.2.9
- merge-stream@2.0.0: {}
-
merge2@1.4.1: {}
micromark-util-character@2.1.1:
mimic-fn@2.1.0: {}
- mimic-fn@4.0.0: {}
-
mimic-function@5.0.1: {}
min-indent@1.0.1: {}
object-assign: 4.1.1
thenify-all: 1.6.0
+ nano-spawn@2.0.0: {}
+
nanoid@3.3.11: {}
nanoid@5.1.6: {}
normalize-path@3.0.0: {}
- npm-run-path@5.3.0:
- dependencies:
- path-key: 4.0.0
-
npm-run-path@6.0.0:
dependencies:
path-key: 4.0.0
dependencies:
mimic-fn: 2.1.0
- onetime@6.0.0:
- dependencies:
- mimic-fn: 4.0.0
-
onetime@7.0.0:
dependencies:
mimic-function: 5.0.1
mrmime: 2.0.1
totalist: 3.0.1
- slash@5.1.0: {}
+ sisteransi@1.0.5: {}
- slice-ansi@5.0.0:
- dependencies:
- ansi-styles: 6.2.1
- is-fullwidth-code-point: 4.0.0
+ slash@5.1.0: {}
- slice-ansi@7.1.0:
+ slice-ansi@7.1.2:
dependencies:
- ansi-styles: 6.2.1
- is-fullwidth-code-point: 5.0.0
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 5.1.0
smart-buffer@4.2.0: {}
string-width@7.2.0:
dependencies:
- emoji-regex: 10.4.0
- get-east-asian-width: 1.3.0
+ emoji-regex: 10.6.0
+ get-east-asian-width: 1.4.0
+ strip-ansi: 7.1.2
+
+ string-width@8.1.0:
+ dependencies:
+ get-east-asian-width: 1.4.0
strip-ansi: 7.1.2
string_decoder@1.1.1:
strip-bom@3.0.0: {}
- strip-final-newline@3.0.0: {}
-
strip-final-newline@4.0.0: {}
strip-indent@3.0.0:
wrap-ansi@8.1.0:
dependencies:
- ansi-styles: 6.2.1
+ ansi-styles: 6.2.3
string-width: 5.1.2
strip-ansi: 7.1.2
- wrap-ansi@9.0.0:
+ wrap-ansi@9.0.2:
dependencies:
- ansi-styles: 6.2.1
+ ansi-styles: 6.2.3
string-width: 7.2.0
strip-ansi: 7.1.2
-import minimist from 'minimist'
import fs from 'node:fs/promises'
-import { join, resolve, dirname } from 'node:path'
+import { existsSync } from 'node:fs'
+import { dirname, join, relative } from 'node:path'
import { fileURLToPath } from 'node:url'
+import minimist from 'minimist'
import chalk from 'chalk'
import semver from 'semver'
-import enquirer from 'enquirer'
+import prompts from '@posva/prompts'
import { execa } from 'execa'
import pSeries from 'p-series'
import { globby } from 'globby'
-const { prompt } = enquirer
-
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const args = minimist(process.argv.slice(2))
-let {
+const {
skipBuild,
tag: optionTag,
dry: isDryRun,
skipCleanCheck: skipCleanGitCheck,
noDepsUpdate,
noPublish,
+ noLockUpdate,
+ all: skipChangeCheck,
} = args
if (args.h || args.help) {
--skipCleanCheck Skip checking if the git repo is clean
--noDepsUpdate Skip updating dependencies in package.json files
--noPublish Skip publishing packages
+ --noLockUpdate Skips updating the lock with "pnpm install"
+ --all Skip checking if the packages have changed since last release
`.trim()
)
process.exit(0)
}
// const preId =
-// args.preid ||
+// args.preId ||
// (semver.prerelease(currentVersion) && semver.prerelease(currentVersion)[0])
const EXPECTED_BRANCH = 'main'
+// this package will use tags like v1.0.0 while the rest will use the full package name like @pinia/testing@1.0.0
+const MAIN_PKG_NAME = 'vue-router'
+// whether the main package is at the root of the mono repo or this is not a mono repo
+const IS_MAIN_PKG_ROOT = false
+// array of folders of packages to release
+const PKG_FOLDERS = [
+ // comment for multiline format
+ join(__dirname, '../packages/router'),
+ // join(__dirname, '../packages/testing'),
+ // join(__dirname, '../packages/nuxt'),
+]
+
+// files to add and commit after building a new version
+const FILES_TO_COMMIT = [
+ // comment for multiline format
+ 'packages/*/package.json',
+ 'packages/*/CHANGELOG.md',
+]
-const bin = name => resolve(__dirname, '../node_modules/.bin/' + name)
/**
- * @param bin {string}
- * @param args {string}
- * @param opts {import('execa').CommonOptions<string>}
- * @returns
+ * @type {typeof execa}
*/
const run = (bin, args, opts = {}) =>
execa(bin, args, { stdio: 'inherit', ...opts })
-const dryRun = (bin, args, opts = {}) =>
- console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts)
+/**
+ * @param bin {string}
+ * @param args {string[]}
+ * @param opts {import('execa').Options}
+ */
+const dryRun = async (bin, args, opts = {}) =>
+ console.log(chalk.blue(`[dry-run] ${bin} ${args.join(' ')}`), opts)
const runIfNotDry = isDryRun ? dryRun : run
-const getPkgRoot = pkg => resolve(__dirname, '../packages/' + pkg)
-const step = msg => console.log(chalk.cyan(msg))
+
+/**
+ * @param msg {string[]}
+ */
+const step = (...msg) => console.log(chalk.cyan(...msg))
async function main() {
if (!skipCleanGitCheck) {
}
}
- const changedPackages = await getChangedPackages()
+ const changedPackages = await getChangedPackages(...PKG_FOLDERS)
+
if (!changedPackages.length) {
console.log(chalk.red(`No packages have changed since last release`))
return
}
if (isDryRun) {
- console.log('\n' + chalk.bold.blue('This is a dry run') + '\n')
+ console.log(`\n${chalk.bold.blue('This is a dry run')}\n`)
}
- // NOTE: I'm unsure if this would mess up the changelog
- // const { pickedPackages } = await prompt({
- // type: 'multiselect',
- // name: 'pickedPackages',
- // messages: 'What packages do you want to release?',
- // choices: changedPackages.map((pkg) => pkg.name),
- // })
+ let packagesToRelease = changedPackages
+
+ // if there are more than one package, ask which ones to release
+ if (packagesToRelease.length > 1) {
+ // allow to select which packages
+ const { pickedPackages } = await prompts({
+ type: 'multiselect',
+ name: 'pickedPackages',
+ message: 'What packages do you want to release?',
+ instructions: false,
+ min: 1,
+ choices: changedPackages.map(pkg => ({
+ title: pkg.name,
+ value: pkg.name,
+ selected: true,
+ })),
+ })
- const packagesToRelease = changedPackages
- // const packagesToRelease = changedPackages.filter((pkg) =>
- // pickedPackages.includes(pkg.name)
- // )
+ // const packagesToRelease = changedPackages
+ packagesToRelease = changedPackages.filter(pkg =>
+ pickedPackages.includes(pkg.name)
+ )
+ }
step(
- `Ready to release ${packagesToRelease
- .map(({ name }) => chalk.bold.white(name))
- .join(', ')}`
+ `Ready to release ${packagesToRelease.map(({ name }) => chalk.bold.white(name)).join(', ')}`
)
const pkgWithVersions = await pSeries(
- packagesToRelease.map(({ name, path, pkg }) => async () => {
+ packagesToRelease.map(({ name, path, pkg, relativePath }) => async () => {
let { version } = pkg
const prerelease = semver.prerelease(version)
...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : []),
]
- const { release } = await prompt({
+ const betaVersion = semver.inc(version, 'prerelease', 'beta')
+
+ const { release } = await prompts({
type: 'select',
name: 'release',
message: `Select release type for ${chalk.bold.white(name)}`,
choices: versionIncrements
- .map(i => `${i}: ${name} (${semver.inc(version, i, preId)})`)
+ .map(release => {
+ const newVersion = semver.inc(version, release, preId)
+ return {
+ value: newVersion,
+ title: `${release}: ${name} (${newVersion})`,
+ }
+ })
.concat(
- optionTag === 'edge'
+ optionTag === 'beta'
? [
- `edge: ${name} (${semver.inc(
- version,
- 'prerelease',
- 'alpha'
- )})`,
+ {
+ title: `beta: ${name} (${betaVersion})`,
+ value: betaVersion,
+ },
]
: []
)
- .concat(['custom']),
+ .concat([{ value: 'custom', title: 'custom' }]),
})
+ console.log(release)
+
if (release === 'custom') {
version = (
- await prompt({
- type: 'input',
+ await prompts({
+ type: 'text',
name: 'version',
message: `Input custom version (${chalk.bold.white(name)})`,
initial: version,
})
).version
} else {
- version = release.match(/\((.*)\)/)[1]
+ version = release
}
if (!semver.valid(version)) {
throw new Error(`invalid target version: ${version}`)
}
- return { name, path, version, pkg }
+ return { name, path, relativePath, version, pkg }
})
)
- const { yes: isReleaseConfirmed } = await prompt({
+ // put the main package first as others might depend on it
+ const mainPkgIndex = packagesToRelease.find(
+ ({ name }) => name === MAIN_PKG_NAME
+ )
+ if (mainPkgIndex > 0) {
+ packagesToRelease.unshift(packagesToRelease.splice(mainPkgIndex, 1)[0])
+ }
+
+ const { yes: isReleaseConfirmed } = await prompts({
type: 'confirm',
name: 'yes',
message: `Releasing \n${pkgWithVersions
.map(
({ name, version }) =>
- ` · ${chalk.white(name)}: ${chalk.yellow.bold('v' + version)}`
+ ` · ${chalk.white(name)}: ${chalk.yellow.bold(`v${version}`)}`
)
.join('\n')}\nConfirm?`,
})
step('\nUpdating versions in package.json files...')
await updateVersions(pkgWithVersions)
- step('\nCopying README for router package...')
- if (!isDryRun) {
- await fs.copyFile(
- resolve(__dirname, '../README.md'),
- resolve(__dirname, '../packages/router/README.md')
- )
- } else {
- console.log(`(skipped)`)
+ if (!noLockUpdate) {
+ step('\nUpdating lock...')
+ await runIfNotDry(`pnpm`, ['install'])
}
- step('\nUpdating lock...')
- await runIfNotDry(`pnpm`, ['install'])
-
step('\nGenerating changelogs...')
- for (const pkg of pkgWithVersions) {
- step(` -> ${pkg.name} (${pkg.path})`)
- await runIfNotDry(`pnpm`, ['run', 'changelog'], { cwd: pkg.path })
- await runIfNotDry(`pnpm`, ['exec', 'prettier', '--write', 'CHANGELOG.md'], {
- cwd: pkg.path,
+ await Promise.all(
+ pkgWithVersions.map(async pkg => {
+ step(` -> ${pkg.name} (${pkg.path})`)
+ const changelogExists = existsSync(join(pkg.path, 'CHANGELOG.md'))
+
+ if (!changelogExists) {
+ console.log(chalk.yellow(`No CHANGELOG.md found in ${pkg.name}`))
+ }
+
+ await runIfNotDry(
+ `pnpm`,
+ [
+ 'exec',
+ 'conventional-changelog',
+ '-i',
+ 'CHANGELOG.md',
+ '--same-file',
+ '-p',
+ 'conventionalcommits',
+ '-r',
+ changelogExists ? '1' : '0',
+ '--commit-path',
+ // in the case of a mono repo with the main package at the root
+ // using `.` would add all the changes of all packages
+ ...(pkg.name === MAIN_PKG_NAME && IS_MAIN_PKG_ROOT
+ ? [join(pkg.path, 'src'), join(pkg.path, 'package.json')]
+ : ['.']),
+ ...(pkg.name === MAIN_PKG_NAME && IS_MAIN_PKG_ROOT
+ ? []
+ : ['--lerna-package', pkg.name]),
+ ...(pkg.name === MAIN_PKG_NAME
+ ? []
+ : ['--tag-prefix', `${pkg.name}@`]),
+ ],
+ { cwd: pkg.path }
+ )
+ await runIfNotDry(
+ `pnpm`,
+ ['exec', 'prettier', '--write', 'CHANGELOG.md'],
+ {
+ cwd: pkg.path,
+ }
+ )
+ // NOTE: pnpm publish automatically copies the LICENSE file
})
- await fs.copyFile(
- resolve(__dirname, '../LICENSE'),
- resolve(pkg.path, 'LICENSE')
- )
- }
+ )
- const { yes: isChangelogCorrect } = await prompt({
+ const { yes: isChangelogCorrect } = await prompts({
type: 'confirm',
name: 'yes',
message: 'Are the changelogs correct?',
+ initial: true,
})
if (!isChangelogCorrect) {
}
step('\nBuilding all packages...')
- if (!skipBuild && !isDryRun) {
- await run('pnpm', ['run', 'build'])
+ if (!skipBuild) {
+ await runIfNotDry('pnpm', ['run', 'build'])
+ await runIfNotDry('pnpm', ['run', 'build:dts'])
} else {
console.log(`(skipped)`)
}
const { stdout } = await run('git', ['diff'], { stdio: 'pipe' })
if (stdout) {
step('\nCommitting changes...')
- await runIfNotDry('git', [
- 'add',
- 'packages/*/CHANGELOG.md',
- 'packages/*/package.json',
- 'pnpm-lock.yaml',
- ])
+ await runIfNotDry('git', ['add', ...FILES_TO_COMMIT])
await runIfNotDry('git', [
'commit',
'-m',
- `release: ${pkgWithVersions
- .map(({ name, version }) => `${name}@${version}`)
- .join(' ')}`,
+ `release: ${pkgWithVersions.map(({ name, version }) => `${name}@${version}`).join(' ')}`,
])
} else {
console.log('No changes to commit.')
}
step('\nCreating tags...')
- let versionsToPush = []
+ const versionsToPush = []
for (const pkg of pkgWithVersions) {
const tagName =
- pkg.name === 'vue-router'
+ pkg.name === MAIN_PKG_NAME
? `v${pkg.version}`
: `${pkg.name}@${pkg.version}`
+
versionsToPush.push(`refs/tags/${tagName}`)
await runIfNotDry('git', ['tag', `${tagName}`])
}
/**
*
- * @param packageList {{ name: string; path: string; version: string, pkg: any }}
+ * @param packageList {{ name: string; path: string; version: string, pkg: any }[]}
*/
async function updateVersions(packageList) {
return Promise.all(
updateDeps(pkg, 'dependencies', packageList)
updateDeps(pkg, 'peerDependencies', packageList)
}
- const content = JSON.stringify(pkg, null, 2) + '\n'
+ const content = `${JSON.stringify(pkg, null, 2)}\n`
return isDryRun
? dryRun('write', [name], {
version: pkg.version,
const updatedDep = updatedPackages.find(pkg => pkg.name === dep)
// avoid updated peer deps that are external like @vue/devtools-api
if (dep && updatedDep) {
- console.log(
- chalk.yellow(
- `${pkg.name} -> ${depType} -> ${dep}@~${updatedDep.version}`
+ // skip any workspace reference, pnpm will handle it
+ if (deps[dep].startsWith('workspace:')) {
+ console.log(
+ chalk.yellow.dim(
+ `${pkg.name} -> ${depType} -> ${dep}@${deps[dep]} (skipped)`
+ )
)
- )
- deps[dep] = '>=' + updatedDep.version
+ } else {
+ console.log(
+ chalk.yellow(
+ `${pkg.name} -> ${depType} -> ${dep}@>=${updatedDep.version}`
+ )
+ )
+ deps[dep] = `>=${updatedDep.version}`
+ }
}
})
}
...(skipCleanGitCheck ? ['--no-git-checks'] : []),
'--access',
'public',
+ // only needed for branches other than main
'--publish-branch',
EXPECTED_BRANCH,
],
}
/**
- * Get the packages that have changed. Based on `lerna changed` but without lerna.
+ * Get the last tag published for a package or null if there are no tags
*
- * @returns {Promise<{ name: string; path: string; pkg: any; version: string }[]}
+ * @param {string} pkgName - package name
*/
-async function getChangedPackages() {
- let lastTag
-
+async function getLastTag(pkgName) {
try {
- const { stdout } = await run('git', ['describe', '--tags', '--abbrev=0'], {
- stdio: 'pipe',
- })
- lastTag = stdout
+ const { stdout } = await run(
+ 'git',
+ [
+ 'describe',
+ '--tags',
+ '--abbrev=0',
+ '--match',
+ pkgName === MAIN_PKG_NAME ? 'v*' : `${pkgName}@*`,
+ ],
+ {
+ stdio: 'pipe',
+ }
+ )
+
+ return stdout
} catch (error) {
- // maybe there are no tags
- console.error(`Couldn't get the last tag, using first commit...`)
+ console.log(
+ chalk.dim(
+ `Couldn't get "${chalk.bold(pkgName)}" last tag, using first commit...`
+ )
+ )
+
+ // 128 is the git exit code when there is nothing to describe
+ if (error.exitCode !== 128) {
+ console.error(error)
+ }
const { stdout } = await run(
'git',
['rev-list', '--max-parents=0', 'HEAD'],
{ stdio: 'pipe' }
)
- lastTag = stdout
+ return stdout
}
- // globby expects `/` even on windows
- const folders = await globby(
- join(__dirname, '../packages/*').replace(/\\/g, '/'),
- {
- onlyFiles: false,
- }
- )
+}
+/**
+ * Get the packages that have changed. Based on `lerna changed` but without lerna.
+ *
+ * @param {string[]} folders
+ * @returns {Promise<{ name: string; path: string; relativePath: string; pkg: any; version: string; start: string }[]} a promise of changed packages
+ */
+async function getChangedPackages(...folders) {
const pkgs = await Promise.all(
folders.map(async folder => {
- if (!(await fs.lstat(folder)).isDirectory()) return null
-
- const pkg = JSON.parse(await fs.readFile(join(folder, 'package.json')))
- if (!pkg.private) {
- const { stdout: hasChanges } = await run(
- 'git',
- [
- 'diff',
- lastTag,
- '--',
- // apparently {src,package.json} doesn't work
- join(folder, 'src'),
- join(folder, 'package.json'),
- ],
- { stdio: 'pipe' }
- )
+ if (!(await fs.lstat(folder)).isDirectory()) {
+ console.warn(chalk.dim(`Skipping "${folder}" as it is not a directory`))
+ return null
+ }
- if (hasChanges) {
- return {
- path: folder,
- name: pkg.name,
- version: pkg.version,
- pkg,
- }
- } else {
- return null
+ const pkg = JSON.parse(
+ await fs.readFile(join(folder, 'package.json'), 'utf-8')
+ )
+ if (pkg.private) {
+ console.info(chalk.dim(`Skipping "${pkg.name}" it's private`))
+ return null
+ }
+
+ const lastTag = await getLastTag(pkg.name)
+
+ const { stdout: hasChanges } = await run(
+ 'git',
+ [
+ 'diff',
+ '--name-only',
+ lastTag,
+ '--',
+ // apparently {src,package.json} doesn't work
+ join(folder, 'src'),
+ // TODO: should not check dev deps and should compare to last tag changes
+ join(folder, 'package.json'),
+ ],
+ { stdio: 'pipe' }
+ )
+ const relativePath = relative(join(__dirname, '..'), folder)
+
+ if (hasChanges || skipChangeCheck) {
+ const changedFiles = hasChanges.split('\n').filter(Boolean)
+ console.log(
+ chalk.dim.blueBright(
+ `Found ${changedFiles.length} changed files in "${pkg.name}" since last release (${lastTag})`
+ )
+ )
+ console.log(chalk.dim(`"${changedFiles.join('", "')}"`))
+
+ return {
+ path: folder,
+ relativePath,
+ name: pkg.name,
+ version: pkg.version,
+ pkg,
+ start: lastTag,
}
+ } else {
+ console.warn(
+ chalk.dim(
+ `Skipping "${pkg.name}" as it has no changes since last release (${lastTag})`
+ )
+ )
+ return null
}
})
)