From 77386ead4d95486abc75059e261441bd1771c3c0 Mon Sep 17 00:00:00 2001 From: "otoneko." Date: Fri, 3 Jul 2026 23:27:04 +0900 Subject: [PATCH 1/2] fix: remove devDependencies - fix types --- .npmrc | 10 --- package.json | 8 +-- pnpm-lock.yaml | 182 ++---------------------------------------------- src/context.ts | 10 ++- src/jishaku.ts | 18 +++-- src/owners.ts | 6 +- src/security.ts | 6 +- src/types.ts | 51 +++++++------- tsup.config.ts | 6 +- 9 files changed, 59 insertions(+), 238 deletions(-) delete mode 100644 .npmrc diff --git a/.npmrc b/.npmrc deleted file mode 100644 index c93e94e..0000000 --- a/.npmrc +++ /dev/null @@ -1,10 +0,0 @@ -# Required for `pnpm build:types` (dts-bundle-generator --external-inlines): pnpm's default -# symlinked node_modules layout (node_modules/discord.js-v13 -> .pnpm/discord.js@13.x/.../discord.js) -# breaks dts-bundle-generator's package-name matching for aliased devDependencies — it resolves -# the symlink and only ever sees the *real* package name ("discord.js"), never the alias, so -# --external-inlines discord.js-v13/discord.js-v14 silently does nothing (falls back to a plain, -# unresolved external import) instead of inlining. `hoisted` gives every package its own real -# directory under node_modules, like npm/yarn, which resolves correctly. Confirmed by reproducing -# and fixing this exact failure. Trade-off: hoisted linking is less strict than pnpm's default — -# phantom access to transitive (non-direct) dependencies becomes possible. -node-linker=hoisted diff --git a/package.json b/package.json index 57cfb0b..71a8ac3 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,7 @@ "dist" ], "scripts": { - "build": "tsup && pnpm build:types", - "build:types": "dts-bundle-generator --no-check --external-inlines discord.js-v13 discord.js-v14 -o dist/index.d.ts src/index.ts", + "build": "tsup", "test": "vitest run", "test:watch": "vitest", "typecheck": "tsc --noEmit", @@ -78,11 +77,6 @@ "devDependencies": { "@biomejs/biome": "^2.5.1", "discord.js": "latest", - "discord.js-v13": "npm:discord.js@^13.17.1", - "discord.js-v14": "npm:discord.js@^14.0.0", - "discord.js-selfbot-v13": "latest", - "discord.js-selfbot-youtsuho-v13": "latest", - "dts-bundle-generator": "^9.5.1", "tsup": "^8.5.1", "typescript": "^6.0.3", "vitest": "^4.1.9" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 438cdfe..c47f16e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,12 @@ importers: consola: specifier: ^3.4.2 version: 3.4.2 + discord.js-selfbot-v13: + specifier: '*' + version: 3.7.1 + discord.js-selfbot-youtsuho-v13: + specifier: '*' + version: 3.7.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) is-package-latest: specifier: ^2.0.3 version: 2.0.3 @@ -27,21 +33,6 @@ importers: discord.js: specifier: latest version: 14.26.4 - discord.js-selfbot-v13: - specifier: latest - version: 3.7.1 - discord.js-selfbot-youtsuho-v13: - specifier: latest - version: 3.7.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - discord.js-v13: - specifier: npm:discord.js@^13.17.1 - version: discord.js@13.17.1 - discord.js-v14: - specifier: npm:discord.js@^14.0.0 - version: discord.js@14.26.4 - dts-bundle-generator: - specifier: ^9.5.1 - version: 9.5.1 tsup: specifier: ^8.5.1 version: 8.5.1(postcss@8.5.16)(typescript@6.0.3) @@ -111,20 +102,10 @@ packages: cpu: [x64] os: [win32] - '@discordjs/builders@0.16.0': - resolution: {integrity: sha512-9/NCiZrLivgRub2/kBc0Vm5pMBE5AUdYbdXsLu/yg9ANgvnaJ0bZKTY8yYnLbsEc/LYUP79lEIdC73qEYhWq7A==} - engines: {node: '>=16.9.0'} - deprecated: no longer supported - '@discordjs/builders@1.14.1': resolution: {integrity: sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ==} engines: {node: '>=16.11.0'} - '@discordjs/collection@0.7.0': - resolution: {integrity: sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==} - engines: {node: '>=16.9.0'} - deprecated: no longer supported - '@discordjs/collection@1.5.3': resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} engines: {node: '>=16.11.0'} @@ -597,10 +578,6 @@ packages: resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} - '@sapphire/shapeshift@3.9.7': - resolution: {integrity: sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==} - engines: {node: '>=v16'} - '@sapphire/shapeshift@4.0.0': resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} engines: {node: '>=v16'} @@ -722,9 +699,6 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/node-fetch@2.6.13': - resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} - '@types/node@26.0.1': resolution: {integrity: sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==} @@ -840,10 +814,6 @@ packages: 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'} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -901,12 +871,6 @@ packages: dijkstrajs@1.0.3: resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} - discord-api-types@0.33.5: - resolution: {integrity: sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==} - - discord-api-types@0.36.3: - resolution: {integrity: sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==} - discord-api-types@0.38.49: resolution: {integrity: sha512-XnqcWmnFZFAE8ZM8SHAw9DIV8D3Or00rMQ8iQLotrEA2PmXhl+ykaf6L6q4l474hrSUH1JaYcv+iOMRWp2p6Tg==} @@ -919,20 +883,10 @@ packages: resolution: {integrity: sha512-O2VF9C8W37UT7fsnu62GJAHs/463AuARuINUMh97SwnALE1kAJeIqXeoePOZkXRyRMTonMdp66a/MI7gue3vpw==} engines: {node: '>=20.18'} - discord.js@13.17.1: - resolution: {integrity: sha512-h13kUf+7ZaP5ZWggzooCxFutvJJvugcAO54oTEIdVr3zQWi0Sf/61S1kETtuY9nVAyYebXR/Ey4C+oWbsgEkew==} - engines: {node: '>=16.6.0', npm: '>=7.0.0'} - deprecated: Version 13 is no longer supported. - discord.js@14.26.4: resolution: {integrity: sha512-4oBp8tc6Kf8IDBwAHhbsMaAqx1b5fob9SNasZT7V6yyyUydoO5i5fGuX7TmvRtR+q/WgKRnRViRoAWnG7fNyvA==} engines: {node: '>=18'} - dts-bundle-generator@9.5.1: - resolution: {integrity: sha512-DxpJOb2FNnEyOzMkG11sxO2dmxPjthoVWxfKqWYJ/bI/rT1rvTMktF5EKjAYrRZu6Z6t3NhOUZ0sZ5ZXevOfbA==} - engines: {node: '>=14.0.0'} - hasBin: true - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -964,10 +918,6 @@ packages: engines: {node: '>=18'} hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1206,15 +1156,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - 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 - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1432,9 +1373,6 @@ packages: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -1570,16 +1508,10 @@ packages: jsdom: optional: true - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - werift-rtp@0.8.8: resolution: {integrity: sha512-GiYMSdvCyScQaw5bnEsraSoHUVZpjfokJAiLV4R1FsiB06t6XiebPYPpkqB9nYNNKiA8Z/cYWsym7wISq1sYSQ==} engines: {node: '>=10'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} @@ -1592,10 +1524,6 @@ packages: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - ws@8.21.0: resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} @@ -1611,26 +1539,14 @@ packages: 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'} - 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.3: - resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} - engines: {node: '>=12'} - snapshots: '@biomejs/biome@2.5.1': @@ -1668,14 +1584,6 @@ snapshots: '@biomejs/cli-win32-x64@2.5.1': optional: true - '@discordjs/builders@0.16.0': - dependencies: - '@sapphire/shapeshift': 3.9.7 - discord-api-types: 0.36.3 - fast-deep-equal: 3.1.3 - ts-mixer: 6.0.4 - tslib: 2.8.1 - '@discordjs/builders@1.14.1': dependencies: '@discordjs/formatters': 0.6.2 @@ -1686,8 +1594,6 @@ snapshots: ts-mixer: 6.0.4 tslib: 2.8.1 - '@discordjs/collection@0.7.0': {} - '@discordjs/collection@1.5.3': {} '@discordjs/collection@2.1.1': {} @@ -1997,11 +1903,6 @@ snapshots: '@sapphire/async-queue@1.5.5': {} - '@sapphire/shapeshift@3.9.7': - dependencies: - fast-deep-equal: 3.1.3 - lodash: 4.18.1 - '@sapphire/shapeshift@4.0.0': dependencies: fast-deep-equal: 3.1.3 @@ -2096,11 +1997,6 @@ snapshots: '@types/estree@1.0.9': {} - '@types/node-fetch@2.6.13': - dependencies: - '@types/node': 26.0.1 - form-data: 4.0.6 - '@types/node@26.0.1': dependencies: undici-types: 8.3.0 @@ -2224,12 +2120,6 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -2264,10 +2154,6 @@ snapshots: dijkstrajs@1.0.3: {} - discord-api-types@0.33.5: {} - - discord-api-types@0.36.3: {} - discord-api-types@0.38.49: {} discord.js-selfbot-v13@3.7.1: @@ -2323,22 +2209,6 @@ snapshots: - opusscript - utf-8-validate - discord.js@13.17.1: - dependencies: - '@discordjs/builders': 0.16.0 - '@discordjs/collection': 0.7.0 - '@sapphire/async-queue': 1.5.5 - '@types/node-fetch': 2.6.13 - '@types/ws': 8.18.1 - discord-api-types: 0.33.5 - form-data: 4.0.6 - node-fetch: 2.7.0 - ws: 8.21.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - discord.js@14.26.4: dependencies: '@discordjs/builders': 1.14.1 @@ -2358,11 +2228,6 @@ snapshots: - bufferutil - utf-8-validate - dts-bundle-generator@9.5.1: - dependencies: - typescript: 6.0.3 - yargs: 17.7.3 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2417,8 +2282,6 @@ snapshots: '@esbuild/win32-ia32': 0.27.7 '@esbuild/win32-x64': 0.27.7 - escalade@3.2.0: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 @@ -2621,10 +2484,6 @@ snapshots: nanoid@3.3.15: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - object-assign@4.1.1: {} obug@2.1.3: {} @@ -2828,8 +2687,6 @@ snapshots: dependencies: tldts: 7.4.5 - tr46@0.0.3: {} - tree-kill@1.2.2: {} ts-interface-checker@0.1.13: {} @@ -2915,8 +2772,6 @@ snapshots: transitivePeerDependencies: - msw - webidl-conversions@3.0.1: {} - werift-rtp@0.8.8: dependencies: '@minhducsun2002/leb128': 1.0.0 @@ -2925,11 +2780,6 @@ snapshots: buffer: 6.0.3 mp4box: 0.5.4 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-module@2.0.1: {} why-is-node-running@2.3.0: @@ -2943,25 +2793,15 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - ws@8.21.0: {} y18n@4.0.3: {} - y18n@5.0.8: {} - 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 @@ -2975,13 +2815,3 @@ snapshots: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 - - yargs@17.7.3: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 diff --git a/src/context.ts b/src/context.ts index df99bd7..69ef051 100644 --- a/src/context.ts +++ b/src/context.ts @@ -28,8 +28,14 @@ export type ContextSource = */ export class Context { constructor( - /** The owning Jishaku instance (config, client, task registry, REPL scope). */ - readonly jsk: Jishaku, + /** + * The owning Jishaku instance (config, client, task registry, REPL scope). + * `Jishaku`, not the bare (`AnyClient`-defaulted) `Jishaku`: `Jishaku`'s client type + * is generic per-instance (see jishaku.ts), and `any` absorbs whichever concrete type that + * instance was constructed with without needing a cast at every call site. + */ + // biome-ignore lint/suspicious/noExplicitAny: absorbs Jishaku for any concrete client type C. + readonly jsk: Jishaku, /** What triggered this command. */ readonly source: ContextSource, /** The resolved subcommand name (empty string for the bare `jsk` status command). */ diff --git a/src/jishaku.ts b/src/jishaku.ts index 8306a96..071e319 100644 --- a/src/jishaku.ts +++ b/src/jishaku.ts @@ -76,7 +76,15 @@ function resolveConfig(config: JishakuConfig): ResolvedConfig { * client.on('messageCreate', (m) => jsk.onMessageCreated(m)) * ``` */ -export class Jishaku { +// `client`/`onMessageCreated`/`onInteractionCreate` are generic — deliberately *unconstrained* +// (not `C extends AnyClient`) — so TypeScript infers the exact concrete type you pass in rather +// than checking it against (and narrowing it down to) the AnyClient/AnyMessage/AnyInteraction +// fallback. This is what makes v13, v14 and both selfbot forks all type-check correctly with +// full, accurate autocomplete: a constrained generic would still perform that assignability +// check at the boundary, which is exactly what breaks for an inlined/foreign declaration (see +// the module comment in types.ts). Internally these are cast back to the fallback types (or +// `any`) since djsk only ever duck-types them at runtime anyway. +export class Jishaku { readonly config: ResolvedConfig readonly owners: OwnerResolver private readonly scrubber: SecretScrubber @@ -92,7 +100,7 @@ export class Jishaku { private taskCounter = 0 constructor( - readonly client: AnyClient, + readonly client: C, config: JishakuConfig = {}, ) { this.config = resolveConfig(config) @@ -161,7 +169,7 @@ export class Jishaku { * Ignores messages that don't target the djsk root command or whose author * is not an owner. Never throws — command errors are reported to the channel. */ - async onMessageCreated(message: AnyMessage): Promise { + async onMessageCreated(message: M): Promise { // biome-ignore lint/suspicious/noExplicitAny: content/author are duck-typed across libraries. const raw = message as any const content: unknown = raw?.content @@ -175,7 +183,7 @@ export class Jishaku { if (!(await this.owners.isOwner(String(authorId)))) return const { name, rawArgs } = splitCommand(rest) - const source = { kind: 'message' as const, message } + const source = { kind: 'message' as const, message: raw as AnyMessage } if (name === '') { await this.run(new Context(this, source, '', ''), statusCommand) @@ -199,7 +207,7 @@ export class Jishaku { * plus the code-input modals that `js`/`sh` show instead of taking a string option. Ignores * anything else. Never throws — command errors are reported back through the interaction. */ - async onInteractionCreate(interaction: AnyInteraction): Promise { + async onInteractionCreate(interaction: I): Promise { // biome-ignore lint/suspicious/noExplicitAny: interaction shapes are duck-typed across libraries. const raw = interaction as any diff --git a/src/owners.ts b/src/owners.ts index 9e2491a..de21b06 100644 --- a/src/owners.ts +++ b/src/owners.ts @@ -1,5 +1,3 @@ -import type { AnyClient } from './types' - /** * Resolves and checks which users are allowed to use djsk. * @@ -14,7 +12,9 @@ export class OwnerResolver { private resolving: Promise> | null = null constructor( - private readonly client: AnyClient, + // `unknown`, not `AnyClient`: `Jishaku`'s client is generic (see jishaku.ts) so any concrete + // client type may flow in here — this is cast to `any` below regardless (duck-typed at runtime). + private readonly client: unknown, configOwners: string[] | null, ) { this.explicit = configOwners && configOwners.length > 0 ? new Set(configOwners) : null diff --git a/src/security.ts b/src/security.ts index 93fa8e7..baee64d 100644 --- a/src/security.ts +++ b/src/security.ts @@ -1,5 +1,3 @@ -import type { AnyClient } from './types' - /** * Best-effort secret redaction for security mode. * @@ -54,7 +52,9 @@ export class SecretScrubber { private readonly extraValues: string[] constructor( - private readonly client: AnyClient, + // `unknown`, not `AnyClient`: `Jishaku`'s client is generic (see jishaku.ts) so any concrete + // client type may flow in here — this is cast to `any` below regardless (duck-typed at runtime). + private readonly client: unknown, options: ScrubberOptions = {}, ) { this.patterns = [...BUILTIN_PATTERNS, ...(options.patterns ?? [])] diff --git a/src/types.ts b/src/types.ts index def7ba2..061ec3e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,38 +1,35 @@ -import type { - Client as ClientV13, - Interaction as InteractionV13, - Message as MessageV13, -} from 'discord.js-v13' -import type { - Client as ClientV14, - Interaction as InteractionV14, - Message as MessageV14, -} from 'discord.js-v14' +import type { Client, Interaction, Message } from 'discord.js' -// djsk is duck-typed at runtime — none of the AnyClient/AnyMessage/AnyInteraction unions below -// are enforced — but discord.js v13 and v14 have meaningfully different shapes, so a -// single-version type would silently show the wrong one for half of djsk's consumers. -// `discord.js-v13`/`discord.js-v14` are `discord.js@13`/`discord.js@14` installed under -// devDependency-only aliases (`npm:discord.js@...`), purely so both majors' types can be -// imported side by side without a version conflict. `pnpm build:types` (dts-bundle-generator, -// not tsup's own dts step — see tsup.config.ts) fully inlines both into the published .d.ts; -// neither alias name may appear in the output, since consumers won't have either installed -// under those names. +// djsk is duck-typed at runtime and works with discord.js v13/v14 and the selfbot forks +// (discord.js-selfbot-v13, discord.js-selfbot-youtsuho-v13) alike — none of these types are +// actually enforced. They exist purely for editor ergonomics, and only matter as *fallbacks*: +// `Jishaku` and its `onMessageCreated`/`onInteractionCreate` handlers are generic over the +// concrete client/message/interaction type you pass in (see jishaku.ts), so in practice your +// editor infers and shows the exact shape of whatever you actually installed — these are only +// used when that can't be inferred. // -// The selfbot forks (discord.js-selfbot-v13, discord.js-selfbot-youtsuho-v13) don't publish -// their own types and are v13-shaped, so they fall under the v13 side of these unions too. +// These must stay a plain external reference to the real `discord.js` package rather than a +// bundled/inlined type (as a previous version of this file did, importing `discord.js-v13`/ +// `discord.js-v14` aliases and fully inlining both into the published .d.ts): discord.js's +// classes carry private fields, which TypeScript treats as nominally typed — identical only +// when they originate from the exact same declaration. An inlined copy of `Client` is a +// *different* declaration from the real `Client` a consumer's own `discord.js` install +// resolves to, so passing their client into anything typed with the inlined version always +// fails to type-check, even on a matching version. A plain external import resolves against +// whatever `discord.js` is hoisted in the consumer's own node_modules, so it's always the +// exact same declaration — no mismatch possible. -/** A discord.js (or compatible fork) Client. See the module-level comment for why this is a union. */ -export type AnyClient = ClientV13 | ClientV14 +/** A discord.js (or compatible fork) Client. See the module-level comment for why this matters. */ +export type AnyClient = Client -/** A discord.js (or compatible fork) Message. See the module-level comment for why this is a union. */ -export type AnyMessage = MessageV13 | MessageV14 +/** A discord.js (or compatible fork) Message. See the module-level comment for why this matters. */ +export type AnyMessage = Message /** * A discord.js (or compatible fork) Interaction (chat input command or modal submit). - * See the module-level comment for why this is a union. + * See the module-level comment for why this matters. */ -export type AnyInteraction = InteractionV13 | InteractionV14 +export type AnyInteraction = Interaction /** Text decoding used when reading shell output. */ export type Encoding = 'UTF-8' | 'Shift_JIS' | (string & {}) diff --git a/tsup.config.ts b/tsup.config.ts index d81cad8..428e846 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -4,11 +4,7 @@ export default defineConfig([ { entry: { index: 'src/index.ts' }, format: ['esm', 'cjs'], - // Declarations are generated separately (`pnpm build:types`, via dts-bundle-generator) — - // tsup's own bundled dts generator (rollup-plugin-dts) can't parse discord.js v13's - // typings at all (crashes on its Mixin-based `extends SomeFn(Base)` class declarations), - // so it can't produce the AnyClient/AnyMessage/AnyInteraction v13 | v14 union in types.ts. - dts: false, + dts: true, clean: true, treeshake: true, target: 'es2022', From ca34564446af21fbb4dc9aedb592465892b18137 Mon Sep 17 00:00:00 2001 From: "otoneko." Date: Fri, 3 Jul 2026 23:37:56 +0900 Subject: [PATCH 2/2] fix: peerDependencies are optional --- package.json | 6 +++++- pnpm-lock.yaml | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 71a8ac3..37090f4 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,11 @@ "discord.js-selfbot-v13": "*", "discord.js-selfbot-youtsuho-v13": "*" }, + "peerDependenciesMeta": { + "discord.js": { "optional": true }, + "discord.js-selfbot-v13": { "optional": true }, + "discord.js-selfbot-youtsuho-v13": { "optional": true } + }, "dependencies": { "chalk": "^5.6.2", "commander": "^13.1.0", @@ -76,7 +81,6 @@ }, "devDependencies": { "@biomejs/biome": "^2.5.1", - "discord.js": "latest", "tsup": "^8.5.1", "typescript": "^6.0.3", "vitest": "^4.1.9" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c47f16e..773b3c6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: consola: specifier: ^3.4.2 version: 3.4.2 + discord.js: + specifier: ^14.0.0 || ^13.0.0 + version: 14.26.4 discord.js-selfbot-v13: specifier: '*' version: 3.7.1 @@ -30,9 +33,6 @@ importers: '@biomejs/biome': specifier: ^2.5.1 version: 2.5.1 - discord.js: - specifier: latest - version: 14.26.4 tsup: specifier: ^8.5.1 version: 8.5.1(postcss@8.5.16)(typescript@6.0.3)