generated from nhcarrigan/template
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64e2b4419c | |||
| 43e8b4e6c6 | |||
| bd3f2c6388 |
+6
-5
@@ -19,12 +19,13 @@
|
|||||||
"@inquirer/prompts": "7.8.6",
|
"@inquirer/prompts": "7.8.6",
|
||||||
"@nhcarrigan/eslint-config": "5.2.0",
|
"@nhcarrigan/eslint-config": "5.2.0",
|
||||||
"@nhcarrigan/typescript-config": "4.0.0",
|
"@nhcarrigan/typescript-config": "4.0.0",
|
||||||
"@types/node": "24.3.0",
|
|
||||||
"eslint": "9.34.0",
|
|
||||||
"tsx": "4.20.5",
|
|
||||||
"typescript": "5.9.2",
|
|
||||||
"@octokit/rest": "22.0.0",
|
"@octokit/rest": "22.0.0",
|
||||||
"@types/cli-progress": "3.11.6",
|
"@types/cli-progress": "3.11.6",
|
||||||
"cli-progress": "3.12.0"
|
"@types/node": "24.3.0",
|
||||||
|
"cli-progress": "3.12.0",
|
||||||
|
"eslint": "9.34.0",
|
||||||
|
"open": "11.0.0",
|
||||||
|
"tsx": "4.20.5",
|
||||||
|
"typescript": "5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+96
@@ -35,6 +35,9 @@ importers:
|
|||||||
eslint:
|
eslint:
|
||||||
specifier: 9.34.0
|
specifier: 9.34.0
|
||||||
version: 9.34.0
|
version: 9.34.0
|
||||||
|
open:
|
||||||
|
specifier: 11.0.0
|
||||||
|
version: 11.0.0
|
||||||
tsx:
|
tsx:
|
||||||
specifier: 4.20.5
|
specifier: 4.20.5
|
||||||
version: 4.20.5
|
version: 4.20.5
|
||||||
@@ -1284,6 +1287,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
|
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
bundle-name@4.1.0:
|
||||||
|
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
cac@6.7.14:
|
cac@6.7.14:
|
||||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1395,10 +1402,22 @@ packages:
|
|||||||
deep-is@0.1.4:
|
deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
|
|
||||||
|
default-browser-id@5.0.1:
|
||||||
|
resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
default-browser@5.4.0:
|
||||||
|
resolution: {integrity: sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
define-data-property@1.1.4:
|
define-data-property@1.1.4:
|
||||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
define-lazy-prop@3.0.0:
|
||||||
|
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
define-properties@1.2.1:
|
define-properties@1.2.1:
|
||||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -1823,6 +1842,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
|
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
is-docker@3.0.0:
|
||||||
|
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
is-extglob@2.1.1:
|
is-extglob@2.1.1:
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1843,6 +1867,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-in-ssh@1.0.0:
|
||||||
|
resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
|
is-inside-container@1.0.0:
|
||||||
|
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
|
||||||
|
engines: {node: '>=14.16'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
is-map@2.0.3:
|
is-map@2.0.3:
|
||||||
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
|
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -1895,6 +1928,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
is-wsl@3.1.0:
|
||||||
|
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
isarray@2.0.5:
|
isarray@2.0.5:
|
||||||
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
|
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
|
||||||
|
|
||||||
@@ -2058,6 +2095,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
open@11.0.0:
|
||||||
|
resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -2153,6 +2194,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
|
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
powershell-utils@0.1.0:
|
||||||
|
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -2227,6 +2272,10 @@ packages:
|
|||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
run-applescript@7.1.0:
|
||||||
|
resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||||
|
|
||||||
@@ -2609,6 +2658,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
wsl-utils@0.3.0:
|
||||||
|
resolution: {integrity: sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
yocto-queue@0.1.0:
|
yocto-queue@0.1.0:
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -4294,6 +4347,10 @@ snapshots:
|
|||||||
|
|
||||||
builtin-modules@3.3.0: {}
|
builtin-modules@3.3.0: {}
|
||||||
|
|
||||||
|
bundle-name@4.1.0:
|
||||||
|
dependencies:
|
||||||
|
run-applescript: 7.1.0
|
||||||
|
|
||||||
cac@6.7.14: {}
|
cac@6.7.14: {}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
@@ -4396,12 +4453,21 @@ snapshots:
|
|||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
|
default-browser-id@5.0.1: {}
|
||||||
|
|
||||||
|
default-browser@5.4.0:
|
||||||
|
dependencies:
|
||||||
|
bundle-name: 4.1.0
|
||||||
|
default-browser-id: 5.0.1
|
||||||
|
|
||||||
define-data-property@1.1.4:
|
define-data-property@1.1.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-define-property: 1.0.1
|
es-define-property: 1.0.1
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
|
|
||||||
|
define-lazy-prop@3.0.0: {}
|
||||||
|
|
||||||
define-properties@1.2.1:
|
define-properties@1.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-data-property: 1.1.4
|
define-data-property: 1.1.4
|
||||||
@@ -5006,6 +5072,8 @@ snapshots:
|
|||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
|
is-docker@3.0.0: {}
|
||||||
|
|
||||||
is-extglob@2.1.1: {}
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
is-finalizationregistry@1.1.1:
|
is-finalizationregistry@1.1.1:
|
||||||
@@ -5025,6 +5093,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
|
is-in-ssh@1.0.0: {}
|
||||||
|
|
||||||
|
is-inside-container@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
is-docker: 3.0.0
|
||||||
|
|
||||||
is-map@2.0.3: {}
|
is-map@2.0.3: {}
|
||||||
|
|
||||||
is-negative-zero@2.0.3: {}
|
is-negative-zero@2.0.3: {}
|
||||||
@@ -5075,6 +5149,10 @@ snapshots:
|
|||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
|
is-wsl@3.1.0:
|
||||||
|
dependencies:
|
||||||
|
is-inside-container: 1.0.0
|
||||||
|
|
||||||
isarray@2.0.5: {}
|
isarray@2.0.5: {}
|
||||||
|
|
||||||
isexe@2.0.0: {}
|
isexe@2.0.0: {}
|
||||||
@@ -5232,6 +5310,15 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
|
|
||||||
|
open@11.0.0:
|
||||||
|
dependencies:
|
||||||
|
default-browser: 5.4.0
|
||||||
|
define-lazy-prop: 3.0.0
|
||||||
|
is-in-ssh: 1.0.0
|
||||||
|
is-inside-container: 1.0.0
|
||||||
|
powershell-utils: 0.1.0
|
||||||
|
wsl-utils: 0.3.0
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
@@ -5317,6 +5404,8 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
powershell-utils@0.1.0: {}
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
prop-types@15.8.1:
|
prop-types@15.8.1:
|
||||||
@@ -5418,6 +5507,8 @@ snapshots:
|
|||||||
'@rollup/rollup-win32-x64-msvc': 4.49.0
|
'@rollup/rollup-win32-x64-msvc': 4.49.0
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
|
run-applescript@7.1.0: {}
|
||||||
|
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
@@ -5869,6 +5960,11 @@ snapshots:
|
|||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
|
|
||||||
|
wsl-utils@0.3.0:
|
||||||
|
dependencies:
|
||||||
|
is-wsl: 3.1.0
|
||||||
|
powershell-utils: 0.1.0
|
||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|
||||||
yoctocolors-cjs@2.1.3: {}
|
yoctocolors-cjs@2.1.3: {}
|
||||||
|
|||||||
+267
-25
@@ -19,6 +19,7 @@ import crypto from "node:crypto";
|
|||||||
import http from "node:http";
|
import http from "node:http";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
import { confirm } from "@inquirer/prompts";
|
import { confirm } from "@inquirer/prompts";
|
||||||
|
import open from "open";
|
||||||
|
|
||||||
interface Guild {
|
interface Guild {
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -29,12 +30,14 @@ interface Guild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Stats {
|
interface Stats {
|
||||||
community: Array<string>;
|
admin: Array<string>;
|
||||||
moderating: Array<string>;
|
community: Array<string>;
|
||||||
owned: Array<string>;
|
discoverable: Array<string>;
|
||||||
partnered: Array<string>;
|
moderating: Array<string>;
|
||||||
total: number;
|
owned: Array<string>;
|
||||||
verified: Array<string>;
|
partnered: Array<string>;
|
||||||
|
total: number;
|
||||||
|
verified: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permission Flags (BigInt)
|
// Permission Flags (BigInt)
|
||||||
@@ -62,28 +65,254 @@ const printReport = (stats: Stats): void => {
|
|||||||
console.log(`Total Servers Joined: ${stats.total.toString()}\n`);
|
console.log(`Total Servers Joined: ${stats.total.toString()}\n`);
|
||||||
|
|
||||||
printList("Owned Servers", stats.owned, "đź‘‘");
|
printList("Owned Servers", stats.owned, "đź‘‘");
|
||||||
printList("Moderating (Non-Owned)", stats.moderating, "🛡️ ");
|
printList("Admin (Non-Owned)", stats.admin, "⚙️ ");
|
||||||
|
printList("Moderating (Non-Admin/Non-Owned)", stats.moderating, "🛡️ ");
|
||||||
printList("Partnered Servers", stats.partnered, "🤝");
|
printList("Partnered Servers", stats.partnered, "🤝");
|
||||||
printList("Verified Servers", stats.verified, "âś…");
|
printList("Verified Servers", stats.verified, "âś…");
|
||||||
printList("Community/Public Servers", stats.community, "🌍");
|
printList("Community/Public Servers", stats.community, "🌍");
|
||||||
|
printList("Discovery Enabled Servers", stats.discoverable, "🔍");
|
||||||
|
|
||||||
console.log(`======================================\n`);
|
console.log(`======================================\n`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const escapeHtml = (value: string): string => {
|
||||||
|
return value.
|
||||||
|
replaceAll("&", "&").
|
||||||
|
replaceAll("<", "<").
|
||||||
|
replaceAll(">", ">").
|
||||||
|
replaceAll("\"", """).
|
||||||
|
replaceAll("'", "'");
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildDashboardHtml = (stats: Stats): string => {
|
||||||
|
const tiles: Array<{ items: Array<string>; label: string; value: number }> = [
|
||||||
|
{ items: stats.owned, label: "You Own", value: stats.owned.length },
|
||||||
|
{ items: stats.admin, label: "You Admin", value: stats.admin.length },
|
||||||
|
{
|
||||||
|
items: stats.moderating,
|
||||||
|
label: "You Moderate",
|
||||||
|
value: stats.moderating.length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: stats.community,
|
||||||
|
label: "Community Enabled",
|
||||||
|
value: stats.community.length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: stats.discoverable,
|
||||||
|
label: "Discovery Enabled",
|
||||||
|
value: stats.discoverable.length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: stats.partnered,
|
||||||
|
label: "Partnered",
|
||||||
|
value: stats.partnered.length,
|
||||||
|
},
|
||||||
|
{ items: stats.verified, label: "Verified", value: stats.verified.length },
|
||||||
|
];
|
||||||
|
|
||||||
|
const cards = tiles.map((tile) => {
|
||||||
|
const listItems
|
||||||
|
= tile.items.length === 0
|
||||||
|
? "<li class=\"empty\">No servers in this category.</li>"
|
||||||
|
: tile.items.map((name) => {
|
||||||
|
return `<li>${escapeHtml(name)}</li>`;
|
||||||
|
}).join("");
|
||||||
|
return `
|
||||||
|
<div class="card">
|
||||||
|
<p class="label">${escapeHtml(tile.label)}</p>
|
||||||
|
<p class="count">${tile.value.toString()}</p>
|
||||||
|
<ul class="server-list">
|
||||||
|
${listItems}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}).join("");
|
||||||
|
|
||||||
|
return `<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Discord Server Counter</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
background: #0f0f16;
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2rem;
|
||||||
|
background: linear-gradient(135deg, #ff4ecd, #7873f5, #4ac7fa, #43e97b);
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
width: min(1100px, 100%);
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
background: linear-gradient(120deg, #ff4ecd, #b388ff, #4ac7fa, #43e97b);
|
||||||
|
box-shadow: 0 20px 50px rgba(15, 23, 42, 0.35);
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
padding: 2rem 2.5rem 3rem;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: clamp(1.75rem, 3vw, 2.5rem);
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
color: #6b7280;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
.total {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
.total span {
|
||||||
|
display: block;
|
||||||
|
color: #6b7280;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
.total strong {
|
||||||
|
font-size: clamp(2.5rem, 5vw, 3.5rem);
|
||||||
|
color: #4c1d95;
|
||||||
|
}
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: #f9fafb;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 1.25rem;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
color: #7c3aed;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
.count {
|
||||||
|
font-size: 2.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
.server-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 180px;
|
||||||
|
}
|
||||||
|
.server-list li {
|
||||||
|
padding: 0.35rem 0;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
.server-list li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.server-list .empty {
|
||||||
|
color: #9ca3af;
|
||||||
|
font-style: italic;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
body {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<h1>Server Counter</h1>
|
||||||
|
<p class="subtitle">View counts of servers you are in along with quick insights.</p>
|
||||||
|
<div class="total">
|
||||||
|
<span>You are in</span>
|
||||||
|
<strong>${stats.total.toString()} servers</strong>
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
${cards}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const serveStatsDashboard = async(stats: Stats): Promise<void> => {
|
||||||
|
const html = buildDashboardHtml(stats);
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const server = http.createServer((request, response) => {
|
||||||
|
if (request.method !== "GET") {
|
||||||
|
response.statusCode = 405;
|
||||||
|
response.end("Method Not Allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.statusCode = 200;
|
||||||
|
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
||||||
|
response.end(html);
|
||||||
|
server.close();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(0, "127.0.0.1", () => {
|
||||||
|
const address = server.address();
|
||||||
|
if (address !== null && typeof address === "object") {
|
||||||
|
const url = `http://${address.address}:${address.port.toString()}/`;
|
||||||
|
console.log(`Opening dashboard at ${url}`);
|
||||||
|
void open(url, { wait: false }).catch(() => {
|
||||||
|
console.log(
|
||||||
|
`Failed to open browser automatically. Please visit ${url} manually.`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const checkForPermission = (perms: bigint, permission: bigint): boolean => {
|
const checkForPermission = (perms: bigint, permission: bigint): boolean => {
|
||||||
// eslint-disable-next-line no-bitwise -- Since Discord uses bit flags...
|
// eslint-disable-next-line no-bitwise -- Since Discord uses bit flags...
|
||||||
return (perms & permission) === permission;
|
return (perms & permission) === permission;
|
||||||
};
|
};
|
||||||
|
|
||||||
const analyzeGuilds = (guilds: Array<Guild>): void => {
|
const analyzeGuilds = (guilds: Array<Guild>): Stats => {
|
||||||
// Arrays to store names instead of just counts
|
// Arrays to store names instead of just counts
|
||||||
const stats: Stats = {
|
const stats: Stats = {
|
||||||
community: [],
|
admin: [],
|
||||||
moderating: [],
|
community: [],
|
||||||
owned: [],
|
discoverable: [],
|
||||||
partnered: [],
|
moderating: [],
|
||||||
total: guilds.length,
|
owned: [],
|
||||||
verified: [],
|
partnered: [],
|
||||||
|
total: guilds.length,
|
||||||
|
verified: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const guild of guilds) {
|
for (const guild of guilds) {
|
||||||
@@ -96,18 +325,17 @@ const analyzeGuilds = (guilds: Array<Guild>): void => {
|
|||||||
stats.owned.push(name ?? "Unknown");
|
stats.owned.push(name ?? "Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
const isAdmin = checkForPermission(perms, permissions.administrator);
|
||||||
* 2. Moderation
|
const hasModeratorPermissions
|
||||||
* We consider you a "Moderator" if you have specific mod permissions,
|
= isAdmin
|
||||||
* Even if you don't own the server.
|
|
||||||
*/
|
|
||||||
const isModerator
|
|
||||||
= checkForPermission(perms, permissions.administrator)
|
|
||||||
|| checkForPermission(perms, permissions.manageGuild)
|
|| checkForPermission(perms, permissions.manageGuild)
|
||||||
|| checkForPermission(perms, permissions.banMembers)
|
|| checkForPermission(perms, permissions.banMembers)
|
||||||
|| checkForPermission(perms, permissions.kickMembers)
|
|| checkForPermission(perms, permissions.kickMembers)
|
||||||
|| checkForPermission(perms, permissions.moderateMembers);
|
|| checkForPermission(perms, permissions.moderateMembers);
|
||||||
if (isModerator && owner !== true) {
|
|
||||||
|
if (isAdmin && owner !== true) {
|
||||||
|
stats.admin.push(name ?? id);
|
||||||
|
} else if (hasModeratorPermissions && owner !== true && !isAdmin) {
|
||||||
stats.moderating.push(name ?? id);
|
stats.moderating.push(name ?? id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,12 +354,16 @@ const analyzeGuilds = (guilds: Array<Guild>): void => {
|
|||||||
* "COMMUNITY" feature enables public facing screens (Welcome Screen, Rules, etc)
|
* "COMMUNITY" feature enables public facing screens (Welcome Screen, Rules, etc)
|
||||||
* "DISCOVERABLE" means it appears in Server Discovery
|
* "DISCOVERABLE" means it appears in Server Discovery
|
||||||
*/
|
*/
|
||||||
if (features.includes("COMMUNITY") || features.includes("DISCOVERABLE")) {
|
if (features.includes("COMMUNITY")) {
|
||||||
stats.community.push(name ?? id);
|
stats.community.push(name ?? id);
|
||||||
}
|
}
|
||||||
|
if (features.includes("DISCOVERABLE")) {
|
||||||
|
stats.discoverable.push(name ?? id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printReport(stats);
|
printReport(stats);
|
||||||
|
return stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultRedirectUri = "http://127.0.0.1:8721/callback";
|
const defaultRedirectUri = "http://127.0.0.1:8721/callback";
|
||||||
@@ -346,13 +578,22 @@ async function startOAuthFlow(): Promise<string> {
|
|||||||
authUrl.searchParams.set("code_challenge_method", "S256");
|
authUrl.searchParams.set("code_challenge_method", "S256");
|
||||||
|
|
||||||
console.log("\n====== Discord OAuth ======");
|
console.log("\n====== Discord OAuth ======");
|
||||||
console.log("1. Open the following URL in your browser:");
|
console.log(
|
||||||
|
`1. Open the following URL in your browser (we will try to automatically open it for you):`,
|
||||||
|
);
|
||||||
console.log(authUrl.toString());
|
console.log(authUrl.toString());
|
||||||
console.log("2. Approve access for your application.");
|
console.log("2. Approve access for your application.");
|
||||||
console.log(
|
console.log(
|
||||||
"3. Return here; the script will continue once approval is complete.\n",
|
"3. Return here; the script will continue once approval is complete.\n",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void open(authUrl.toString(), { wait: false }).catch(() => {
|
||||||
|
console.log(
|
||||||
|
"Failed to open browser. Please open the following URL in your browser:",
|
||||||
|
);
|
||||||
|
console.log(authUrl.toString());
|
||||||
|
});
|
||||||
|
|
||||||
const code = await waitForOAuthCode(redirectUri, state);
|
const code = await waitForOAuthCode(redirectUri, state);
|
||||||
const tokenRequest: TokenExchangeOptions = {
|
const tokenRequest: TokenExchangeOptions = {
|
||||||
clientId,
|
clientId,
|
||||||
@@ -422,7 +663,8 @@ async function getGuilds(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const guilds: Array<Guild> = await response.json();
|
const guilds: Array<Guild> = await response.json();
|
||||||
analyzeGuilds(guilds);
|
const stats = analyzeGuilds(guilds);
|
||||||
|
await serveStatsDashboard(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
await getGuilds();
|
await getGuilds();
|
||||||
|
|||||||
Reference in New Issue
Block a user