eslint-plugin-discordjs 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +12 -0
- package/dist/index.cjs +861 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +859 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["noChoicesAndAutocomplete","noConflictingButtonProps","noDiscordLimitExceeded","noMixedMessageFormat","preferEphemeralFlag","preferV2Component","requireComponentsV2Flag","requiredOptionBeforeOptional","selectMenuMinExceedsMax","validCommandName"],"sources":["../src/createRule.ts","../../eslint-utils/dist/index.mjs","../src/rules/discord/no-choices-and-autocomplete.ts","../src/rules/discord/no-conflicting-button-props.ts","../src/rules/discord/no-discord-limit-exceeded.ts","../src/rules/discord/no-mixed-message-format.ts","../src/rules/discord/prefer-ephemeral-flag.ts","../src/rules/discord/prefer-v2-component.ts","../src/rules/discord/require-components-v2-flag.ts","../src/rules/discord/required-option-before-optional.ts","../src/rules/discord/select-menu-min-exceeds-max.ts","../src/rules/discord/valid-command-name.ts","../src/index.ts"],"sourcesContent":["import { ESLintUtils } from '@typescript-eslint/utils';\n\nexport const createRule = ESLintUtils.RuleCreator(\n (name) => `https://github.com/seedcord/seedcord/blob/next/packages/eslint-plugin-discordjs/docs/rules/${name}.md`\n);\n","import { AST_NODE_TYPES } from \"@typescript-eslint/utils\";\nimport { TypeFlags } from \"typescript\";\n\n//#region src/typeUtils.ts\nfunction isFromDiscordJs(symbol) {\n\tconst file = symbol?.declarations?.[0]?.getSourceFile().fileName;\n\treturn file !== void 0 && (file.includes(\"/discord.js/\") || file.includes(\"/@discordjs/\"));\n}\nfunction asClassOrInterface(type) {\n\tif (type.isClassOrInterface()) return type;\n\tconst target = type.target;\n\tif (target !== void 0 && target !== type && target.isClassOrInterface()) return target;\n}\nfunction walkBaseChain(checker, type, match) {\n\tconst seen = /* @__PURE__ */ new Set();\n\tconst stack = [type];\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === void 0 || seen.has(current)) continue;\n\t\tseen.add(current);\n\t\tif (current.isUnionOrIntersection()) {\n\t\t\tstack.push(...current.types);\n\t\t\tcontinue;\n\t\t}\n\t\tconst symbol = current.getSymbol();\n\t\tif (symbol !== void 0 && match(symbol)) return true;\n\t\tconst iface = asClassOrInterface(current);\n\t\tif (iface !== void 0) stack.push(...checker.getBaseTypes(iface));\n\t}\n\treturn false;\n}\nfunction extendsDjsType(checker, type, names) {\n\tconst wanted = typeof names === \"string\" ? new Set([names]) : names;\n\treturn walkBaseChain(checker, type, (symbol) => wanted.has(symbol.getName()) && isFromDiscordJs(symbol));\n}\nfunction booleanLiteralValue(checker, type) {\n\tif ((type.flags & TypeFlags.BooleanLiteral) === 0) return void 0;\n\treturn checker.typeToString(type) === \"true\";\n}\nfunction extendsSeedcordType(checker, type, names) {\n\tconst wanted = typeof names === \"string\" ? new Set([names]) : names;\n\treturn walkBaseChain(checker, type, (symbol) => wanted.has(symbol.getName()));\n}\n\n//#endregion\n//#region src/utils.ts\nfunction isSeedcordSource(source) {\n\treturn source === \"seedcord\" || source.startsWith(\"@seedcord/\");\n}\nfunction decoratorName(decorator) {\n\tconst expr = decorator.expression;\n\tif (expr.type === AST_NODE_TYPES.CallExpression && expr.callee.type === AST_NODE_TYPES.Identifier) return expr.callee.name;\n\tif (expr.type === AST_NODE_TYPES.Identifier) return expr.name;\n}\nfunction hasDecoratorNamed(node, names) {\n\treturn node.decorators.some((decorator) => {\n\t\tconst name = decoratorName(decorator);\n\t\treturn name !== void 0 && names.has(name);\n\t});\n}\nfunction forEachSeedcordImport(node, fn) {\n\tif (typeof node.source.value !== \"string\" || !isSeedcordSource(node.source.value)) return;\n\tfor (const spec of node.specifiers) {\n\t\tif (spec.type !== AST_NODE_TYPES.ImportSpecifier) continue;\n\t\tif (spec.imported.type !== AST_NODE_TYPES.Identifier) continue;\n\t\tfn(spec.imported.name, spec.local.name);\n\t}\n}\nfunction methodName(call) {\n\tconst { callee } = call;\n\tif (callee.type !== AST_NODE_TYPES.MemberExpression || callee.computed) return void 0;\n\tif (callee.property.type !== AST_NODE_TYPES.Identifier) return void 0;\n\treturn callee.property.name;\n}\nfunction isChainTop(node) {\n\tconst { parent } = node;\n\treturn parent.type !== AST_NODE_TYPES.MemberExpression || parent.object !== node;\n}\nfunction collectChain(top) {\n\tconst calls = [];\n\tlet current = top;\n\twhile (current.type === AST_NODE_TYPES.CallExpression && current.callee.type === AST_NODE_TYPES.MemberExpression) {\n\t\tcalls.push(current);\n\t\tcurrent = current.callee.object;\n\t}\n\treturn calls;\n}\nfunction chainRoot(top) {\n\tlet current = top;\n\twhile (current.type === AST_NODE_TYPES.CallExpression && current.callee.type === AST_NODE_TYPES.MemberExpression) current = current.callee.object;\n\treturn current;\n}\nfunction resolveConstInit(sourceCode, identifier) {\n\tconst variable = sourceCode.getScope(identifier).references.find((ref) => ref.identifier === identifier)?.resolved;\n\tconst definition = variable?.defs[0];\n\tif (definition?.node.type !== AST_NODE_TYPES.VariableDeclarator) return void 0;\n\tif (variable?.references.some((ref) => ref.isWrite() && !ref.init)) return void 0;\n\treturn definition.node.init ?? void 0;\n}\nfunction propertyKeyIs(prop, name) {\n\tif (prop.computed) return false;\n\tconst { key } = prop;\n\tif (key.type === AST_NODE_TYPES.Identifier) return key.name === name;\n\treturn key.value === name;\n}\nfunction getProperty(node, name) {\n\treturn node.properties.find((prop) => prop.type === AST_NODE_TYPES.Property && propertyKeyIs(prop, name));\n}\nfunction unwrapAssertions(expr) {\n\tlet current = expr;\n\twhile (current.type === AST_NODE_TYPES.TSAsExpression || current.type === AST_NODE_TYPES.TSTypeAssertion || current.type === AST_NODE_TYPES.TSSatisfiesExpression) current = current.expression;\n\treturn current;\n}\n\n//#endregion\n//#region src/componentsV2.ts\nconst V2_BUILDERS = new Set([\n\t\"ContainerBuilder\",\n\t\"SectionBuilder\",\n\t\"TextDisplayBuilder\",\n\t\"MediaGalleryBuilder\",\n\t\"FileBuilder\",\n\t\"SeparatorBuilder\",\n\t\"ThumbnailBuilder\"\n]);\nfunction isV2Type(type, checker) {\n\treturn extendsDjsType(checker, type, V2_BUILDERS);\n}\nfunction arrayHoldsV2(type, checker) {\n\tconst elementType = type?.getNumberIndexType();\n\treturn elementType !== void 0 && isV2Type(elementType, checker);\n}\nfunction componentsValueIsV2(value, services, checker) {\n\tif (value.type === AST_NODE_TYPES.ArrayExpression) return value.elements.some((element) => {\n\t\tif (element === null) return false;\n\t\tif (element.type === AST_NODE_TYPES.SpreadElement) return arrayHoldsV2(services.getTypeAtLocation(element.argument), checker);\n\t\treturn isV2Type(services.getTypeAtLocation(element), checker);\n\t});\n\treturn arrayHoldsV2(services.getTypeAtLocation(value), checker);\n}\nfunction hasV2Components(node, services, checker) {\n\tlet holdsV2 = false;\n\tfor (const prop of node.properties) if (prop.type === AST_NODE_TYPES.Property && propertyKeyIs(prop, \"components\")) holdsV2 = componentsValueIsV2(prop.value, services, checker);\n\telse if (prop.type === AST_NODE_TYPES.SpreadElement) {\n\t\tconst symbol = services.getTypeAtLocation(prop.argument).getProperty(\"components\");\n\t\tif (symbol !== void 0) holdsV2 = arrayHoldsV2(checker.getTypeOfSymbol(symbol), checker);\n\t}\n\treturn holdsV2;\n}\n\n//#endregion\nexport { booleanLiteralValue, chainRoot, collectChain, extendsDjsType, extendsSeedcordType, forEachSeedcordImport, getProperty, hasDecoratorNamed, hasV2Components, isChainTop, isFromDiscordJs, methodName, propertyKeyIs, resolveConstInit, unwrapAssertions };\n//# sourceMappingURL=index.mjs.map","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { booleanLiteralValue, extendsDjsType } from '@seedcord/eslint-utils';\nimport { chainRoot, collectChain, isChainTop, methodName } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\nconst OPTION_BUILDERS = new Set(['SlashCommandStringOption', 'SlashCommandIntegerOption', 'SlashCommandNumberOption']);\n\n// the last setAutocomplete call is the effective one. collectChain is outermost-first, so the first match is the last executed\nfunction autocompleteOn(\n calls: TSESTree.CallExpression[],\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): boolean {\n const last = calls.find((call) => methodName(call) === 'setAutocomplete');\n const arg = last?.arguments[0];\n if (arg === undefined) return false;\n if (arg.type === AST_NODE_TYPES.Literal) return arg.value === true;\n // a const flag's boolean literal type is its value\n return booleanLiteralValue(checker, services.getTypeAtLocation(arg)) === true;\n}\n\n// addChoices appends literal choices, setChoices replaces them\nfunction declaresChoices(calls: TSESTree.CallExpression[]): boolean {\n let has = false;\n // reversed to source order, so a later setChoices resets an earlier addChoices\n for (const call of [...calls].reverse()) {\n const name = methodName(call);\n if (name === 'addChoices') {\n if (call.arguments.some((arg) => arg.type !== AST_NODE_TYPES.SpreadElement)) has = true;\n } else if (name === 'setChoices') {\n has = call.arguments.some((arg) => {\n if (arg.type === AST_NODE_TYPES.SpreadElement) return false;\n if (arg.type === AST_NODE_TYPES.ArrayExpression) {\n return arg.elements.some((el) => el !== null && el.type !== AST_NODE_TYPES.SpreadElement);\n }\n return true;\n });\n }\n }\n return has;\n}\n\nexport default createRule({\n name: 'no-choices-and-autocomplete',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow both autocomplete and choices on the same slash option.'\n },\n messages: {\n bothSet:\n 'A slash option cannot enable autocomplete and declare choices at once. Building that throws a RangeError.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n CallExpression(node) {\n if (!isChainTop(node)) return;\n if (!extendsDjsType(checker, services.getTypeAtLocation(chainRoot(node)), OPTION_BUILDERS)) return;\n\n const calls = collectChain(node);\n if (autocompleteOn(calls, services, checker) && declaresChoices(calls)) {\n context.report({ node, messageId: 'bothSet' });\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType } from '@seedcord/eslint-utils';\nimport { chainRoot, collectChain, isChainTop, methodName } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\n\nconst BUTTON_STYLE_LINK = 5; // stable Discord wire value for a link button\n\nfunction setsLinkStyle(call: TSESTree.CallExpression, services: ParserServicesWithTypeInformation): boolean {\n if (methodName(call) !== 'setStyle') return false;\n const arg = call.arguments[0];\n if (arg === undefined) return false;\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === BUTTON_STYLE_LINK) return true;\n if (\n arg.type === AST_NODE_TYPES.MemberExpression &&\n arg.object.type === AST_NODE_TYPES.Identifier &&\n arg.object.name === 'ButtonStyle' &&\n arg.property.type === AST_NODE_TYPES.Identifier &&\n arg.property.name === 'Link'\n )\n return true;\n // a variable whose type resolves to the numeric literal ButtonStyle.Link\n const type = services.getTypeAtLocation(arg);\n return type.isNumberLiteral() && type.value === BUTTON_STYLE_LINK;\n}\n\nexport default createRule({\n name: 'no-conflicting-button-props',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow conflicting props on a button builder.'\n },\n messages: {\n idAndUrl: 'A button cannot set both a customId and a url.',\n linkWithCustomId: 'A link button uses a url and cannot have a customId.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n CallExpression(node) {\n if (!isChainTop(node)) return;\n if (!extendsDjsType(checker, services.getTypeAtLocation(chainRoot(node)), 'ButtonBuilder')) return;\n\n const calls = collectChain(node);\n const hasCustomId = calls.some((call) => methodName(call) === 'setCustomId');\n const hasUrl = calls.some((call) => methodName(call) === 'setURL');\n\n if (hasCustomId && hasUrl) {\n context.report({ node, messageId: 'idAndUrl' });\n } else if (hasCustomId && calls.some((call) => setsLinkStyle(call, services))) {\n context.report({ node, messageId: 'linkWithCustomId' });\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType } from '@seedcord/eslint-utils';\nimport { chainRoot, collectChain, isChainTop, methodName } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\ninterface Limit {\n builders: ReadonlySet<string>;\n addMethod: string;\n setMethod: string;\n cap: number;\n detail: string;\n}\n\nconst LIMITS: readonly Limit[] = [\n {\n builders: new Set(['ActionRowBuilder']),\n addMethod: 'addComponents',\n setMethod: 'setComponents',\n cap: 5,\n detail: 'An action row holds at most 5 components'\n },\n {\n builders: new Set(['StringSelectMenuBuilder']),\n addMethod: 'addOptions',\n setMethod: 'setOptions',\n cap: 25,\n detail: 'A select menu holds at most 25 options'\n },\n {\n builders: new Set(['EmbedBuilder']),\n addMethod: 'addFields',\n setMethod: 'setFields',\n cap: 25,\n detail: 'An embed holds at most 25 fields'\n },\n {\n builders: new Set(['SlashCommandStringOption', 'SlashCommandIntegerOption', 'SlashCommandNumberOption']),\n addMethod: 'addChoices',\n setMethod: 'setChoices',\n cap: 25,\n detail: 'A slash option holds at most 25 choices'\n }\n];\n\n// a fixed-arity tuple type (an as-const array) has a statically known length\nfunction tupleLength(type: ts.Type, checker: ts.TypeChecker): number | undefined {\n if (!checker.isTupleType(type)) return undefined;\n // justified: isTupleType narrows to a reference whose target is the tuple shape\n const reference = type as ts.TypeReference;\n const target = reference.target as ts.TupleType;\n const length = checker.getTypeArguments(reference).length;\n // an optional or rest element raises the argument count past minLength, so the arity is uncertain\n return target.minLength === length ? length : undefined;\n}\n\nfunction spreadCount(\n spread: TSESTree.SpreadElement,\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): number | undefined {\n return tupleLength(services.getTypeAtLocation(spread.argument), checker);\n}\n\n// the array length when every element is countable, spreads resolve through tuple arity\nfunction arrayLength(\n array: TSESTree.ArrayExpression,\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): number | undefined {\n let count = 0;\n for (const element of array.elements) {\n if (element?.type === AST_NODE_TYPES.SpreadElement) {\n const arity = spreadCount(element, services, checker);\n if (arity === undefined) return undefined;\n count += arity;\n } else {\n count += 1;\n }\n }\n return count;\n}\n\nfunction countStaticItems(\n calls: TSESTree.CallExpression[],\n limit: Limit,\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): number | undefined {\n let count = 0;\n let matched = false;\n // reversed to source order, so a later setMethod wins over earlier adds\n for (const call of [...calls].reverse()) {\n const name = methodName(call);\n if (name === limit.addMethod) {\n matched = true;\n for (const arg of call.arguments) {\n if (arg.type === AST_NODE_TYPES.SpreadElement) {\n const arity = spreadCount(arg, services, checker);\n if (arity === undefined) return undefined;\n count += arity;\n } else {\n count += 1;\n }\n }\n } else if (name === limit.setMethod) {\n matched = true;\n const arg = call.arguments[0];\n const length =\n arg?.type === AST_NODE_TYPES.ArrayExpression\n ? arrayLength(arg, services, checker)\n : arg !== undefined && arg.type !== AST_NODE_TYPES.SpreadElement\n ? tupleLength(services.getTypeAtLocation(arg), checker)\n : undefined;\n if (length === undefined) return undefined;\n count = length; // setMethod replaces, so this resets the count\n }\n }\n return matched ? count : undefined;\n}\n\nexport default createRule({\n name: 'no-discord-limit-exceeded',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow exceeding a Discord builder limit with a statically-known number of items.'\n },\n messages: {\n tooMany: '{{detail}}. This chain declares {{count}}.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n CallExpression(node) {\n if (!isChainTop(node)) return;\n\n const calls = collectChain(node);\n const methods = new Set(calls.map((call) => methodName(call)));\n // skip the type lookup when no capped method is on the chain\n if (!LIMITS.some((limit) => methods.has(limit.addMethod) || methods.has(limit.setMethod))) return;\n\n const type = services.getTypeAtLocation(chainRoot(node));\n const limit = LIMITS.find((entry) => extendsDjsType(checker, type, entry.builders));\n if (!limit) return;\n\n const count = countStaticItems(calls, limit, services, checker);\n if (count !== undefined && count > limit.cap) {\n context.report({ node, messageId: 'tooMany', data: { detail: limit.detail, count } });\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\nimport { SymbolFlags, TypeFlags } from 'typescript';\n\nimport { hasV2Components } from '@seedcord/eslint-utils';\nimport { createRule } from '../../createRule';\nimport { getProperty } from '@seedcord/eslint-utils';\n\nimport type { TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\n// a message carries content through these fields or through builder components, never both\nconst CONTENT_FIELDS = ['content', 'embeds', 'poll', 'stickers', 'sticker_ids'];\n\n// JSON serialization drops an undefined property, so the wire payload carries no such field\nfunction isDefinitelyUndefined(type: ts.Type): boolean {\n return (type.flags & TypeFlags.Undefined) !== 0;\n}\n\nexport default createRule({\n name: 'no-mixed-message-format',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow a message that mixes builder components with content, embeds, poll, or stickers.'\n },\n messages: {\n mixedFormat:\n 'A message cannot mix builder components with content, embeds, poll, or stickers. Discord rejects the payload.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n // the content side can also arrive through a spread of another object, so read the spread's type.\n // an optional field may be absent at runtime. only a required one is certainly set\n function spreadHasContent(node: TSESTree.ObjectExpression): boolean {\n for (const prop of node.properties) {\n if (prop.type !== AST_NODE_TYPES.SpreadElement) continue;\n const type = services.getTypeAtLocation(prop.argument);\n const carries = CONTENT_FIELDS.some((name) => {\n const symbol = type.getProperty(name);\n if (symbol === undefined || (symbol.flags & SymbolFlags.Optional) !== 0) return false;\n return !isDefinitelyUndefined(checker.getTypeOfSymbol(symbol));\n });\n if (carries) return true;\n }\n return false;\n }\n\n function hasContentField(node: TSESTree.ObjectExpression): boolean {\n const direct = CONTENT_FIELDS.some((name) => {\n const prop = getProperty(node, name);\n return prop !== undefined && !isDefinitelyUndefined(services.getTypeAtLocation(prop.value));\n });\n return direct || spreadHasContent(node);\n }\n\n return {\n ObjectExpression(node) {\n if (hasV2Components(node, services, checker) && hasContentField(node)) {\n context.report({ node, messageId: 'mixedFormat' });\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType } from '@seedcord/eslint-utils';\nimport { methodName, resolveConstInit } from '@seedcord/eslint-utils';\n\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\nconst REPLY_METHODS = new Set(['reply', 'deferReply', 'followUp']);\n\nfunction propertyName(property: TSESTree.ObjectLiteralElement): string | undefined {\n if (property.type !== AST_NODE_TYPES.Property || property.computed) return undefined;\n if (property.key.type === AST_NODE_TYPES.Identifier) return property.key.name;\n // a non-computed, non-identifier key is a string or number literal\n return typeof property.key.value === 'string' ? property.key.value : undefined;\n}\n\nfunction resolveOptions(\n sourceCode: TSESLint.SourceCode,\n arg: TSESTree.CallExpressionArgument | undefined\n): TSESTree.ObjectExpression | undefined {\n if (arg?.type === AST_NODE_TYPES.ObjectExpression) return arg;\n if (arg?.type !== AST_NODE_TYPES.Identifier) return undefined;\n const init = resolveConstInit(sourceCode, arg);\n return init?.type === AST_NODE_TYPES.ObjectExpression ? init : undefined;\n}\n\nfunction canReplaceEphemeral(\n ephemeral: TSESTree.Property,\n options: TSESTree.ObjectExpression,\n messageFlagsAlias: string | undefined\n): boolean {\n const hasFlags = options.properties.some((property) => propertyName(property) === 'flags');\n // a spread could already carry a flags key, so the autofix is skipped to avoid duplicating it\n const hasSpread = options.properties.some((property) => property.type === AST_NODE_TYPES.SpreadElement);\n const isTrue = ephemeral.value.type === AST_NODE_TYPES.Literal && ephemeral.value.value === true;\n return messageFlagsAlias !== undefined && !hasFlags && !hasSpread && isTrue;\n}\n\n// a reply method destructured off an interaction: `const { reply } = interaction; reply(...)`\nfunction destructuredReply(\n node: TSESTree.CallExpression,\n sourceCode: TSESLint.SourceCode\n): { name: string; init: TSESTree.Expression } | undefined {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) return undefined;\n const calleeId = node.callee;\n const variable = sourceCode.getScope(node).references.find((ref) => ref.identifier === calleeId)?.resolved;\n const def = variable?.defs[0];\n if (def?.node.type !== AST_NODE_TYPES.VariableDeclarator) return undefined;\n const { id: pattern, init } = def.node;\n if (pattern.type !== AST_NODE_TYPES.ObjectPattern || !init) return undefined;\n const prop = pattern.properties.find(\n (p): p is TSESTree.Property =>\n p.type === AST_NODE_TYPES.Property &&\n !p.computed &&\n p.key.type === AST_NODE_TYPES.Identifier &&\n p.value.type === AST_NODE_TYPES.Identifier &&\n p.value.name === calleeId.name\n );\n if (prop?.key.type !== AST_NODE_TYPES.Identifier) return undefined;\n return { name: prop.key.name, init };\n}\n\nexport default createRule({\n name: 'prefer-ephemeral-flag',\n meta: {\n type: 'suggestion',\n fixable: 'code',\n docs: {\n description: 'Disallow the deprecated ephemeral reply option in favor of MessageFlags.Ephemeral.'\n },\n messages: {\n deprecated: 'The ephemeral reply option is deprecated. Use flags: MessageFlags.Ephemeral.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n let messageFlagsAlias: string | undefined;\n\n return {\n ImportDeclaration(node) {\n if (node.source.value !== 'discord.js') return;\n for (const spec of node.specifiers) {\n if (\n spec.type === AST_NODE_TYPES.ImportSpecifier &&\n spec.imported.type === AST_NODE_TYPES.Identifier &&\n spec.imported.name === 'MessageFlags'\n ) {\n messageFlagsAlias = spec.local.name;\n }\n }\n },\n CallExpression(node) {\n let name: string | undefined;\n let receiverType: ts.Type | undefined;\n if (node.callee.type === AST_NODE_TYPES.MemberExpression) {\n name = methodName(node);\n receiverType = services.getTypeAtLocation(node.callee.object);\n } else {\n const reply = destructuredReply(node, context.sourceCode);\n name = reply?.name;\n receiverType = reply ? services.getTypeAtLocation(reply.init) : undefined;\n }\n if (name === undefined || !REPLY_METHODS.has(name) || receiverType === undefined) return;\n if (!extendsDjsType(checker, receiverType, 'BaseInteraction')) return;\n\n const options = resolveOptions(context.sourceCode, node.arguments[0]);\n if (options === undefined) return;\n\n const ephemeral = options.properties.find((property) => propertyName(property) === 'ephemeral');\n if (ephemeral?.type !== AST_NODE_TYPES.Property) return;\n\n const canFix = canReplaceEphemeral(ephemeral, options, messageFlagsAlias);\n context.report({\n node: ephemeral,\n messageId: 'deprecated',\n fix: canFix\n ? (fixer) => fixer.replaceText(ephemeral, `flags: ${messageFlagsAlias}.Ephemeral`)\n : null\n });\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType, extendsSeedcordType, isFromDiscordJs } from '@seedcord/eslint-utils';\n\nexport default createRule({\n name: 'prefer-v2-component',\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Prefer a components v2 layout over a legacy embed.'\n },\n messages: {\n preferV2: 'Prefer a components v2 layout (ContainerBuilder, TextDisplayBuilder) over an embed.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n NewExpression(node) {\n if (extendsDjsType(checker, services.getTypeAtLocation(node), 'EmbedBuilder')) {\n context.report({ node, messageId: 'preferV2' });\n }\n },\n // EmbedBuilder.from() is a static factory that returns an embed without `new`\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return;\n if (node.callee.property.type !== AST_NODE_TYPES.Identifier || node.callee.property.name !== 'from') {\n return;\n }\n if (extendsDjsType(checker, services.getTypeAtLocation(node.callee.object), 'EmbedBuilder')) {\n context.report({ node, messageId: 'preferV2' });\n }\n },\n // a seedcord embed component: a class whose .component resolves to EmbedBuilder through its generic\n ClassDeclaration(node) {\n if (!node.superClass || !node.id) return;\n\n const symbol = services.getSymbolAtLocation(node.id);\n if (!symbol) return;\n const classType = checker.getDeclaredTypeOfSymbol(symbol);\n if (!extendsSeedcordType(checker, classType, 'BuilderComponent')) return;\n\n const component = classType.getProperty('component');\n if (!component) return;\n\n const componentType = checker.getTypeOfSymbolAtLocation(\n component,\n services.esTreeNodeToTSNodeMap.get(node)\n );\n const componentSymbol = componentType.getSymbol();\n if (componentSymbol?.getName() === 'EmbedBuilder' && isFromDiscordJs(componentSymbol)) {\n context.report({ node: node.id, messageId: 'preferV2' });\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { hasV2Components } from '@seedcord/eslint-utils';\nimport { createRule } from '../../createRule';\nimport { isFromDiscordJs } from '@seedcord/eslint-utils';\nimport { propertyKeyIs, resolveConstInit } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\n// MessageFlags.IsComponentsV2, the stable Discord wire bit\nconst IS_COMPONENTS_V2 = 32_768;\n\ntype FlagState = 'present' | 'absent' | 'unknown';\n\n// the runtime value is one member of the union, so the flag is only determined when all members match\nfunction combine(states: FlagState[]): FlagState {\n const [first] = states;\n if (first === undefined) return 'unknown';\n return states.every((state) => state === first) ? first : 'unknown';\n}\n\nfunction bitState(value: number): FlagState {\n return (value & IS_COMPONENTS_V2) === 0 ? 'absent' : 'present';\n}\n\nfunction flagTypeState(type: ts.Type | undefined): FlagState {\n if (type === undefined) return 'unknown';\n if (type.isUnion()) return combine(type.types.map(flagTypeState));\n if (type.isNumberLiteral()) return bitState(type.value);\n if (type.isStringLiteral()) {\n if (type.value === 'IsComponentsV2') return 'present';\n // the `${bigint}` resolvable arm, e.g. flags: '32768'\n if (/^\\d+$/u.test(type.value)) return bitState(Number(type.value));\n return 'absent';\n }\n const element = type.getNumberIndexType();\n if (element !== undefined) return flagTypeState(element);\n // a non-literal type (a variable, a computed value, a MessageFlagsBitField) has no statically-known bits\n return 'unknown';\n}\n\nfunction applyBitwise(operator: string, left: number, right: number): number | undefined {\n switch (operator) {\n case '|': {\n return left | right;\n }\n case '&': {\n return left & right;\n }\n case '^': {\n return left ^ right;\n }\n case '<<': {\n return left << right;\n }\n case '>>': {\n return left >> right;\n }\n case '>>>': {\n return left >>> right;\n }\n default: {\n return undefined;\n }\n }\n}\n\n// the type checker widens a bitwise flag expression to `number`, so fold it from operands it still\n// resolves to literals (a numeric literal or an enum member)\nfunction foldToNumber(node: TSESTree.Node, services: ParserServicesWithTypeInformation): number | undefined {\n switch (node.type) {\n case AST_NODE_TYPES.Literal: {\n return typeof node.value === 'number' ? node.value : undefined;\n }\n case AST_NODE_TYPES.TSAsExpression: {\n return foldToNumber(node.expression, services);\n }\n case AST_NODE_TYPES.UnaryExpression: {\n const value = foldToNumber(node.argument, services);\n if (value === undefined) return undefined;\n if (node.operator === '-') return -value;\n if (node.operator === '~') return ~value;\n if (node.operator === '+') return value;\n return undefined;\n }\n case AST_NODE_TYPES.BinaryExpression: {\n const left = foldToNumber(node.left, services);\n const right = foldToNumber(node.right, services);\n if (left === undefined || right === undefined) return undefined;\n return applyBitwise(node.operator, left, right);\n }\n case AST_NODE_TYPES.Identifier:\n case AST_NODE_TYPES.MemberExpression: {\n const type = services.getTypeAtLocation(node);\n return type.isNumberLiteral() ? type.value : undefined;\n }\n default: {\n return undefined;\n }\n }\n}\n\nfunction elementState(node: TSESTree.Node, services: ParserServicesWithTypeInformation): FlagState {\n const folded = foldToNumber(node, services);\n if (folded !== undefined) return bitState(folded);\n return flagTypeState(services.getTypeAtLocation(node));\n}\n\nfunction flagValueState(value: TSESTree.Node, services: ParserServicesWithTypeInformation): FlagState {\n if (value.type === AST_NODE_TYPES.ArrayExpression) {\n const states = new Set(\n value.elements.map((element): FlagState => {\n if (element === null) return 'absent';\n if (element.type === AST_NODE_TYPES.SpreadElement) {\n return flagTypeState(services.getTypeAtLocation(element.argument).getNumberIndexType());\n }\n return elementState(element, services);\n })\n );\n if (states.has('present')) return 'present';\n return states.has('unknown') ? 'unknown' : 'absent';\n }\n return elementState(value, services);\n}\n\n// object properties apply left to right, so the last flags contributor (a key or a spread) wins\nfunction flagState(\n node: TSESTree.ObjectExpression,\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): FlagState {\n let state: FlagState = 'absent';\n for (const prop of node.properties) {\n if (prop.type === AST_NODE_TYPES.Property && propertyKeyIs(prop, 'flags')) {\n state = flagValueState(prop.value, services);\n } else if (prop.type === AST_NODE_TYPES.SpreadElement) {\n const symbol = services.getTypeAtLocation(prop.argument).getProperty('flags');\n if (symbol !== undefined) state = flagTypeState(checker.getTypeOfSymbol(symbol));\n }\n }\n return state;\n}\n\n// a discord.js message-options type declares both a components list and a flags field\nfunction isMessageOptionsType(type: ts.Type): boolean {\n if (type.isUnion()) return type.types.some(isMessageOptionsType);\n const components = type.getProperty('components');\n const flags = type.getProperty('flags');\n return components !== undefined && flags !== undefined && isFromDiscordJs(components) && isFromDiscordJs(flags);\n}\n\nexport default createRule({\n name: 'require-components-v2-flag',\n meta: {\n type: 'problem',\n docs: {\n description: 'Require the IsComponentsV2 flag on a message that uses v2 builder components.'\n },\n messages: {\n missingFlag:\n 'A message using v2 builder components must set flags: MessageFlags.IsComponentsV2. Discord rejects the payload otherwise.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n const reportedInits = new Set<TSESTree.ObjectExpression>();\n\n function payloadViolates(node: TSESTree.ObjectExpression): boolean {\n return hasV2Components(node, services, checker) && flagState(node, services, checker) === 'absent';\n }\n\n function contextualType(node: TSESTree.Identifier | TSESTree.ObjectExpression): ts.Type | undefined {\n // justified: the node map widens an identifier to declaration kinds it cannot be in value position\n return checker.getContextualType(services.esTreeNodeToTSNodeMap.get(node) as ts.Expression);\n }\n\n return {\n ObjectExpression(node) {\n if (!payloadViolates(node)) return;\n const contextual = contextualType(node);\n if (contextual === undefined || !isMessageOptionsType(contextual)) return;\n\n context.report({ node, messageId: 'missingFlag' });\n },\n // an unannotated payload variable has no contextual type at its declaration, so it\n // resolves at the call site\n CallExpression(node) {\n for (const arg of node.arguments) {\n if (arg.type !== AST_NODE_TYPES.Identifier) continue;\n const init = resolveConstInit(context.sourceCode, arg);\n if (init?.type !== AST_NODE_TYPES.ObjectExpression) continue;\n // an annotated declaration is already reported at the object literal\n if (contextualType(init) !== undefined) continue;\n // a payload reused across sends is one fix at one declaration\n if (reportedInits.has(init)) continue;\n const contextual = contextualType(arg);\n if (contextual === undefined || !isMessageOptionsType(contextual)) continue;\n if (payloadViolates(init)) {\n reportedInits.add(init);\n context.report({ node: init, messageId: 'missingFlag' });\n }\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { booleanLiteralValue, extendsDjsType } from '@seedcord/eslint-utils';\nimport { chainRoot, collectChain, isChainTop, methodName } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\nimport type * as ts from 'typescript';\n\nconst SLASH_COMMAND_BUILDERS = new Set(['SlashCommandBuilder', 'SlashCommandSubcommandBuilder']);\n\nconst ADD_OPTION = new Set([\n 'addStringOption',\n 'addIntegerOption',\n 'addBooleanOption',\n 'addUserOption',\n 'addChannelOption',\n 'addRoleOption',\n 'addMentionableOption',\n 'addNumberOption',\n 'addAttachmentOption'\n]);\n\ntype OptionState = 'required' | 'optional' | 'unknown';\n\n// the option-builder expression a callback returns: its expression body, or the return of a block body\nfunction optionChain(callback: TSESTree.CallExpressionArgument | undefined): TSESTree.Expression | undefined {\n if (\n callback?.type !== AST_NODE_TYPES.ArrowFunctionExpression &&\n callback?.type !== AST_NODE_TYPES.FunctionExpression\n ) {\n return undefined;\n }\n if (callback.body.type !== AST_NODE_TYPES.BlockStatement) return callback.body;\n for (const statement of callback.body.body) {\n if (statement.type === AST_NODE_TYPES.ReturnStatement) return statement.argument ?? undefined;\n }\n return undefined;\n}\n\nfunction optionRequiredState(\n callback: TSESTree.CallExpressionArgument | undefined,\n services: ParserServicesWithTypeInformation,\n checker: ts.TypeChecker\n): OptionState {\n const chain = optionChain(callback);\n if (chain?.type !== AST_NODE_TYPES.CallExpression) return 'unknown';\n\n const setRequired = collectChain(chain).find((call) => methodName(call) === 'setRequired');\n if (!setRequired) return 'optional';\n\n const arg = setRequired.arguments[0];\n if (arg?.type === AST_NODE_TYPES.Literal && typeof arg.value === 'boolean') {\n return arg.value ? 'required' : 'optional';\n }\n if (arg === undefined || arg.type === AST_NODE_TYPES.SpreadElement) return 'unknown';\n // a const flag's boolean literal type is its value\n const value = booleanLiteralValue(checker, services.getTypeAtLocation(arg));\n if (value === undefined) return 'unknown';\n return value ? 'required' : 'optional';\n}\n\nexport default createRule({\n name: 'required-option-before-optional',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow a required slash option after an optional one.'\n },\n messages: {\n outOfOrder: 'A required slash option cannot come after an optional one.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n CallExpression(node) {\n if (!isChainTop(node)) return;\n if (!extendsDjsType(checker, services.getTypeAtLocation(chainRoot(node)), SLASH_COMMAND_BUILDERS))\n return;\n\n // collectChain is outermost-first, reverse to source order\n const options = collectChain(node)\n .filter((call) => ADD_OPTION.has(methodName(call) ?? ''))\n .reverse()\n .map((call) => ({ call, state: optionRequiredState(call.arguments[0], services, checker) }));\n if (options.length < 2) return;\n if (options.some((option) => option.state === 'unknown')) return;\n\n let seenOptional = false;\n for (const { call, state } of options) {\n if (state === 'optional') {\n seenOptional = true;\n } else if (seenOptional) {\n // so squiggle lands on the offending option\n const target =\n call.callee.type === AST_NODE_TYPES.MemberExpression ? call.callee.property : call;\n context.report({ node: target, messageId: 'outOfOrder' });\n return;\n }\n }\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType } from '@seedcord/eslint-utils';\nimport { chainRoot, collectChain, isChainTop, methodName, unwrapAssertions } from '@seedcord/eslint-utils';\n\nimport type { ParserServicesWithTypeInformation, TSESTree } from '@typescript-eslint/utils';\n\n// collectChain is outermost-first, so the first match is the last call executed, and that one wins\nfunction lastCall(calls: TSESTree.CallExpression[], name: string): TSESTree.CallExpression | undefined {\n return calls.find((call) => methodName(call) === name);\n}\n\nfunction staticNumber(\n arg: TSESTree.CallExpressionArgument | undefined,\n services: ParserServicesWithTypeInformation\n): number | undefined {\n if (arg === undefined || arg.type === AST_NODE_TYPES.SpreadElement) return undefined;\n // a cast only changes the checker's view, the literal behind it is the runtime value\n const target = unwrapAssertions(arg);\n if (target.type === AST_NODE_TYPES.Literal && typeof target.value === 'number') return target.value;\n // a const bound resolves through its number-literal type\n const type = services.getTypeAtLocation(target);\n return type.isNumberLiteral() ? type.value : undefined;\n}\n\nexport default createRule({\n name: 'select-menu-min-exceeds-max',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow a select menu whose minimum selections exceed its maximum.'\n },\n messages: {\n minOverMax: 'setMinValues({{min}}) is greater than setMaxValues({{max}}). Discord rejects the select menu.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return {\n CallExpression(node) {\n if (!isChainTop(node)) return;\n\n const calls = collectChain(node);\n // both setters must be on the chain before the type lookup is worth paying for\n const minCall = lastCall(calls, 'setMinValues');\n const maxCall = lastCall(calls, 'setMaxValues');\n if (minCall === undefined || maxCall === undefined) return;\n\n if (!extendsDjsType(checker, services.getTypeAtLocation(chainRoot(node)), 'BaseSelectMenuBuilder')) {\n return;\n }\n\n const min = staticNumber(minCall.arguments[0], services);\n const max = staticNumber(maxCall.arguments[0], services);\n if (min === undefined || max === undefined || min <= max) return;\n\n // so the squiggle lands on the offending setter\n const target =\n minCall.callee.type === AST_NODE_TYPES.MemberExpression ? minCall.callee.property : minCall;\n context.report({ node: target, messageId: 'minOverMax', data: { min, max } });\n }\n };\n }\n});\n","import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils';\n\nimport { createRule } from '../../createRule';\nimport { extendsDjsType } from '@seedcord/eslint-utils';\nimport { methodName } from '@seedcord/eslint-utils';\n\nimport type { TSESTree } from '@typescript-eslint/utils';\n\n// the discord.js slash command and option builders, all requiring a lowercase chat-input name\nconst SLASH_BUILDERS = new Set([\n 'SlashCommandBuilder',\n 'SlashCommandSubcommandBuilder',\n 'SlashCommandSubcommandGroupBuilder',\n 'SlashCommandStringOption',\n 'SlashCommandIntegerOption',\n 'SlashCommandNumberOption',\n 'SlashCommandBooleanOption',\n 'SlashCommandUserOption',\n 'SlashCommandChannelOption',\n 'SlashCommandRoleOption',\n 'SlashCommandMentionableOption',\n 'SlashCommandAttachmentOption'\n]);\n\n// mirrors Discord's chat-input name character rule (\\p{Ll} already excludes uppercase)\nfunction isValidChatInputName(name: string): boolean {\n return /^[\\p{Ll}\\p{Lm}\\p{Lo}\\p{N}\\p{sc=Devanagari}\\p{sc=Thai}_-]{1,32}$/u.test(name);\n}\n\nfunction staticName(arg: TSESTree.CallExpressionArgument): string | undefined {\n if (arg.type === AST_NODE_TYPES.Literal && typeof arg.value === 'string') return arg.value;\n if (arg.type === AST_NODE_TYPES.TemplateLiteral && arg.expressions.length === 0) {\n return arg.quasis[0]?.value.cooked ?? undefined;\n }\n return undefined;\n}\n\nexport default createRule({\n name: 'valid-command-name',\n meta: {\n type: 'problem',\n docs: {\n description: 'Enforce Discord chat-input name rules on slash command and option names.'\n },\n messages: {\n invalidName:\n 'This name is not a valid chat-input name. Use lowercase letters, digits, hyphens, or underscores, 1 to 32 characters.'\n },\n schema: []\n },\n defaultOptions: [],\n create(context) {\n const services = ESLintUtils.getParserServices(context);\n\n return {\n CallExpression(node) {\n if (methodName(node) !== 'setName') return;\n const arg = node.arguments[0];\n if (arg === undefined) return;\n let name = staticName(arg);\n // a const string's literal type is its value\n if (\n name === undefined &&\n (arg.type === AST_NODE_TYPES.Identifier || arg.type === AST_NODE_TYPES.MemberExpression)\n ) {\n const argType = services.getTypeAtLocation(arg);\n if (argType.isStringLiteral()) name = argType.value;\n }\n if (name === undefined || isValidChatInputName(name)) return;\n\n // a context menu name allows any case, so restrict the check to the discord.js slash builders\n if (node.callee.type !== AST_NODE_TYPES.MemberExpression) return;\n const checker = services.program.getTypeChecker();\n const receiverType = services.getTypeAtLocation(node.callee.object);\n if (!extendsDjsType(checker, receiverType, SLASH_BUILDERS)) return;\n\n context.report({ node: arg, messageId: 'invalidName' });\n }\n };\n }\n});\n","import noChoicesAndAutocomplete from './rules/discord/no-choices-and-autocomplete';\nimport noConflictingButtonProps from './rules/discord/no-conflicting-button-props';\nimport noDiscordLimitExceeded from './rules/discord/no-discord-limit-exceeded';\nimport noMixedMessageFormat from './rules/discord/no-mixed-message-format';\nimport preferEphemeralFlag from './rules/discord/prefer-ephemeral-flag';\nimport preferV2Component from './rules/discord/prefer-v2-component';\nimport requireComponentsV2Flag from './rules/discord/require-components-v2-flag';\nimport requiredOptionBeforeOptional from './rules/discord/required-option-before-optional';\nimport selectMenuMinExceedsMax from './rules/discord/select-menu-min-exceeds-max';\nimport validCommandName from './rules/discord/valid-command-name';\n\nimport type { TSESLint } from '@typescript-eslint/utils';\n\nconst rules = {\n 'no-choices-and-autocomplete': noChoicesAndAutocomplete,\n 'no-conflicting-button-props': noConflictingButtonProps,\n 'no-discord-limit-exceeded': noDiscordLimitExceeded,\n 'no-mixed-message-format': noMixedMessageFormat,\n 'prefer-ephemeral-flag': preferEphemeralFlag,\n 'prefer-v2-component': preferV2Component,\n 'require-components-v2-flag': requireComponentsV2Flag,\n 'required-option-before-optional': requiredOptionBeforeOptional,\n 'select-menu-min-exceeds-max': selectMenuMinExceedsMax,\n 'valid-command-name': validCommandName\n} satisfies Record<string, TSESLint.RuleModule<string, readonly unknown[]>>;\n\nconst plugin: TSESLint.FlatConfig.Plugin = {\n meta: { name: 'eslint-plugin-discordjs', version: process.env.PACKAGE_VERSION ?? '0.0.0' },\n rules\n};\n\n// prefer-* rules are style choices, so they warn\nconst WARN_RULES = new Set(['prefer-ephemeral-flag', 'prefer-v2-component']);\n\nconst presetRules: NonNullable<TSESLint.FlatConfig.Config['rules']> = {};\nfor (const name of Object.keys(rules)) {\n presetRules[`discordjs/${name}`] = WARN_RULES.has(name) ? 'warn' : 'error';\n}\n\nexport const recommended: TSESLint.FlatConfig.Config = {\n plugins: { discordjs: plugin },\n rules: presetRules\n};\n\nplugin.configs = { recommended };\n\nexport default plugin;\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-discordjs",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "ESLint rules for discord.js bots",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/seedcord/seedcord.git",
|
|
9
|
+
"directory": "packages/eslint-plugin-discordjs"
|
|
10
|
+
},
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.mts",
|
|
16
|
+
"default": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/index.d.cts",
|
|
20
|
+
"default": "./dist/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"package.json",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsdown",
|
|
32
|
+
"clean": "rm -rf dist",
|
|
33
|
+
"lint": "eslint 'src/**/*.{ts,tsx}' 'tests/**/*.{ts,tsx}' --cache",
|
|
34
|
+
"lint:fix": "eslint 'src/**/*.{ts,tsx}' 'tests/**/*.{ts,tsx}' --fix --cache",
|
|
35
|
+
"fmt": "prettier --write 'src/**/*.{ts,tsx,json,md}' 'tests/**/*.{ts,tsx,json,md}' --cache",
|
|
36
|
+
"fmt:check": "prettier --check 'src/**/*.{ts,tsx,json,md}' 'tests/**/*.{ts,tsx,json,md}' --cache",
|
|
37
|
+
"tc": "tsgo --noEmit",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest dev",
|
|
40
|
+
"coverage": "vitest run --coverage"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
44
|
+
"typescript": "catalog:peer"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@typescript-eslint/utils": "catalog:eslint"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@seedcord/eslint-config-base": "workspace:*",
|
|
51
|
+
"@seedcord/eslint-utils": "workspace:*",
|
|
52
|
+
"@seedcord/tsconfig": "workspace:*",
|
|
53
|
+
"@seedcord/tsdown-config": "workspace:*",
|
|
54
|
+
"@typescript-eslint/rule-tester": "catalog:eslint",
|
|
55
|
+
"dedent": "catalog:test",
|
|
56
|
+
"discord.js": "catalog:peer",
|
|
57
|
+
"eslint": "catalog:eslint"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public",
|
|
61
|
+
"provenance": true
|
|
62
|
+
}
|
|
63
|
+
}
|