diff --git a/knip.json b/knip.json index 02ce57e1c..1a5df6221 100644 --- a/knip.json +++ b/knip.json @@ -1,6 +1,7 @@ { "$schema": "https://unpkg.com/knip@latest/schema.json", "entry": ["script/*e2e.js", "src/index.ts!", "src/**/*.test.*"], + "ignoreDependencies": ["all-contributors-cli"], "ignoreExportsUsedInFile": { "interface": true, "type": true }, "project": ["src/**/*.ts!", "script/**/*.js"] } diff --git a/package.json b/package.json index bfbdf5edb..245f82164 100644 --- a/package.json +++ b/package.json @@ -43,11 +43,9 @@ "dependencies": { "@clack/prompts": "^0.8.2", "@prettier/sync": "^0.5.2", - "all-contributors-for-repository": "^0.3.0", "chalk": "^5.3.0", - "create": "0.1.0-alpha.3", + "create": "0.1.0-alpha.4", "execa": "^9.5.1", - "get-github-auth-token": "^0.1.0", "git-remote-origin-url": "^4.0.0", "git-url-parse": "^16.0.0", "input-from-file": "0.1.0-alpha.0", @@ -56,14 +54,17 @@ "lazy-value": "^3.0.0", "npm-user": "^6.1.1", "octokit": "^4.0.2", + "octokit-from-auth": "^0.2.0", "parse-author": "^2.0.0", "parse-package-name": "^1.0.0", + "populate-all-contributors-for-repository": "^0.1.0", "prettier": "^3.4.1", "replace-in-file": "^8.2.0", "rimraf": "^6.0.1", + "set-github-repository-labels": "^0.1.0", "sort-package-json": "^2.12.0", "title-case": "^4.3.2", - "zod": "^3.23.8", + "zod": "^3.24.1", "zod-validation-error": "^3.4.0" }, "devDependencies": { @@ -78,9 +79,10 @@ "@types/parse-author": "2.0.3", "@vitest/coverage-v8": "2.1.8", "@vitest/eslint-plugin": "1.1.14", + "all-contributors-cli": "^6.26.1", "c8": "10.1.2", "console-fail-test": "0.5.0", - "create-testers": "0.1.0-alpha.3", + "create-testers": "0.1.0-alpha.4", "cspell": "8.16.1", "eslint": "9.16.0", "eslint-plugin-jsdoc": "50.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5461e35d6..0825e650a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,21 +14,15 @@ importers: '@prettier/sync': specifier: ^0.5.2 version: 0.5.2(prettier@3.4.1) - all-contributors-for-repository: - specifier: ^0.3.0 - version: 0.3.0 chalk: specifier: ^5.3.0 version: 5.3.0 create: - specifier: 0.1.0-alpha.3 - version: 0.1.0-alpha.3 + specifier: 0.1.0-alpha.4 + version: 0.1.0-alpha.4 execa: specifier: ^9.5.1 - version: 9.5.1 - get-github-auth-token: - specifier: ^0.1.0 - version: 0.1.0 + version: 9.5.2 git-remote-origin-url: specifier: ^4.0.0 version: 4.0.0 @@ -37,10 +31,10 @@ importers: version: 16.0.0 input-from-file: specifier: 0.1.0-alpha.0 - version: 0.1.0-alpha.0(create@0.1.0-alpha.3) + version: 0.1.0-alpha.0(create@0.1.0-alpha.4) input-from-file-json: specifier: 0.1.0-alpha.1 - version: 0.1.0-alpha.1(create@0.1.0-alpha.3) + version: 0.1.0-alpha.1(create@0.1.0-alpha.4) js-yaml: specifier: ^4.1.0 version: 4.1.0 @@ -53,12 +47,18 @@ importers: octokit: specifier: ^4.0.2 version: 4.0.2 + octokit-from-auth: + specifier: ^0.2.0 + version: 0.2.0 parse-author: specifier: ^2.0.0 version: 2.0.0 parse-package-name: specifier: ^1.0.0 version: 1.0.0 + populate-all-contributors-for-repository: + specifier: ^0.1.0 + version: 0.1.2 prettier: specifier: ^3.4.1 version: 3.4.1 @@ -68,6 +68,9 @@ importers: rimraf: specifier: ^6.0.1 version: 6.0.1 + set-github-repository-labels: + specifier: ^0.1.0 + version: 0.1.0 sort-package-json: specifier: ^2.12.0 version: 2.12.0 @@ -75,11 +78,11 @@ importers: specifier: ^4.3.2 version: 4.3.2 zod: - specifier: ^3.23.8 - version: 3.23.8 + specifier: ^3.24.1 + version: 3.24.1 zod-validation-error: specifier: ^3.4.0 - version: 3.4.0(zod@3.23.8) + version: 3.4.0(zod@3.24.1) devDependencies: '@eslint-community/eslint-plugin-eslint-comments': specifier: 4.4.1 @@ -114,6 +117,9 @@ importers: '@vitest/eslint-plugin': specifier: 1.1.14 version: 1.1.14(@typescript-eslint/utils@8.18.0(eslint@9.16.0(jiti@2.4.0))(typescript@5.7.2))(eslint@9.16.0(jiti@2.4.0))(typescript@5.7.2)(vitest@2.1.8(@types/node@22.10.1)) + all-contributors-cli: + specifier: ^6.26.1 + version: 6.26.1 c8: specifier: 10.1.2 version: 10.1.2 @@ -121,8 +127,8 @@ importers: specifier: 0.5.0 version: 0.5.0 create-testers: - specifier: 0.1.0-alpha.3 - version: 0.1.0-alpha.3(create@0.1.0-alpha.3) + specifier: 0.1.0-alpha.4 + version: 0.1.0-alpha.4(create@0.1.0-alpha.4) cspell: specifier: 8.16.1 version: 8.16.1 @@ -240,6 +246,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime@7.26.0': + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.25.7': resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} engines: {node: '>=6.9.0'} @@ -1477,8 +1487,13 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - all-contributors-for-repository@0.3.0: - resolution: {integrity: sha512-McUwhFuxTOLMzX5oQeZLd+kQB8ZumhkF482qbZQ7dSPkAxfUyW5xG6Qzzpcz/vKFbQjF4/nIvaOOBNBWMmL6HA==} + all-contributors-cli@6.26.1: + resolution: {integrity: sha512-Ymgo3FJACRBEd1eE653FD1J/+uD0kqpUNYfr9zNC1Qby0LgbhDBzB3EF6uvkAbYpycStkk41J+0oo37Lc02yEw==} + engines: {node: '>=4'} + hasBin: true + + all-contributors-for-repository@0.4.0: + resolution: {integrity: sha512-qGJHdVaRnoKMEZ6IcDvrFQJIDA9KPSsCVAMk+mjqVkHMYrgvp05TU94I8x4SjwWIfYBLp9heC9Onh55BIrOA4A==} engines: {node: '>=18'} ansi-align@3.0.1: @@ -1542,6 +1557,9 @@ packages: async-retry@1.3.3: resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + atomically@2.0.3: resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} @@ -1626,6 +1644,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} @@ -1713,10 +1735,17 @@ packages: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1868,14 +1897,14 @@ packages: typescript: optional: true - create-testers@0.1.0-alpha.3: - resolution: {integrity: sha512-2PBTCn+9CcWT6hoqYRyh1aFOGk485dxOiGWE0vfNsdKYbYRdaGnOg3Gbhc354PQX9MyzojpP4rOM7ytFkUr3Ag==} + create-testers@0.1.0-alpha.4: + resolution: {integrity: sha512-ortGiKsmlzb1Mqt4PWwP5rEw3Wt/j18OCbbsc6t0qHB596Bu3Ckx9/GELKa4w02KthOsI1CcZmRNS/OoZHLIqQ==} engines: {node: '>=18'} peerDependencies: - create: 0.1.0-alpha.3 + create: 0.1.0-alpha.4 - create@0.1.0-alpha.3: - resolution: {integrity: sha512-wYj56M08XZXuQm3r3QTX/bZVQYq31QoiyvbXcVq+i/xy5AJRHVfDMESSaoT2Y3AINtJRlCCiOJ92HULcFE9bqA==} + create@0.1.0-alpha.4: + resolution: {integrity: sha512-h8p8ZFD+lObrfQx3HFYyy//3m3n5MwEEnTuGa3xA1RkaP8QGdaFanwlEuBnrd87zH4aIyyjE+koQWdk7CJ3YsQ==} engines: {node: '>=18'} hasBin: true @@ -1942,6 +1971,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -1995,6 +2028,9 @@ packages: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -2247,8 +2283,8 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - execa@9.5.1: - resolution: {integrity: sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==} + execa@9.5.2: + resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} engines: {node: ^18.19.0 || >=20.5.0} expect-type@1.1.0: @@ -2287,6 +2323,10 @@ packages: picomatch: optional: true + figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -2307,6 +2347,10 @@ packages: resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} engines: {node: '>=18'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -2582,6 +2626,10 @@ packages: peerDependencies: create: 0.1.0-alpha.0 + inquirer@7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + inquirer@9.3.2: resolution: {integrity: sha512-+ynEbhWKhyomnaX0n2aLIMSkgSlGB5RrWbNXnEqj6mdaIydu6y40MdBjL38SAB0JcdmOaIaMua1azdjLEr3sdw==} engines: {node: '>=18'} @@ -2770,6 +2818,10 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-fixer@1.6.15: + resolution: {integrity: sha512-TuDuZ5KrgyjoCIppdPXBMqiGfota55+odM+j2cQ5rt/XKyKmqGB3Whz1F8SN8+60yYGy/Nu5lbRZ+rx8kBIvBw==} + engines: {node: '>=10'} + json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -2846,6 +2898,10 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -3013,6 +3069,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + mute-stream@1.0.0: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3046,6 +3105,15 @@ packages: resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + normalize-package-data@6.0.0: resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3077,6 +3145,14 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + octokit-from-auth@0.2.0: + resolution: {integrity: sha512-UMo+WQkWi1PS/HZ15SMM1sgPhhXykqPJKCCAi6R0+JAhTbLBcfeKCJ3AwUVdJBJQKSQ37BUqPpME4iGAjZQtkw==} + engines: {node: '>=18.3.0'} + + octokit-from-auth@0.3.0: + resolution: {integrity: sha512-HeS+YVPExV5nkdRZyQQRepZVV+pL4ahVmh9KfKXLAbNc3D82G2xeuSWfKzHSIlqB1taQnZYPJWdpfcIe45d1lw==} + engines: {node: '>=18.3.0'} + octokit@4.0.2: resolution: {integrity: sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg==} engines: {node: '>= 18'} @@ -3120,10 +3196,18 @@ packages: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -3132,6 +3216,10 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + pac-proxy-agent@7.0.1: resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} engines: {node: '>= 14'} @@ -3239,6 +3327,11 @@ packages: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} + pegjs@0.10.0: + resolution: {integrity: sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==} + engines: {node: '>=0.10'} + hasBin: true + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -3255,10 +3348,19 @@ packages: engines: {node: '>=0.10'} hasBin: true + pify@5.0.0: + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + populate-all-contributors-for-repository@0.1.2: + resolution: {integrity: sha512-PQ93fI7OpetHtW0c+iu6Dx2aaiRurj07LTu51pAw/qkky0eb1CdcZ+4Y+DYbzZXId4UhHGH/ednm46Pwf1P8FA==} + engines: {node: '>=18.3.0'} + hasBin: true + postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} @@ -3305,6 +3407,11 @@ packages: peerDependencies: prettier: ^3.0.3 + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + prettier@3.4.1: resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==} engines: {node: '>=14'} @@ -3370,6 +3477,9 @@ packages: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -3400,6 +3510,9 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -3448,6 +3561,10 @@ packages: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} + run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} @@ -3459,6 +3576,10 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -3480,6 +3601,14 @@ packages: sentences-per-line@0.2.1: resolution: {integrity: sha512-6hlyKBwqoaZJ5+RBTKNNem2kBGAboh9e9KfFw5KYKA+64xaTYWbv5C6XnOudx8xk1Sg6f/4yalhJtCZFSLWIsQ==} + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-github-repository-labels@0.1.0: + resolution: {integrity: sha512-hnTqVqoJq9lFcBOSH6K9NK09RZvSTFSgtbwFjJdqz4qUV4T/7Krzztl71wPYt+IETWlOS+Vn3LlIsStW0Fc60Q==} + engines: {node: '>=18.3.0'} + hasBin: true + sh-syntax@0.4.2: resolution: {integrity: sha512-/l2UZ5fhGZLVZa16XQM9/Vq/hezGGbdHeVEA01uWjOL1+7Ek/gt6FquW0iKKws4a9AYPYvlz6RyVvjh3JxOteg==} engines: {node: '>=16.0.0'} @@ -3688,6 +3817,12 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + throttled-queue@2.1.4: + resolution: {integrity: sha512-YGdk8sdmr4ge3g+doFj/7RLF5kLM+Mi7DEciu9PHxnMJZMeVuZeTj31g4VE7ekUffx/IdbvrtOCiz62afg0mkg==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -3725,6 +3860,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -3741,6 +3879,9 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -3929,15 +4070,24 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} when-exit@2.1.3: resolution: {integrity: sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3985,6 +4135,9 @@ packages: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -4003,10 +4156,18 @@ packages: engines: {node: '>= 14'} hasBin: true + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -4029,8 +4190,8 @@ packages: peerDependencies: zod: ^3.18.0 - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} snapshots: @@ -4070,6 +4231,10 @@ snapshots: dependencies: '@babel/types': 7.25.8 + '@babel/runtime@7.26.0': + dependencies: + regenerator-runtime: 0.14.1 + '@babel/template@7.25.7': dependencies: '@babel/code-frame': 7.25.7 @@ -5159,12 +5324,30 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - all-contributors-for-repository@0.3.0: + all-contributors-cli@6.26.1: + dependencies: + '@babel/runtime': 7.26.0 + async: 3.2.6 + chalk: 4.1.2 + didyoumean: 1.2.2 + inquirer: 7.3.3 + json-fixer: 1.6.15 + lodash: 4.17.21 + node-fetch: 2.7.0 + pify: 5.0.0 + yargs: 15.4.1 + optionalDependencies: + prettier: 2.8.8 + transitivePeerDependencies: + - encoding + + all-contributors-for-repository@0.4.0: dependencies: co-author-to-username: 0.1.1 conventional-commits-parser: 6.0.0 description-to-co-authors: 0.3.0 octokit: 4.0.2 + octokit-from-auth: 0.3.0 ansi-align@3.0.1: dependencies: @@ -5216,6 +5399,8 @@ snapshots: dependencies: retry: 0.13.1 + async@3.2.6: {} + atomically@2.0.3: dependencies: stubborn-fs: 1.2.5 @@ -5303,6 +5488,8 @@ snapshots: callsites@3.1.0: {} + camelcase@5.3.1: {} + camelcase@8.0.0: {} chai@5.1.2: @@ -5393,8 +5580,16 @@ snapshots: slice-ansi: 5.0.0 string-width: 7.2.0 + cli-width@3.0.0: {} + cli-width@4.1.0: {} + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -5558,16 +5753,15 @@ snapshots: optionalDependencies: typescript: 5.7.2 - create-testers@0.1.0-alpha.3(create@0.1.0-alpha.3): + create-testers@0.1.0-alpha.4(create@0.1.0-alpha.4): dependencies: - create: 0.1.0-alpha.3 + create: 0.1.0-alpha.4 - create@0.1.0-alpha.3: + create@0.1.0-alpha.4: dependencies: - execa: 9.5.1 - get-github-auth-token: 0.1.0 - octokit: 4.0.2 - zod: 3.23.8 + execa: 9.5.2 + octokit-from-auth: 0.2.0 + zod: 3.24.1 cross-spawn@7.0.6: dependencies: @@ -5680,6 +5874,8 @@ snapshots: dependencies: ms: 2.1.3 + decamelize@1.2.0: {} + deep-eql@5.0.2: {} deep-extend@0.6.0: {} @@ -5717,6 +5913,8 @@ snapshots: detect-newline@4.0.1: {} + didyoumean@1.2.2: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -6112,7 +6310,7 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - execa@9.5.1: + execa@9.5.2: dependencies: '@sindresorhus/merge-streams': 4.0.0 cross-spawn: 7.0.6 @@ -6159,6 +6357,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -6177,6 +6379,11 @@ snapshots: find-up-simple@1.0.0: {} + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -6438,16 +6645,32 @@ snapshots: ini@4.1.1: {} - input-from-file-json@0.1.0-alpha.1(create@0.1.0-alpha.3): + input-from-file-json@0.1.0-alpha.1(create@0.1.0-alpha.4): + dependencies: + create: 0.1.0-alpha.4 + input-from-file: 0.1.0-alpha.0(create@0.1.0-alpha.4) + zod: 3.24.1 + + input-from-file@0.1.0-alpha.0(create@0.1.0-alpha.4): dependencies: - create: 0.1.0-alpha.3 - input-from-file: 0.1.0-alpha.0(create@0.1.0-alpha.3) - zod: 3.23.8 + create: 0.1.0-alpha.4 + zod: 3.24.1 - input-from-file@0.1.0-alpha.0(create@0.1.0-alpha.3): + inquirer@7.3.3: dependencies: - create: 0.1.0-alpha.3 - zod: 3.23.8 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 inquirer@9.3.2: dependencies: @@ -6610,6 +6833,12 @@ snapshots: json-buffer@3.0.1: {} + json-fixer@1.6.15: + dependencies: + '@babel/runtime': 7.26.0 + chalk: 4.1.2 + pegjs: 0.10.0 + json-parse-even-better-errors@2.3.1: {} json-schema-traverse@0.4.1: {} @@ -6655,8 +6884,8 @@ snapshots: strip-json-comments: 5.0.1 summary: 2.1.0 typescript: 5.7.2 - zod: 3.23.8 - zod-validation-error: 3.4.0(zod@3.23.8) + zod: 3.24.1 + zod-validation-error: 3.4.0(zod@3.24.1) ky@1.2.2: {} @@ -6709,6 +6938,10 @@ snapshots: load-tsconfig@0.2.5: {} + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -6878,6 +7111,8 @@ snapshots: ms@2.1.3: {} + mute-stream@0.0.8: {} + mute-stream@1.0.0: {} mvdan-sh@0.10.1: {} @@ -6902,6 +7137,10 @@ snapshots: dependencies: type-fest: 2.19.0 + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + normalize-package-data@6.0.0: dependencies: hosted-git-info: 7.0.1 @@ -6938,6 +7177,16 @@ snapshots: object-assign@4.1.1: {} + octokit-from-auth@0.2.0: + dependencies: + get-github-auth-token: 0.1.0 + octokit: 4.0.2 + + octokit-from-auth@0.3.0: + dependencies: + get-github-auth-token: 0.1.0 + octokit: 4.0.2 + octokit@4.0.2: dependencies: '@octokit/app': 15.0.1 @@ -7014,10 +7263,18 @@ snapshots: os-tmpdir@1.0.2: {} + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 @@ -7026,6 +7283,8 @@ snapshots: dependencies: aggregate-error: 3.1.0 + p-try@2.2.0: {} + pac-proxy-agent@7.0.1: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 @@ -7148,6 +7407,8 @@ snapshots: pathval@2.0.0: {} + pegjs@0.10.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -7156,8 +7417,18 @@ snapshots: pidtree@0.6.0: {} + pify@5.0.0: {} + pirates@4.0.6: {} + populate-all-contributors-for-repository@0.1.2: + dependencies: + all-contributors-cli: 6.26.1 + all-contributors-for-repository: 0.4.0 + execa: 9.5.2 + transitivePeerDependencies: + - encoding + postcss-load-config@6.0.1(jiti@2.4.0)(postcss@8.4.36)(tsx@4.19.2)(yaml@2.6.1): dependencies: lilconfig: 3.1.2 @@ -7197,6 +7468,9 @@ snapshots: prettier: 3.4.1 sh-syntax: 0.4.2 + prettier@2.8.8: + optional: true + prettier@3.4.1: {} pretty-ms@9.1.0: @@ -7269,6 +7543,8 @@ snapshots: dependencies: '@eslint-community/regexpp': 4.12.1 + regenerator-runtime@0.14.1: {} + regexp-ast-analysis@0.7.1: dependencies: '@eslint-community/regexpp': 4.12.1 @@ -7322,6 +7598,8 @@ snapshots: require-directory@2.1.1: {} + require-main-filename@2.0.0: {} + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -7381,6 +7659,8 @@ snapshots: run-applescript@7.0.0: {} + run-async@2.4.1: {} + run-async@3.0.0: {} run-con@1.3.2: @@ -7394,6 +7674,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@6.6.7: + dependencies: + tslib: 1.14.1 + rxjs@7.8.1: dependencies: tslib: 2.6.2 @@ -7414,6 +7698,14 @@ snapshots: dependencies: markdownlint: 0.11.0 + set-blocking@2.0.0: {} + + set-github-repository-labels@0.1.0: + dependencies: + octokit-from-auth: 0.2.0 + throttled-queue: 2.1.4 + zod: 3.24.1 + sh-syntax@0.4.2: dependencies: tslib: 2.6.2 @@ -7612,6 +7904,10 @@ snapshots: dependencies: any-promise: 1.3.0 + throttled-queue@2.1.4: {} + + through@2.3.8: {} + tinybench@2.9.0: {} tinyexec@0.3.1: {} @@ -7639,6 +7935,8 @@ snapshots: dependencies: is-number: 7.0.0 + tr46@0.0.3: {} + tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -7651,6 +7949,8 @@ snapshots: ts-interface-checker@0.1.13: {} + tslib@1.14.1: {} + tslib@2.6.2: {} tsup@8.3.5(jiti@2.4.0)(postcss@8.4.36)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.6.1): @@ -7838,8 +8138,15 @@ snapshots: dependencies: defaults: 1.0.4 + webidl-conversions@3.0.1: {} + webidl-conversions@4.0.2: {} + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0 @@ -7848,6 +8155,8 @@ snapshots: when-exit@2.1.3: {} + which-module@2.0.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -7897,6 +8206,8 @@ snapshots: xdg-basedir@5.1.0: {} + y18n@4.0.3: {} + y18n@5.0.8: {} yaml-eslint-parser@1.2.2: @@ -7909,8 +8220,27 @@ snapshots: yaml@2.6.1: {} + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + yargs-parser@21.1.1: {} + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -7927,8 +8257,8 @@ snapshots: yoctocolors@2.1.1: {} - zod-validation-error@3.4.0(zod@3.23.8): + zod-validation-error@3.4.0(zod@3.24.1): dependencies: - zod: 3.23.8 + zod: 3.24.1 - zod@3.23.8: {} + zod@3.24.1: {} diff --git a/script/__snapshots__/migrate-test-e2e.ts.snap b/script/__snapshots__/migrate-test-e2e.ts.snap index b99c27782..b67b86519 100644 --- a/script/__snapshots__/migrate-test-e2e.ts.snap +++ b/script/__snapshots__/migrate-test-e2e.ts.snap @@ -214,6 +214,7 @@ exports[`expected file changes > knip.json 1`] = ` { "$schema": "https://unpkg.com/knip@latest/schema.json", - "entry": ["script/*e2e.js", "src/index.ts!", "src/**/*.test.*"], +- "ignoreDependencies": ["all-contributors-cli"], + "entry": ["src/index.ts!"], "ignoreExportsUsedInFile": { "interface": true, "type": true }, - "project": ["src/**/*.ts!", "script/**/*.js"] diff --git a/src/create/createWithOptions.test.ts b/src/create/createWithOptions.test.ts index d7895f484..5799549ee 100644 --- a/src/create/createWithOptions.test.ts +++ b/src/create/createWithOptions.test.ts @@ -35,10 +35,6 @@ vi.mock("execa", () => ({ })); const mockOctokit = new Octokit(); -const github = { - auth: "auth-token", - octokit: mockOctokit, -}; vi.mock("../shared/cli/spinners.js", () => ({ withSpinner: async (label: string, task: SpinnerTask) => { @@ -89,11 +85,8 @@ describe("createWithOptions", () => { skipAllContributorsApi: false, }; - await createWithOptions({ github, options }); - expect(addToolAllContributors).toHaveBeenCalledWith( - github.octokit, - options, - ); + await createWithOptions({ octokit: mockOctokit, options }); + expect(addToolAllContributors).toHaveBeenCalledWith(mockOctokit, options); }); it("does not call addToolAllContributors when excludeAllContributors is true", async () => { @@ -102,7 +95,7 @@ describe("createWithOptions", () => { excludeAllContributors: true, }; - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(addToolAllContributors).not.toHaveBeenCalled(); }); @@ -112,7 +105,7 @@ describe("createWithOptions", () => { skipAllContributorsApi: true, }; - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(addToolAllContributors).not.toHaveBeenCalled(); }); @@ -122,7 +115,7 @@ describe("createWithOptions", () => { skipInstall: true, }; - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(finalizeDependencies).not.toHaveBeenCalled(); expect(runCleanup).not.toHaveBeenCalled(); }); @@ -133,7 +126,7 @@ describe("createWithOptions", () => { skipInstall: false, }; - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(finalizeDependencies).toHaveBeenCalledWith(options); expect(runCleanup).toHaveBeenCalled(); @@ -142,7 +135,7 @@ describe("createWithOptions", () => { it("does not initialize GitHub repository if repository does not exist", async () => { const options = optionsBase; vi.mocked(doesRepositoryExist).mockResolvedValueOnce(false); - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(initializeGitHubRepository).not.toHaveBeenCalled(); expect(mock$).not.toHaveBeenCalled(); }); @@ -151,7 +144,7 @@ describe("createWithOptions", () => { const options = optionsBase; vi.mocked(doesRepositoryExist).mockResolvedValueOnce(true); - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); expect(mock$.mock.calls).toMatchInlineSnapshot(` [ @@ -189,11 +182,11 @@ describe("createWithOptions", () => { const options = optionsBase; vi.mocked(doesRepositoryExist).mockResolvedValueOnce(true); - await createWithOptions({ github, options }); + await createWithOptions({ octokit: mockOctokit, options }); - expect(doesRepositoryExist).toHaveBeenCalledWith(github.octokit, options); + expect(doesRepositoryExist).toHaveBeenCalledWith(mockOctokit, options); expect(initializeGitHubRepository).toHaveBeenCalledWith( - github.octokit, + mockOctokit, options, ); }); diff --git a/src/create/createWithOptions.ts b/src/create/createWithOptions.ts index 9c8bc6cd3..f37a747d6 100644 --- a/src/create/createWithOptions.ts +++ b/src/create/createWithOptions.ts @@ -9,7 +9,7 @@ import { import { createCleanupCommands } from "../shared/createCleanupCommands.js"; import { doesRepositoryExist } from "../shared/doesRepositoryExist.js"; import { isUsingCreateEngine } from "../shared/isUsingCreateEngine.js"; -import { GitHubAndOptions } from "../shared/options/readOptions.js"; +import { OctokitAndOptions } from "../shared/options/readOptions.js"; import { addToolAllContributors } from "../steps/addToolAllContributors.js"; import { clearLocalGitTags } from "../steps/clearLocalGitTags.js"; import { finalizeDependencies } from "../steps/finalizeDependencies.js"; @@ -18,7 +18,10 @@ import { runCleanup } from "../steps/runCleanup.js"; import { writeReadme } from "../steps/writeReadme/index.js"; import { writeStructure } from "../steps/writing/writeStructure.js"; -export async function createWithOptions({ github, options }: GitHubAndOptions) { +export async function createWithOptions({ + octokit, + options, +}: OctokitAndOptions) { if (isUsingCreateEngine()) { await withSpinner("Creating repository", async () => { await runCreateEnginePreset(options); @@ -43,7 +46,7 @@ export async function createWithOptions({ github, options }: GitHubAndOptions) { if (!options.excludeAllContributors && !options.skipAllContributorsApi) { await withSpinner("Adding contributors to table", async () => { - await addToolAllContributors(github?.octokit, options); + await addToolAllContributors(octokit, options); }); } @@ -57,8 +60,7 @@ export async function createWithOptions({ github, options }: GitHubAndOptions) { await withSpinner("Clearing any local Git tags", clearLocalGitTags); - const sendToGitHub = - github && (await doesRepositoryExist(github.octokit, options)); + const sendToGitHub = octokit && (await doesRepositoryExist(octokit, options)); if (sendToGitHub) { await withSpinner("Initializing GitHub repository", async () => { @@ -66,7 +68,7 @@ export async function createWithOptions({ github, options }: GitHubAndOptions) { await $`git add -A`; await $`git commit --message ${"feat: initialized repo ✨"} --no-gpg-sign`; await $`git push -u origin main --force`; - await initializeGitHubRepository(github.octokit, options); + await initializeGitHubRepository(octokit, options); }); } diff --git a/src/initialize/initializeWithOptions.test.ts b/src/initialize/initializeWithOptions.test.ts index 38ff82821..3910a7c00 100644 --- a/src/initialize/initializeWithOptions.test.ts +++ b/src/initialize/initializeWithOptions.test.ts @@ -1,6 +1,6 @@ +import { Octokit } from "octokit"; import { describe, expect, it, vi } from "vitest"; -import { GitHub } from "../shared/options/getGitHub.js"; import { Options } from "../shared/types.js"; import { initializeWithOptions } from "./initializeWithOptions.js"; @@ -77,7 +77,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -94,7 +94,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -102,17 +102,15 @@ describe("initializeWithOptions", () => { }); it("runs initializeGitHubRepository when github is truthy", async () => { - const github = { - octokit: {}, - } as GitHub; + const octokit = {} as Octokit; await initializeWithOptions({ - github, + octokit, options: optionsBase, }); expect(mockInitializeGitHubRepository).toHaveBeenCalledWith( - github.octokit, + octokit, optionsBase, ); }); @@ -124,7 +122,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -138,7 +136,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -152,7 +150,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -167,7 +165,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -181,7 +179,7 @@ describe("initializeWithOptions", () => { }; await initializeWithOptions({ - github: undefined, + octokit: undefined, options, }); diff --git a/src/initialize/initializeWithOptions.ts b/src/initialize/initializeWithOptions.ts index b3665af93..f6e37cbf6 100644 --- a/src/initialize/initializeWithOptions.ts +++ b/src/initialize/initializeWithOptions.ts @@ -1,6 +1,6 @@ import { withSpinner, withSpinners } from "../shared/cli/spinners.js"; import { createCleanupCommands } from "../shared/createCleanupCommands.js"; -import { GitHubAndOptions } from "../shared/options/readOptions.js"; +import { OctokitAndOptions } from "../shared/options/readOptions.js"; import { addOwnerAsAllContributor } from "../steps/addOwnerAsAllContributor.js"; import { clearChangelog } from "../steps/clearChangelog.js"; import { initializeGitHubRepository } from "../steps/initializeGitHubRepository/index.js"; @@ -13,9 +13,9 @@ import { updateLocalFiles } from "../steps/updateLocalFiles.js"; import { updateReadme } from "../steps/updateReadme.js"; export async function initializeWithOptions({ - github, + octokit, options, -}: GitHubAndOptions) { +}: OctokitAndOptions) { await withSpinners("Initializing local files", [ [ "Updating local files", @@ -41,13 +41,13 @@ export async function initializeWithOptions({ if (!options.excludeAllContributors) { await withSpinner("Updating existing contributor details", async () => { - await addOwnerAsAllContributor(github?.octokit, options); + await addOwnerAsAllContributor(octokit, options); }); } - if (github) { + if (octokit) { await withSpinner("Initializing GitHub repository", async () => { - await initializeGitHubRepository(github.octokit, options); + await initializeGitHubRepository(octokit, options); }); } diff --git a/src/migrate/migrateWithOptions.test.ts b/src/migrate/migrateWithOptions.test.ts index 353186e59..5215b27a9 100644 --- a/src/migrate/migrateWithOptions.test.ts +++ b/src/migrate/migrateWithOptions.test.ts @@ -1,6 +1,6 @@ +import { Octokit } from "octokit"; import { describe, expect, it, vi } from "vitest"; -import { GitHub } from "../shared/options/getGitHub.js"; import { Options } from "../shared/types.js"; import { migrateWithOptions } from "./migrateWithOptions.js"; @@ -11,11 +11,11 @@ vi.mock("../shared/cli/spinners.js", () => ({ withSpinners: vi.fn(), })); -const mockDetectExistingContributors = vi.fn(); +const mockPopulateAllContributorsForRepository = vi.fn(); -vi.mock("../steps/detectExistingContributors.js", () => ({ - get detectExistingContributors() { - return mockDetectExistingContributors; +vi.mock("populate-all-contributors-for-repository", () => ({ + get populateAllContributorsForRepository() { + return mockPopulateAllContributorsForRepository; }, })); @@ -65,18 +65,16 @@ vi.mock("../shared/options/readOptions.js", () => ({ const optionsBase = {} as Options; describe("migrateWithOptions", () => { - it("runs initializeGitHubRepository when github is truthy", async () => { - const github = { - octokit: {}, - } as GitHub; + it("runs initializeGitHubRepository when octokit is truthy", async () => { + const octokit = {} as Octokit; await migrateWithOptions({ - github, + octokit, options: optionsBase, }); expect(mockInitializeGitHubRepository).toHaveBeenCalledWith( - github.octokit, + octokit, optionsBase, ); }); @@ -88,14 +86,14 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); expect(mockInitializeGitHubRepository).not.toHaveBeenCalled(); }); - it("does not run detectExistingContributors when excludeAllContributors is true", async () => { + it("does not run populateAllContributorsForRepository excludeAllContributors is true", async () => { const options = { ...optionsBase, excludeAllContributors: true, @@ -103,14 +101,14 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); - expect(mockDetectExistingContributors).not.toHaveBeenCalled(); + expect(mockPopulateAllContributorsForRepository).not.toHaveBeenCalled(); }); - it("does not run detectExistingContributors when skipAllContributorsApi is true", async () => { + it("does not run populateAllContributorsForRepository skipAllContributorsApi is true", async () => { const options = { ...optionsBase, excludeAllContributors: false, @@ -118,14 +116,14 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); - expect(mockDetectExistingContributors).not.toHaveBeenCalled(); + expect(mockPopulateAllContributorsForRepository).not.toHaveBeenCalled(); }); - it("runs detectExistingContributors when excludeAllContributors and skipAllContributorsApi are false", async () => { + it("runs populateAllContributorsForRepository excludeAllContributors and skipAllContributorsApi are false", async () => { const options = { ...optionsBase, excludeAllContributors: false, @@ -133,14 +131,14 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); - expect(mockDetectExistingContributors).toHaveBeenCalledWith( - undefined, - options, - ); + expect(mockPopulateAllContributorsForRepository).toHaveBeenCalledWith({ + owner: options.owner, + repo: options.repository, + }); }); it("runs finalizeDependencies when skipInstall is false", async () => { @@ -150,7 +148,7 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -164,7 +162,7 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -178,7 +176,7 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); @@ -192,7 +190,7 @@ describe("migrateWithOptions", () => { }; await migrateWithOptions({ - github: undefined, + octokit: undefined, options, }); diff --git a/src/migrate/migrateWithOptions.ts b/src/migrate/migrateWithOptions.ts index 0e6ce16e0..00ea83c6f 100644 --- a/src/migrate/migrateWithOptions.ts +++ b/src/migrate/migrateWithOptions.ts @@ -1,8 +1,9 @@ +import { populateAllContributorsForRepository } from "populate-all-contributors-for-repository"; + import { withSpinner, withSpinners } from "../shared/cli/spinners.js"; import { createCleanupCommands } from "../shared/createCleanupCommands.js"; -import { GitHubAndOptions } from "../shared/options/readOptions.js"; +import { OctokitAndOptions } from "../shared/options/readOptions.js"; import { clearUnnecessaryFiles } from "../steps/clearUnnecessaryFiles.js"; -import { detectExistingContributors } from "../steps/detectExistingContributors.js"; import { finalizeDependencies } from "../steps/finalizeDependencies.js"; import { initializeGitHubRepository } from "../steps/initializeGitHubRepository/index.js"; import { populateCSpellDictionary } from "../steps/populateCSpellDictionary.js"; @@ -13,9 +14,9 @@ import { writeReadme } from "../steps/writeReadme/index.js"; import { writeStructure } from "../steps/writing/writeStructure.js"; export async function migrateWithOptions({ - github, + octokit, options, -}: GitHubAndOptions) { +}: OctokitAndOptions) { await withSpinners("Migrating repository structure", [ ["Clearing unnecessary files", clearUnnecessaryFiles], [ @@ -44,15 +45,18 @@ export async function migrateWithOptions({ ], ]); - if (github) { + if (octokit) { await withSpinner("Initializing GitHub repository", async () => { - await initializeGitHubRepository(github.octokit, options); + await initializeGitHubRepository(octokit, options); }); } if (!options.excludeAllContributors && !options.skipAllContributorsApi) { await withSpinner("Detecting existing contributors", async () => - detectExistingContributors(github?.auth, options), + populateAllContributorsForRepository({ + owner: options.owner, + repo: options.repository, + }), ); } diff --git a/src/next/blocks/blockRepositoryLabels.ts b/src/next/blocks/blockRepositoryLabels.ts new file mode 100644 index 000000000..fdd6c185f --- /dev/null +++ b/src/next/blocks/blockRepositoryLabels.ts @@ -0,0 +1,15 @@ +import { outcomeLabels } from "../../steps/initializeGitHubRepository/outcomeLabels.js"; +import { base } from "../base.js"; + +export const blockRepositoryLabels = base.createBlock({ + about: { + name: "Repository Labels", + }, + produce({ options }) { + return { + scripts: [ + `npx set-github-repository-labels --outcomes ${JSON.stringify(outcomeLabels)} --owner "${options.owner}" --repository "${options.repository}"`, + ], + }; + }, +}); diff --git a/src/shared/options/ensureRepositoryExists.test.ts b/src/shared/options/ensureRepositoryExists.test.ts index 62de3f05b..3345f3adf 100644 --- a/src/shared/options/ensureRepositoryExists.test.ts +++ b/src/shared/options/ensureRepositoryExists.test.ts @@ -26,7 +26,6 @@ vi.mock("../doesRepositoryExist.js", () => ({ }, })); -const auth = "abc123"; const owner = "StubOwner"; const repository = "stub-repository"; @@ -54,16 +53,13 @@ describe("ensureRepositoryExists", () => { it("returns the repository when octokit is defined and the repository exists", async () => { mockDoesRepositoryExist.mockResolvedValue(true); const octokit = createMockOctokit(); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { - mode: "initialize", - owner, - repository, - }, - ); - - expect(actual).toEqual({ github: { auth, octokit }, repository }); + const actual = await ensureRepositoryExists(octokit, { + mode: "initialize", + owner, + repository, + }); + + expect(actual).toEqual({ octokit, repository }); }); it("creates a new repository when the prompt is 'create' and the repository does not exist", async () => { @@ -72,12 +68,13 @@ describe("ensureRepositoryExists", () => { mockDoesRepositoryExist.mockResolvedValue(false); mockSelect.mockResolvedValue("create"); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { mode: "initialize", owner, repository }, - ); + const actual = await ensureRepositoryExists(octokit, { + mode: "initialize", + owner, + repository, + }); - expect(actual).toEqual({ github: { auth, octokit }, repository }); + expect(actual).toEqual({ octokit, repository }); expect(mockCreateRepositoryWithApi).toHaveBeenCalledWith(octokit, { owner, preserveGeneratedFrom: undefined, @@ -90,12 +87,13 @@ describe("ensureRepositoryExists", () => { mockDoesRepositoryExist.mockResolvedValue(false); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { mode: "create", owner, repository }, - ); + const actual = await ensureRepositoryExists(octokit, { + mode: "create", + owner, + repository, + }); - expect(actual).toEqual({ github: { auth, octokit }, repository }); + expect(actual).toEqual({ octokit, repository }); expect(mockCreateRepositoryWithApi).toHaveBeenCalledWith(octokit, { owner, preserveGeneratedFrom: undefined, @@ -114,13 +112,14 @@ describe("ensureRepositoryExists", () => { mockSelect.mockResolvedValueOnce("different"); mockText.mockResolvedValue(newRepository); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { mode: "initialize", owner, repository }, - ); + const actual = await ensureRepositoryExists(octokit, { + mode: "initialize", + owner, + repository, + }); expect(actual).toEqual({ - github: { auth, octokit }, + octokit, repository: newRepository, }); expect(mockCreateRepositoryWithApi).not.toHaveBeenCalled(); @@ -136,13 +135,14 @@ describe("ensureRepositoryExists", () => { .mockResolvedValueOnce("create"); mockText.mockResolvedValue(newRepository); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { mode: "initialize", owner, repository }, - ); + const actual = await ensureRepositoryExists(octokit, { + mode: "initialize", + owner, + repository, + }); expect(actual).toEqual({ - github: { auth, octokit }, + octokit, repository: newRepository, }); expect(mockCreateRepositoryWithApi).toHaveBeenCalledWith(octokit, { @@ -158,10 +158,11 @@ describe("ensureRepositoryExists", () => { mockDoesRepositoryExist.mockResolvedValue(false); mockSelect.mockResolvedValue("local"); - const actual = await ensureRepositoryExists( - { auth, octokit }, - { mode: "initialize", owner, repository }, - ); + const actual = await ensureRepositoryExists(octokit, { + mode: "initialize", + owner, + repository, + }); expect(actual).toEqual({ octokit: undefined, repository }); expect(mockCreateRepositoryWithApi).not.toHaveBeenCalled(); diff --git a/src/shared/options/ensureRepositoryExists.ts b/src/shared/options/ensureRepositoryExists.ts index 08b0ee40a..a04c9b707 100644 --- a/src/shared/options/ensureRepositoryExists.ts +++ b/src/shared/options/ensureRepositoryExists.ts @@ -1,11 +1,11 @@ import * as prompts from "@clack/prompts"; +import { Octokit } from "octokit"; import { doesRepositoryExist } from "../doesRepositoryExist.js"; import { isUsingCreateEngine } from "../isUsingCreateEngine.js"; import { filterPromptCancel } from "../prompts.js"; import { Options } from "../types.js"; import { createRepositoryWithApi } from "./createRepositoryWithApi.js"; -import { GitHub } from "./getGitHub.js"; export type EnsureRepositoryExistsOptions = Pick< Options, @@ -13,12 +13,12 @@ export type EnsureRepositoryExistsOptions = Pick< >; export interface RepositoryExistsResult { - github: GitHub | undefined; + octokit: Octokit | undefined; repository: string; } export async function ensureRepositoryExists( - github: GitHub | undefined, + octokit: Octokit | undefined, options: EnsureRepositoryExistsOptions, ): Promise> { // We'll only respect input options once before prompting for them @@ -27,12 +27,12 @@ export async function ensureRepositoryExists( // We'll continuously pester the user for a repository // until they bail, create a new one, or it exists. - while (github) { + while (octokit) { if ( isUsingCreateEngine() || - (await doesRepositoryExist(github.octokit, options)) + (await doesRepositoryExist(octokit, options)) ) { - return { github, repository }; + return { octokit, repository }; } const selection = createRepository @@ -63,12 +63,12 @@ export async function ensureRepositoryExists( return {}; case "create": - await createRepositoryWithApi(github.octokit, { + await createRepositoryWithApi(octokit, { owner: options.owner, preserveGeneratedFrom: options.preserveGeneratedFrom, repository, }); - return { github, repository }; + return { octokit, repository }; case "different": { const newRepository = filterPromptCancel( @@ -86,10 +86,10 @@ export async function ensureRepositoryExists( } case "local": - github = undefined; + octokit = undefined; break; } } - return { github, repository }; + return { octokit, repository }; } diff --git a/src/shared/options/getGitHub.test.ts b/src/shared/options/getGitHub.test.ts deleted file mode 100644 index 01dcf7975..000000000 --- a/src/shared/options/getGitHub.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { describe, expect, it, vi } from "vitest"; - -import { getGitHub } from "./getGitHub.js"; - -const mockGetGitHubAuthToken = vi.fn(); - -vi.mock("get-github-auth-token", () => ({ - get getGitHubAuthToken() { - return mockGetGitHubAuthToken; - }, -})); - -class MockOctokit { - readonly auth: string; - - constructor(options: { auth: string }) { - this.auth = options.auth; - } -} - -vi.mock("octokit", () => ({ - get Octokit() { - return MockOctokit; - }, -})); - -describe("getOctokit", () => { - it("throws an error when getGitHubAuthToken fails", async () => { - mockGetGitHubAuthToken.mockResolvedValue({ - error: "Oh no!", - succeeded: false, - }); - - await expect(getGitHub).rejects.toMatchInlineSnapshot( - `[Error: Couldn't authenticate with GitHub. Either log in with \`gh auth login\` (https://cli.github.com) or set a GH_TOKEN environment variable.]`, - ); - }); - - it("returns a new Octokit when getGitHubAuthToken succeeds", async () => { - const auth = "abc123"; - - mockGetGitHubAuthToken.mockResolvedValue({ - succeeded: true, - token: auth, - }); - - const actual = await getGitHub(); - - expect(actual).toEqual({ auth, octokit: new MockOctokit({ auth }) }); - }); -}); diff --git a/src/shared/options/getGitHub.ts b/src/shared/options/getGitHub.ts deleted file mode 100644 index 6f3f573e1..000000000 --- a/src/shared/options/getGitHub.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { getGitHubAuthToken } from "get-github-auth-token"; -import { Octokit } from "octokit"; - -export interface GitHub { - auth: string; - octokit: Octokit; -} - -export async function getGitHub(): Promise { - const auth = await getGitHubAuthToken(); - - if (!auth.succeeded) { - throw new Error( - "Couldn't authenticate with GitHub. Either log in with `gh auth login` (https://cli.github.com) or set a GH_TOKEN environment variable.", - { cause: auth.error }, - ); - } - - const octokit = new Octokit({ auth: auth.token }); - - return { auth: auth.token, octokit }; -} diff --git a/src/shared/options/readOptions.test.ts b/src/shared/options/readOptions.test.ts index 2c6c26d87..f219eaae8 100644 --- a/src/shared/options/readOptions.test.ts +++ b/src/shared/options/readOptions.test.ts @@ -222,7 +222,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "MockRepository" })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -245,7 +245,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock description." })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -270,7 +270,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock Title" })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -299,7 +299,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock Title" })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -327,7 +327,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock description." })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -353,7 +353,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock title." })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -379,7 +379,7 @@ describe("readOptions", () => { .mockImplementationOnce(() => ({ value: "Mock title." })) .mockImplementation(() => ({ value: undefined })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); mockAugmentOptionsWithExcludes.mockResolvedValue(undefined); @@ -406,7 +406,7 @@ describe("readOptions", () => { value: "mock", })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -414,7 +414,7 @@ describe("readOptions", () => { await readOptions(["--base", mockOptions.base], "create"), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, @@ -431,7 +431,7 @@ describe("readOptions", () => { value: "mock", })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -449,7 +449,7 @@ describe("readOptions", () => { ), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, @@ -486,7 +486,7 @@ describe("readOptions", () => { }), ); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); mockGetPrefillOrPromptedOption.mockImplementation(() => ({ @@ -497,7 +497,7 @@ describe("readOptions", () => { await readOptions(["--base", mockOptions.base], "create"), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: expect.objectContaining({ preserveGeneratedFrom: false, }), @@ -512,7 +512,7 @@ describe("readOptions", () => { }), ); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); mockGetPrefillOrPromptedOption.mockImplementation(() => ({ @@ -526,7 +526,7 @@ describe("readOptions", () => { ), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: expect.objectContaining({ preserveGeneratedFrom: true, }), @@ -543,7 +543,7 @@ describe("readOptions", () => { value: "mock", })); mockEnsureRepositoryExists.mockResolvedValue({ - github: mockOptions.github, + octokit: undefined, repository: mockOptions.repository, }); @@ -551,7 +551,7 @@ describe("readOptions", () => { await readOptions(["--base", mockOptions.base, "--offline"], "create"), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, @@ -586,7 +586,7 @@ describe("readOptions", () => { ); expect(await readOptions(["--offline"], "migrate")).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, @@ -640,7 +640,7 @@ describe("readOptions", () => { ), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, @@ -697,7 +697,7 @@ describe("readOptions", () => { ), ).toStrictEqual({ cancelled: false, - github: mockOptions.github, + octokit: undefined, options: { ...emptyOptions, ...mockOptions, diff --git a/src/shared/options/readOptions.ts b/src/shared/options/readOptions.ts index 6fa0f4bb9..7e08efdb9 100644 --- a/src/shared/options/readOptions.ts +++ b/src/shared/options/readOptions.ts @@ -1,4 +1,6 @@ import { parseArgs } from "node:util"; +import { Octokit } from "octokit"; +import { octokitFromAuth } from "octokit-from-auth"; import { titleCase } from "title-case"; import { z } from "zod"; @@ -11,13 +13,12 @@ import { createOptionDefaults } from "./createOptionDefaults/index.js"; import { detectEmailRedundancy } from "./detectEmailRedundancy.js"; import { ensureRepositoryExists } from "./ensureRepositoryExists.js"; import { getBase } from "./getBase.js"; -import { getGitHub, GitHub } from "./getGitHub.js"; import { getPrefillOrPromptedOption } from "./getPrefillOrPromptedOption.js"; import { logInferredOptions } from "./logInferredOptions.js"; import { optionsSchema } from "./optionsSchema.js"; -export interface GitHubAndOptions { - github: GitHub | undefined; +export interface OctokitAndOptions { + octokit: Octokit | undefined; options: Options; } @@ -29,7 +30,7 @@ export interface OptionsParseCancelled { export type OptionsParseResult = OptionsParseCancelled | OptionsParseSuccess; -export interface OptionsParseSuccess extends GitHubAndOptions { +export interface OptionsParseSuccess extends OctokitAndOptions { cancelled: false; } @@ -160,10 +161,12 @@ export async function readOptions( }; } - const { github, repository } = await ensureRepositoryExists( + const { octokit, repository } = await ensureRepositoryExists( options.skipGitHubApi ? undefined - : await withSpinner("Checking GitHub authentication", getGitHub), + : await withSpinner("Checking GitHub authentication", async () => + octokitFromAuth(), + ), { mode, owner: options.owner, @@ -293,7 +296,7 @@ export async function readOptions( return { cancelled: false, - github, + octokit, options: augmentedOptions, }; } diff --git a/src/steps/detectExistingContributors.test.ts b/src/steps/detectExistingContributors.test.ts deleted file mode 100644 index c5aae0a0b..000000000 --- a/src/steps/detectExistingContributors.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it, vi } from "vitest"; - -import { detectExistingContributors } from "./detectExistingContributors.js"; - -const mockGetAllContributorsForRepository = vi.fn(); - -vi.mock("all-contributors-for-repository", () => ({ - get getAllContributorsForRepository() { - return mockGetAllContributorsForRepository; - }, -})); - -const mock$ = vi.fn().mockImplementation(() => mock$); - -vi.mock("execa", () => ({ - get $() { - return mock$; - }, -})); - -const options = { - owner: "TestOwner", - repository: "test-repository", -}; - -describe("detectExistingContributors", () => { - it("runs npx all-contributors add for each contributor and contribution type", async () => { - mockGetAllContributorsForRepository.mockResolvedValue({ - username: ["bug", "docs"], - }); - - await detectExistingContributors("auth-token", options); - - expect(mock$.mock.calls).toMatchInlineSnapshot(` - [ - [ - { - "env": { - "PRIVATE_TOKEN": "auth-token", - }, - }, - ], - [ - [ - "npx -y all-contributors-cli add ", - " ", - "", - ], - "username", - "0,1", - ], - ] - `); - }); -}); diff --git a/src/steps/detectExistingContributors.ts b/src/steps/detectExistingContributors.ts deleted file mode 100644 index c11348213..000000000 --- a/src/steps/detectExistingContributors.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { getAllContributorsForRepository } from "all-contributors-for-repository"; -import { $ } from "execa"; - -import { Options } from "../shared/types.js"; - -export async function detectExistingContributors( - auth: string | undefined, - options: Pick, -) { - const contributors = await getAllContributorsForRepository({ - auth, - owner: options.owner, - repo: options.repository, - }); - - for (const [contributor, contributions] of Object.entries(contributors)) { - const contributionTypes = Object.keys(contributions).join(","); - await $({ - env: { PRIVATE_TOKEN: auth }, - })`npx -y all-contributors-cli add ${contributor} ${contributionTypes}`; - } -} diff --git a/src/steps/finalizeDependencies.ts b/src/steps/finalizeDependencies.ts index ffb123e15..cf127a990 100644 --- a/src/steps/finalizeDependencies.ts +++ b/src/steps/finalizeDependencies.ts @@ -65,7 +65,7 @@ export async function finalizeDependencies(options: Options) { if (!options.excludeAllContributors) { await execaCommand(`npx all-contributors-cli generate`); await removeDependencies( - ["all-contributors-cli", "all-contributors-for-repository"], + ["all-contributors-cli"], (await readPackageData()).devDependencies, "-D", ); diff --git a/src/steps/initializeGitHubRepository/index.ts b/src/steps/initializeGitHubRepository/index.ts index 51ed2a996..c266a4745 100644 --- a/src/steps/initializeGitHubRepository/index.ts +++ b/src/steps/initializeGitHubRepository/index.ts @@ -1,10 +1,11 @@ import { Octokit } from "octokit"; +import { setGitHubRepositoryLabels } from "set-github-repository-labels"; import { Options } from "../../shared/types.js"; import { initializeGitRemote } from "../initializeGitRemote.js"; import { initializeRepositorySettings } from "../initializeRepositorySettings.js"; import { initializeBranchProtectionSettings } from "./initializeBranchProtectionSettings.js"; -import { initializeRepositoryLabels } from "./labels/initializeRepositoryLabels.js"; +import { outcomeLabels } from "./outcomeLabels.js"; export async function initializeGitHubRepository( octokit: Octokit, @@ -13,5 +14,9 @@ export async function initializeGitHubRepository( await initializeGitRemote(options); await initializeRepositorySettings(octokit, options); await initializeBranchProtectionSettings(octokit, options); - await initializeRepositoryLabels(octokit, options); + await setGitHubRepositoryLabels({ + labels: outcomeLabels, + owner: options.owner, + repository: options.repository, + }); } diff --git a/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.test.ts b/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.test.ts deleted file mode 100644 index 66e747b98..000000000 --- a/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { getExistingEquivalentLabels } from "./getExistingEquivalentLabels.js"; - -const createLabel = (name: string) => ({ - color: "#000000", - description: "A good label.", - name, -}); - -describe("getExistingEquivalentLabels", () => { - it("returns no labels when there are no existing labels", () => { - const actual = getExistingEquivalentLabels([], "abc"); - - expect(actual).toEqual([]); - }); - - it("returns no labels when no existing label matches", () => { - const actual = getExistingEquivalentLabels([createLabel("abc")], "def"); - - expect(actual).toEqual([]); - }); - - it("returns an existing un-prefixed label when it matches by name", () => { - const abcLabel = createLabel("abc"); - const actual = getExistingEquivalentLabels( - [createLabel("def"), abcLabel, createLabel("ghi")], - "abc", - ); - - expect(actual).toEqual([abcLabel]); - }); - - it("returns an existing prefixed label when it matches by name", () => { - const abcDefLabel = createLabel("abc: def"); - const actual = getExistingEquivalentLabels([abcDefLabel], "abc: def"); - - expect(actual).toEqual([abcDefLabel]); - }); - - it("returns the existing label when it matches excluding prefix", () => { - const abcLabel = createLabel("abc"); - const actual = getExistingEquivalentLabels( - [createLabel("abc: def"), abcLabel, createLabel("ghi")], - "type: abc", - ); - - expect(actual).toEqual([abcLabel]); - }); - - it("returns the existing label when it matches an alias", () => { - const enhancementLabel = createLabel("enhancement"); - const actual = getExistingEquivalentLabels( - [createLabel("abc: def"), enhancementLabel, createLabel("ghi")], - "type: feature", - ); - - expect(actual).toEqual([enhancementLabel]); - }); - - it("returns both existing labels when one matches on name and another matches an alias", () => { - const enhancementLabel = createLabel("enhancement"); - const typeFeatureLabel = createLabel("type: feature"); - const actual = getExistingEquivalentLabels( - [ - createLabel("abc: def"), - enhancementLabel, - createLabel("ghi"), - typeFeatureLabel, - ], - "type: feature", - ); - - expect(actual).toEqual([enhancementLabel, typeFeatureLabel]); - }); -}); diff --git a/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.ts b/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.ts deleted file mode 100644 index e884751ce..000000000 --- a/src/steps/initializeGitHubRepository/labels/getExistingEquivalentLabels.ts +++ /dev/null @@ -1,26 +0,0 @@ -const aliases = new Map([ - ["enhancement", "type: feature"], - ["help wanted", "status: accepting prs"], -]); - -export interface GhLabelData { - color: string; - description: null | string; - name: string; -} - -export function getExistingEquivalentLabels( - existingLabels: GhLabelData[], - outcomeLabelName: string, -) { - const outcomeTrimmed = outcomeLabelName.replace(/\w+: (\w+)/, "$1"); - - return existingLabels.filter(({ name: existingName }) => { - return ( - existingName === outcomeLabelName || - existingName === outcomeTrimmed || - aliases.get(existingName) === outcomeLabelName || - existingName.replace(/\w+: (\w+)/, "$1") === outcomeLabelName - ); - }); -} diff --git a/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.test.ts b/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.test.ts deleted file mode 100644 index fc7420bb5..000000000 --- a/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.test.ts +++ /dev/null @@ -1,387 +0,0 @@ -import { Octokit } from "octokit"; -import { describe, expect, it, MockInstance, vi } from "vitest"; - -import { GhLabelData } from "./getExistingEquivalentLabels.js"; -import { initializeRepositoryLabels } from "./initializeRepositoryLabels.js"; - -const mockOutcomeLabel = { - color: "000000", - description: "def ghi", - name: "area: abc", -}; - -vi.mock("./outcomeLabels.js", () => ({ - get outcomeLabels() { - return [mockOutcomeLabel]; - }, -})); - -const createMockOctokit = (existingLabels: GhLabelData[]) => - ({ - request: vi.fn().mockResolvedValueOnce({ data: existingLabels }), - }) as unknown as Octokit & { request: MockInstance }; - -const options = { - owner: "TestOwner", - repository: "test-repository", -}; - -describe("migrateRepositoryLabels", () => { - it("creates an outcome label when there are no existing labels", async () => { - const octokit = createMockOctokit([]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "POST /repos/{owner}/{repo}/labels", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("creates a new outcome label when an existing label doesn't have an equivalent", async () => { - const octokit = createMockOctokit([ - { - color: "111111", - description: "jkl mno", - name: "other", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "POST /repos/{owner}/{repo}/labels", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("doesn't edit a outcome label when it already exists with the same information", async () => { - const octokit = createMockOctokit([mockOutcomeLabel]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("edits the outcome label when it already exists with different color", async () => { - const octokit = createMockOctokit([ - { - ...mockOutcomeLabel, - color: "111111", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "PATCH /repos/{owner}/{repo}/labels/{name}", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "new_name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("edits the outcome label when it already exists with a different description", async () => { - const octokit = createMockOctokit([ - { - ...mockOutcomeLabel, - description: "updated", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "PATCH /repos/{owner}/{repo}/labels/{name}", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "new_name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("deletes an existing non-outcome label when the equivalent outcome label already exists", async () => { - const octokit = createMockOctokit([ - { - color: "000000", - description: "def ghi", - name: "abc", - }, - { - color: "000000", - description: "def ghi", - name: "area: abc", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "DELETE /repos/{owner}/{repo}/labels/{name}", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("doesn't delete a pre-existing label when it isn't a outcome label", async () => { - const octokit = createMockOctokit([ - { - color: "000000", - description: "def ghi", - name: "unknown", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "POST /repos/{owner}/{repo}/labels", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("deletes the existing duplicate outcome label and edits the label with the outcome name and different color when both exist", async () => { - const octokit = createMockOctokit([ - { - color: "000000", - description: "def ghi", - name: "abc", - }, - { - color: "111111", - description: "def ghi", - name: "area: abc", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "DELETE /repos/{owner}/{repo}/labels/{name}", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "PATCH /repos/{owner}/{repo}/labels/{name}", - { - "color": "000000", - "description": "def ghi", - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "area: abc", - "new_name": "area: abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); - - it("deletes the existing duplicate outcome label and does not edit the label with the outcome name and same information when both exist", async () => { - const octokit = createMockOctokit([ - { - color: "000000", - description: "def ghi", - name: "abc", - }, - { - color: "000000", - description: "def ghi", - name: "area: abc", - }, - ]); - - await initializeRepositoryLabels(octokit, options); - - expect(octokit.request.mock.calls).toMatchInlineSnapshot(` - [ - [ - "GET /repos/{owner}/{repo}/labels", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - [ - "DELETE /repos/{owner}/{repo}/labels/{name}", - { - "headers": { - "X-GitHub-Api-Version": "2022-11-28", - }, - "name": "abc", - "owner": "TestOwner", - "repo": "test-repository", - }, - ], - ] - `); - }); -}); diff --git a/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.ts b/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.ts deleted file mode 100644 index 5c3357076..000000000 --- a/src/steps/initializeGitHubRepository/labels/initializeRepositoryLabels.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Octokit } from "octokit"; - -import { Options } from "../../../shared/types.js"; -import { getExistingEquivalentLabels } from "./getExistingEquivalentLabels.js"; -import { outcomeLabels } from "./outcomeLabels.js"; - -export async function initializeRepositoryLabels( - octokit: Octokit, - options: Pick, -) { - const { data: existingLabels } = await octokit.request( - "GET /repos/{owner}/{repo}/labels", - { - headers: { - "X-GitHub-Api-Version": "2022-11-28", - }, - owner: options.owner, - repo: options.repository, - }, - ); - - for (const outcome of outcomeLabels) { - const existingEquivalents = getExistingEquivalentLabels( - existingLabels, - outcome.name, - ); - - // Case: the repo has neither of the two label types - if (!existingEquivalents.length) { - await octokit.request("POST /repos/{owner}/{repo}/labels", { - color: outcome.color.replace("#", ""), - description: outcome.description, - headers: { - "X-GitHub-Api-Version": "2022-11-28", - }, - name: outcome.name, - owner: options.owner, - repo: options.repository, - }); - continue; - } - - for (const existingEquivalent of existingEquivalents) { - // Case: the repo already has both prefixed and non-prefixed label name types - // E.g. both "area: documentation" and "documentation" - if ( - existingEquivalent.name !== outcome.name && - existingLabels.some((existing) => existing.name === outcome.name) - ) { - await octokit.request("DELETE /repos/{owner}/{repo}/labels/{name}", { - headers: { - "X-GitHub-Api-Version": "2022-11-28", - }, - name: existingEquivalent.name, - owner: options.owner, - repo: options.repository, - }); - - continue; - } - - // Case: the repo has one of the two label types, with >=1 different property - // E.g. "documentation" and the same color and description - // E.g. "area: documentation" but with a different color - if ( - outcome.color !== existingEquivalent.color || - outcome.description !== existingEquivalent.description || - outcome.name !== existingEquivalent.name - ) { - await octokit.request("PATCH /repos/{owner}/{repo}/labels/{name}", { - color: outcome.color.replace("#", ""), - description: outcome.description, - headers: { - "X-GitHub-Api-Version": "2022-11-28", - }, - name: existingEquivalent.name, - new_name: outcome.name, - owner: options.owner, - repo: options.repository, - }); - } - } - } -} diff --git a/src/steps/initializeGitHubRepository/labels/outcomeLabels.ts b/src/steps/initializeGitHubRepository/outcomeLabels.ts similarity index 94% rename from src/steps/initializeGitHubRepository/labels/outcomeLabels.ts rename to src/steps/initializeGitHubRepository/outcomeLabels.ts index 8b7ce6312..092bfd5bc 100644 --- a/src/steps/initializeGitHubRepository/labels/outcomeLabels.ts +++ b/src/steps/initializeGitHubRepository/outcomeLabels.ts @@ -1,6 +1,7 @@ /* spellchecker: disable */ export const outcomeLabels = [ { + aliases: ["docs"], color: "0075ca", description: "Improvements or additions to docs 📝", name: "area: documentation", @@ -27,6 +28,7 @@ export const outcomeLabels = [ name: "invalid", }, { + aliases: ["help wanted"], color: "0E8A16", description: "Please, send a pull request to resolve this! 🙏", name: "status: accepting prs", @@ -68,10 +70,11 @@ export const outcomeLabels = [ }, { color: "d73a4a", - description: "Something isn't working :( 🐛", + description: "Something isn't working 🐛", name: "type: bug", }, { + aliases: ["enhancement"], color: "a2eeef", description: "New enhancement or request 🚀", name: "type: feature", diff --git a/src/steps/uninstallPackages.ts b/src/steps/uninstallPackages.ts index 9354c351b..7e4386bfa 100644 --- a/src/steps/uninstallPackages.ts +++ b/src/steps/uninstallPackages.ts @@ -9,12 +9,10 @@ export async function uninstallPackages(offline: boolean | undefined) { [ "@clack/prompts", "@prettier/sync", - "all-contributors-for-repository", "all-contributors-cli", "chalk", "create", "execa", - "get-github-auth-token", "git-remote-origin-url", "git-url-parse", "input-from-file", @@ -23,11 +21,14 @@ export async function uninstallPackages(offline: boolean | undefined) { "lazy-value", "npm-user", "octokit", + "octokit-from-auth", "parse-author", "parse-package-name", + "populate-all-contributors-for-repository", "prettier", "replace-in-file", "rimraf", + "set-github-repository-labels", "sort-package-json", "title-case", "zod", diff --git a/src/steps/writing/creation/index.test.ts b/src/steps/writing/creation/index.test.ts index 1b30de512..90c5a768c 100644 --- a/src/steps/writing/creation/index.test.ts +++ b/src/steps/writing/creation/index.test.ts @@ -202,11 +202,9 @@ describe("createStructure", () => { dependencies: getPackageDependencies( "@clack/prompts", "@prettier/sync", - "all-contributors-for-repository", "chalk", "create", "execa", - "get-github-auth-token", "git-remote-origin-url", "git-url-parse", "input-from-file", @@ -215,11 +213,14 @@ describe("createStructure", () => { "lazy-value", "npm-user", "octokit", + "octokit-from-auth", "parse-author", "parse-package-name", + "populate-all-contributors-for-repository", "prettier", "replace-in-file", "rimraf", + "set-github-repository-labels", "sort-package-json", "title-case", "zod", @@ -231,6 +232,7 @@ describe("createStructure", () => { "@types/git-url-parse", "@types/js-yaml", "@types/parse-author", + "all-contributors-cli", "c8", "create-testers", "cspell",