Documentation
¶
Overview ¶
Package config loads scripts/devbase.yaml, the per-repo configuration file consulted by devbase lint graphql for exclude patterns and per-rule severity/option overrides.
Index ¶
Constants ¶
const ( // RuleUniqueDirectiveNames requires directive definitions to have // unique names. RuleUniqueDirectiveNames = "unique-directive-names" // RuleUniqueFieldDefinitionNames requires fields within a type to // have unique names. RuleUniqueFieldDefinitionNames = "unique-field-definition-names" // RuleUniqueOperationTypes requires at most one query, mutation, // and subscription root type. RuleUniqueOperationTypes = "unique-operation-types" // RuleUniqueTypeNames requires type definitions to have unique // names. RuleUniqueTypeNames = "unique-type-names" // RuleKnownArgumentNames requires arguments to be defined in the // schema. RuleKnownArgumentNames = "known-argument-names" // RuleKnownDirectives requires directives to be defined and used // in a valid location. RuleKnownDirectives = "known-directives" // RuleKnownTypeNames requires referenced types to exist in the // schema. RuleKnownTypeNames = "known-type-names" // RuleProvidedRequiredArguments requires required arguments to be // provided. RuleProvidedRequiredArguments = "provided-required-arguments" // RuleLoneSchemaDefinition allows at most one schema definition. RuleLoneSchemaDefinition = "lone-schema-definition" // RuleUniqueEnumValueNames requires enum values within an enum to // have unique names. RuleUniqueEnumValueNames = "unique-enum-value-names" )
Names of the 10 Tier 1 rules: spec validations gqlparser performs for free while parsing SDL. Named as constants so internal/graphql/lint can tag violations with the same identifiers this package validates against.
RuleUniqueEnumValueNames belongs here, not among the gap-fill rules in internal/graphql/lint, because the gqlparser/v2 version pinned in go.mod already rejects a duplicate enum value on its own, the same way it already rejects a duplicate field name for RuleUniqueFieldDefinitionNames -- no custom code needed.
const ( // RuleUniqueDirectiveNamesPerLocation requires a non-repeatable // directive to appear at most once per location in SDL. RuleUniqueDirectiveNamesPerLocation = "unique-directive-names-per-location" // RulePossibleTypeExtension requires a type extension to reference // a type that is actually defined somewhere. RulePossibleTypeExtension = "possible-type-extension" )
Names of the 2 remaining Tier 2 gap-fill rules: gqlparser partially covers each, but a custom pass is still needed to fill the gap. Unlike the Tier 1 rules, scripts/devbase.yaml may override their severity.
const ( // RuleRequireDescription requires a description on the kinds of // definition its options enable it for. RuleRequireDescription = "require-description" // RuleDescriptionStyle requires every description in a schema to // use the same quoting style: inline "..." or block """...""", // per its "style" option. RuleDescriptionStyle = "description-style" // RuleNoHashtagDescription forbids a "#" comment immediately // preceding a definition, field, argument, or enum value, in favor // of a "..." or """...""" description. RuleNoHashtagDescription = "no-hashtag-description" // RuleRequireDeprecationReason requires every applied @deprecated // directive to have a non-empty "reason" argument. RuleRequireDeprecationReason = "require-deprecation-reason" // RuleRequireDeprecationDate requires every applied @deprecated // directive to have a valid, not-yet-passed deletion date, per its // "argumentName" option (default "deletionDate"). RuleRequireDeprecationDate = "require-deprecation-date" // RuleNoTypenamePrefix forbids a field on an object or interface // type from starting with that type's own name. RuleNoTypenamePrefix = "no-typename-prefix" // RuleNamingConvention requires names to follow the casing, // prefix/suffix, and underscore conventions its options configure // per kind of definition. RuleNamingConvention = "naming-convention" // RuleNoCaseInsensitiveEnumValuesDuplicates forbids two enum values // on the same enum whose names differ only by casing. RuleNoCaseInsensitiveEnumValuesDuplicates = "no-case-insensitive-enum-values-duplicates" // RuleAlphabetize requires alphabetical order among the fields, // enum values, and/or arguments its "fields", "values", and // "arguments" options select. RuleAlphabetize = "alphabetize" // RuleNoUnreachableTypes forbids a type or directive definition // that no root operation type's fields can ever reach. RuleNoUnreachableTypes = "no-unreachable-types" )
Names of all 10 Tier 3 custom style/convention rules. Unlike Tier 1 and Tier 2, no part of a Tier 3 rule is enforced by gqlparser -- each is entirely custom Go code. Like the Tier 2 gap-fill rules above, a Tier 3 rule never runs unless scripts/devbase.yaml gives it a severity other than SeverityOff -- see Lint.Enabled. Each rule's options (for example require-description's "types" and "FieldDefinition" keys, or require-deprecation-date's "argumentName") are read from Rule.Options by internal/graphql/lint, not validated here -- this package treats every rule's options as opaque, leaving their shape to the rule implementation.
Variables ¶
var ErrInvalidRule = errors.New("invalid rule config")
ErrInvalidRule is wrapped by errors returned when a rule entry in scripts/devbase.yaml is neither the short form (a severity scalar) nor the long form (a [severity, options] sequence), or names an unknown severity.
var ErrTier1RuleNotConfigurable = errors.New("tier 1 rule severity cannot be overridden")
ErrTier1RuleNotConfigurable is wrapped by the error returned when scripts/devbase.yaml overrides a Tier 1 rule's severity. Tier 1 rules are enforced by gqlparser while parsing SDL, always at "error" severity, and cannot be turned off or downgraded.
Functions ¶
func Tier1RuleNames ¶
func Tier1RuleNames() []string
Tier1RuleNames returns the 10 Tier 1 rule names above, in the order they are declared.
Types ¶
type Lint ¶
type Lint struct {
// Exclude is a list of glob patterns for files to skip, relative
// to the directory Load found scripts/devbase.yaml in.
Exclude []string `yaml:"exclude"`
// Rules overrides the severity (and, for some rules, options) of
// individual lint rules, keyed by rule name. Tier 1 rules always
// stay at "error" (gqlparser enforces them unconditionally, and
// this map can never target one -- see ErrTier1RuleNotConfigurable).
// Every other rule absent from this map, or explicitly set to
// SeverityOff, does not run at all -- matching @graphql-eslint's own
// behavior, where a rule is inert until a config opts into it.
Rules map[string]Rule `yaml:"rules"`
// Federation, if set, is the Apollo Federation subgraph spec
// version (for example "v2.3") this repo's own schema links
// against via `extend schema @link(url: "...", import: [...])`.
// See internal/graphql/lint/federation.go for the supported
// versions and directives, and how a mismatched or unrecognized
// import is reported.
Federation string `yaml:"federation"`
// Scalars lists custom scalar type names that are registered
// outside this repo's *.graphql files -- for example, at runtime
// in application code -- and so are never declared via `scalar X`
// SDL. Each name is merged into the schema as a bare `scalar X`
// declaration.
Scalars []string `yaml:"scalars"`
}
Lint is the graphql.lint section of scripts/devbase.yaml.
func Load ¶
Load discovers and parses scripts/devbase.yaml for the repository containing startDir, and returns the directory it was found in. Load walks up from startDir, checking each directory for scripts/devbase.yaml, until either the file is found or the enclosing git repository's top-level directory is reached (whichever comes first); the walk never crosses git repository boundaries.
Callers should resolve Lint.Exclude patterns relative to the returned directory, not the process's working directory -- matching how ESLint, Biome, and Oxlint resolve their own ignore patterns relative to the config file rather than cwd.
If no config file is found, Load returns the built-in defaults (no excludes, no rule overrides, so every Tier 1 rule stays at "error" and every other rule stays off) alongside an empty directory.
func (*Lint) Enabled ¶
Enabled reports whether the rule should run at all. A Tier 2 or Tier 3 rule is enabled only once scripts/devbase.yaml gives it a severity other than SeverityOff -- it does not run by default, matching @graphql-eslint's own behavior of a rule staying inert until a config opts into it. c may be nil (no config file found), in which case every rule this method is asked about is disabled.
This method is never consulted for Tier 1 rules: gqlparser enforces them unconditionally while parsing SDL, so Files runs them regardless of any config.
func (*Lint) MergeExcludes ¶
MergeExcludes returns the config's exclude patterns extended with extra patterns, e.g. from repeatable --exclude CLI flags. The config file's list is always kept, never replaced.
func (*Lint) Options ¶
Options returns rule's Rule.Options, or nil if c is nil or has no override for rule -- the rule's options are opaque to this package, which leaves their shape to the rule implementation.
func (*Lint) SeverityOf ¶
SeverityOf resolves the severity that applies to a violation tagged with rule. A Tier 2/3 rule present in c.Rules is always configured to SeverityWarn or SeverityError -- Enabled has already ruled out SeverityOff, since a rule at that severity never produces a violation -- so its configured severity is used directly. Every other rule -- a Tier 1 rule, which scripts/devbase.yaml can never override, or an unclassified gqlparser violation -- defaults to SeverityError. c may be nil (no config file found), in which case every rule defaults to SeverityError.
type Rule ¶
type Rule struct {
// Severity overrides the rule's default severity.
Severity Severity
// Options carries rule-specific options from the long form. It is
// nil when the short form was used.
Options map[string]any
}
Rule is the per-rule override for a single lint rule. It accepts two YAML shapes:
# Short form: severity only. rule-name: warn # Long form: severity plus rule-specific options. rule-name: - error - someOption: true