@sanity/schema-lint 0.0.1 → 0.0.3
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/dist/index.cjs +640 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +133 -0
- package/dist/testing.cjs +18530 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +81 -0
- package/dist/types-C3OVyCP6.d.cts +121 -0
- package/package.json +7 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/linter.ts","../src/rules/missing-define-type.ts","../src/rules/missing-define-field.ts","../src/rules/missing-icon.ts","../src/rules/missing-title.ts","../src/rules/missing-description.ts","../src/rules/presentation-field-name.ts","../src/rules/boolean-instead-of-list.ts","../src/rules/missing-slug-source.ts","../src/rules/missing-required-validation.ts","../src/rules/reserved-field-name.ts","../src/rules/array-missing-constraints.ts","../src/rules/heading-level-in-schema.ts","../src/rules/unnecessary-reference.ts","../src/rules/index.ts"],"sourcesContent":["// Types\nexport type {\n SchemaField,\n SchemaType,\n SchemaRule,\n SchemaRuleContext,\n SchemaRuleConfig,\n SchemaLinterConfig,\n} from './types'\n\n// Linter\nexport { lint, lintSchemas } from './linter'\nexport type { LintOptions, LintResult } from './linter'\n\n// Rules\nexport { rules } from './rules'\nexport * from './rules'\n","import type { Finding, Severity } from '@sanity/lint-core'\nimport type { SchemaType, SchemaRule, SchemaLinterConfig, SchemaRuleContext } from './types'\n\nexport interface LintOptions {\n /** Specific rules to run (if not provided, runs all) */\n rules?: SchemaRule[]\n /** Configuration for rules */\n config?: SchemaLinterConfig\n /** File path for context */\n filePath?: string\n}\n\nexport interface LintResult {\n /** The findings from all rules */\n findings: Finding[]\n}\n\n/**\n * Get effective severity for a rule based on config\n */\nfunction getEffectiveSeverity(\n rule: SchemaRule,\n config: SchemaLinterConfig | undefined\n): Severity | null {\n if (!config?.rules) {\n return rule.severity\n }\n\n const ruleConfig = config.rules[rule.id]\n\n if (ruleConfig === false) {\n return null // Disabled\n }\n\n if (ruleConfig === true) {\n return rule.severity\n }\n\n if (typeof ruleConfig === 'object') {\n if (ruleConfig.enabled === false) {\n return null\n }\n return ruleConfig.severity ?? rule.severity\n }\n\n return rule.severity\n}\n\n/**\n * Lint a schema type definition\n *\n * @param schema - The schema to lint\n * @param allRules - All available rules\n * @param options - Lint options\n * @returns Lint result with findings\n */\nexport function lint(\n schema: SchemaType,\n allRules: SchemaRule[],\n options: LintOptions = {}\n): LintResult {\n const { rules = allRules, config, filePath = '' } = options\n\n // Track which rules have fired (for supersedes logic)\n const firedRules = new Set<string>()\n const allFindings: Finding[] = []\n\n for (const rule of rules) {\n const severity = getEffectiveSeverity(rule, config)\n\n // Skip disabled rules\n if (severity === null) {\n continue\n }\n\n const ruleFindings: Finding[] = []\n const context: SchemaRuleContext = {\n filePath,\n report: (finding) => {\n ruleFindings.push({\n ...finding,\n ruleId: rule.id,\n severity: finding.severity ?? severity,\n })\n },\n }\n\n try {\n rule.check(schema, context)\n } catch (error) {\n // Don't let one rule crash the whole linter\n console.error(`Rule ${rule.id} threw an error:`, error)\n }\n\n if (ruleFindings.length > 0) {\n firedRules.add(rule.id)\n allFindings.push(...ruleFindings)\n }\n }\n\n // Apply supersedes logic AFTER running all rules\n // Only filter out findings if a superseding rule actually fired\n const findings = allFindings.filter((finding) => {\n // Check if any rule that supersedes this finding's rule has fired\n const isSuperseded = rules.some(\n (r) => r.supersedes?.includes(finding.ruleId) && firedRules.has(r.id)\n )\n return !isSuperseded\n })\n\n return { findings }\n}\n\n/**\n * Lint multiple schema types\n */\nexport function lintSchemas(\n schemas: SchemaType[],\n allRules: SchemaRule[],\n options: LintOptions = {}\n): LintResult {\n const findings: Finding[] = []\n\n for (const schema of schemas) {\n const result = lint(schema, allRules, options)\n findings.push(...result.findings)\n }\n\n return { findings }\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: missing-define-type\n *\n * Schema types should be wrapped with defineType() for proper type inference\n * and Studio integration.\n */\nexport const missingDefineType: SchemaRule = {\n id: 'missing-define-type',\n name: 'Missing defineType()',\n description: 'Schema types should use defineType() wrapper',\n severity: 'error',\n category: 'correctness',\n\n check(schema, context) {\n if (!schema.usesDefineType) {\n context.report({\n message: `Schema type \"${schema.name}\" should be wrapped with defineType()`,\n severity: 'error',\n ...(schema.span && { span: schema.span }),\n help: 'Import defineType from \"sanity\" and wrap your schema: export const myType = defineType({ ... })',\n })\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: missing-define-field\n *\n * Fields should be wrapped with defineField() for proper type inference.\n */\nexport const missingDefineField: SchemaRule = {\n id: 'missing-define-field',\n name: 'Missing defineField()',\n description: 'Fields should use defineField() wrapper',\n severity: 'error',\n category: 'correctness',\n\n check(schema, context) {\n // Only check if schema uses defineType (otherwise it's already broken)\n if (!schema.usesDefineType) {\n return\n }\n\n if (schema.usesDefineField === false && schema.fields && schema.fields.length > 0) {\n context.report({\n message: `Schema type \"${schema.name}\" has fields not wrapped with defineField()`,\n severity: 'error',\n ...(schema.span && { span: schema.span }),\n help: 'Import defineField from \"sanity\" and wrap each field: defineField({ name: \"...\", type: \"...\" })',\n })\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: missing-icon\n *\n * Document and object types should have an icon for better Studio UX.\n */\nexport const missingIcon: SchemaRule = {\n id: 'missing-icon',\n name: 'Missing icon',\n description: 'Document and object types should have an icon',\n severity: 'warning',\n category: 'style',\n\n check(schema, context) {\n // Only applies to document and object types\n if (schema.type !== 'document' && schema.type !== 'object') {\n return\n }\n\n if (!schema.hasIcon) {\n context.report({\n message: `Schema type \"${schema.name}\" should have an icon`,\n severity: 'warning',\n ...(schema.span && { span: schema.span }),\n help: 'Add an icon from @sanity/icons: icon: DocumentIcon',\n })\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: missing-title\n *\n * Schema types should have a human-readable title.\n */\nexport const missingTitle: SchemaRule = {\n id: 'missing-title',\n name: 'Missing title',\n description: 'Schema types should have a title property',\n severity: 'warning',\n category: 'style',\n\n check(schema, context) {\n // Only applies to document and object types\n if (schema.type !== 'document' && schema.type !== 'object') {\n return\n }\n\n if (!schema.title) {\n context.report({\n message: `Schema type \"${schema.name}\" should have a title property`,\n severity: 'warning',\n ...(schema.span && { span: schema.span }),\n help: 'Add a human-readable title: title: \"Blog Post\"',\n })\n }\n },\n}\n","import type { SchemaRule, SchemaField } from '../types'\n\n/**\n * Rule: missing-description\n *\n * Fields should have descriptions to help content editors.\n */\nexport const missingDescription: SchemaRule = {\n id: 'missing-description',\n name: 'Missing field description',\n description: 'Fields should have descriptions for better editor UX',\n severity: 'info',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n const fieldsWithoutDescription: SchemaField[] = []\n\n for (const field of schema.fields) {\n // Skip hidden fields\n if (field.hidden) {\n continue\n }\n\n // Skip common fields that don't need descriptions\n if (['_id', '_type', '_rev', '_createdAt', '_updatedAt'].includes(field.name)) {\n continue\n }\n\n if (!field.description) {\n fieldsWithoutDescription.push(field)\n }\n }\n\n // Report if more than half of visible fields lack descriptions\n const visibleFields = schema.fields.filter(\n (f) => !f.hidden && !['_id', '_type', '_rev', '_createdAt', '_updatedAt'].includes(f.name)\n )\n\n if (\n fieldsWithoutDescription.length > 0 &&\n fieldsWithoutDescription.length >= visibleFields.length / 2\n ) {\n const fieldNames = fieldsWithoutDescription.map((f) => f.name).slice(0, 3)\n const moreCount = fieldsWithoutDescription.length - 3\n\n context.report({\n message: `Fields in \"${schema.name}\" lack descriptions: ${fieldNames.join(', ')}${moreCount > 0 ? ` and ${moreCount} more` : ''}`,\n severity: 'info',\n ...(schema.span && { span: schema.span }),\n help: 'Add description to fields to help content editors understand what to enter',\n })\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Presentation-focused name patterns to flag\n */\nconst PRESENTATION_PATTERNS = [\n // Color-based names\n /^(red|blue|green|yellow|white|black|gray|grey|dark|light)/i,\n // Size-based names\n /^(big|small|large|tiny|huge|medium)/i,\n /(Big|Small|Large|Tiny|Huge|Medium)$/,\n // Layout-based names\n /^(left|right|center|top|bottom)/i,\n /(Left|Right|Center|Top|Bottom)$/,\n // Column/row names\n /(two|three|four|five|six)(Column|Row)/i,\n /^(column|row)\\d+$/i,\n // Explicit presentation terms\n /(Button|Text|Image|Box|Container|Wrapper|Section|Block|Card|Banner|Hero)$/,\n /^(hero|banner|sidebar|header|footer)/i,\n]\n\n/**\n * Semantic alternatives for common presentation names\n */\nconst SUGGESTIONS: Record<string, string> = {\n bigText: 'headline, title, heading',\n smallText: 'caption, subtitle, description',\n redButton: 'primaryAction, callToAction',\n heroSection: 'featuredContent, highlight',\n leftColumn: 'primaryContent, mainContent',\n rightColumn: 'secondaryContent, sidebar',\n threeColumnRow: 'featuresGrid, comparisonSection',\n headerImage: 'featuredImage, coverImage',\n bannerText: 'announcement, promotion',\n}\n\n/**\n * Rule: presentation-field-name\n *\n * Field names should be semantic, not presentation-focused.\n */\nexport const presentationFieldName: SchemaRule = {\n id: 'presentation-field-name',\n name: 'Presentation-focused field name',\n description: 'Avoid presentation-focused field names; use semantic names instead',\n severity: 'warning',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n const name = field.name\n\n for (const pattern of PRESENTATION_PATTERNS) {\n if (pattern.test(name)) {\n const suggestion = SUGGESTIONS[name] || 'a semantic name describing the content purpose'\n\n context.report({\n message: `Field \"${name}\" uses presentation-focused naming`,\n severity: 'warning',\n ...(field.span && { span: field.span }),\n help: `Consider using ${suggestion}. Field names should describe content purpose, not visual presentation.`,\n })\n break // Only report once per field\n }\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Common boolean field patterns that might benefit from being a list\n */\nconst EXPANDABLE_BOOLEAN_PATTERNS = [\n /^is[A-Z]/, // isActive, isPublished\n /^has[A-Z]/, // hasFeatured, hasDiscount\n /^show[A-Z]/, // showBanner, showSidebar\n /^enable[A-Z]/, // enableComments, enableSharing\n /^allow[A-Z]/, // allowComments, allowGuests\n /Status$/, // publicationStatus, reviewStatus\n /State$/, // publishState, approvalState\n /Mode$/, // displayMode, editMode\n]\n\n/**\n * Rule: boolean-instead-of-list\n *\n * Some boolean fields might be better represented as a string field\n * with options.list for future expandability.\n */\nexport const booleanInsteadOfList: SchemaRule = {\n id: 'boolean-instead-of-list',\n name: 'Boolean instead of list',\n description: 'Consider using options.list instead of boolean for expandable states',\n severity: 'info',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n if (field.type !== 'boolean') {\n continue\n }\n\n const name = field.name\n\n for (const pattern of EXPANDABLE_BOOLEAN_PATTERNS) {\n if (pattern.test(name)) {\n context.report({\n message: `Boolean field \"${name}\" might be better as a string with options.list`,\n severity: 'info',\n ...(field.span && { span: field.span }),\n help: 'Consider using type: \"string\" with options: { list: [...], layout: \"radio\" } for future expandability',\n })\n break\n }\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: missing-slug-source\n *\n * Slug fields should have options.source for auto-generation.\n */\nexport const missingSlugSource: SchemaRule = {\n id: 'missing-slug-source',\n name: 'Missing slug source',\n description: 'Slug fields should have options.source for auto-generation',\n severity: 'warning',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n if (field.type !== 'slug') {\n continue\n }\n\n if (!field.options?.source) {\n context.report({\n message: `Slug field \"${field.name}\" should have options.source`,\n severity: 'warning',\n ...(field.span && { span: field.span }),\n help: 'Add options: { source: \"title\" } to auto-generate slug from another field',\n })\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Field names that typically should have required validation\n */\nconst TYPICALLY_REQUIRED_FIELDS = ['title', 'name', 'slug', 'email', 'url', 'headline', 'heading']\n\n/**\n * Rule: missing-required-validation\n *\n * Critical fields like title, name, and slug should have validation rules.\n */\nexport const missingRequiredValidation: SchemaRule = {\n id: 'missing-required-validation',\n name: 'Missing required validation',\n description: 'Critical fields should have validation rules',\n severity: 'warning',\n category: 'correctness',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n // Only check document types\n if (schema.type !== 'document') {\n return\n }\n\n for (const field of schema.fields) {\n const name = field.name.toLowerCase()\n\n if (TYPICALLY_REQUIRED_FIELDS.includes(name) && !field.hasValidation) {\n context.report({\n message: `Field \"${field.name}\" in document type should have validation`,\n severity: 'warning',\n ...(field.span && { span: field.span }),\n help: 'Add validation: (rule) => rule.required() for critical fields',\n })\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Reserved Sanity field name prefixes\n */\nconst RESERVED_PREFIXES = ['_']\n\n/**\n * Reserved Sanity field names\n */\nconst RESERVED_NAMES = [\n '_id',\n '_type',\n '_rev',\n '_key',\n '_createdAt',\n '_updatedAt',\n '_ref',\n '_weak',\n '_strengthenOnPublish',\n]\n\n/**\n * Rule: reserved-field-name\n *\n * Field names starting with underscore are reserved by Sanity.\n */\nexport const reservedFieldName: SchemaRule = {\n id: 'reserved-field-name',\n name: 'Reserved field name',\n description: 'Field names starting with _ are reserved by Sanity',\n severity: 'error',\n category: 'correctness',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n const name = field.name\n\n // Check for reserved prefixes\n for (const prefix of RESERVED_PREFIXES) {\n if (name.startsWith(prefix)) {\n const isExactReserved = RESERVED_NAMES.includes(name)\n\n context.report({\n message: `Field name \"${name}\" uses reserved prefix \"${prefix}\"`,\n severity: 'error',\n ...(field.span && { span: field.span }),\n help: isExactReserved\n ? `\"${name}\" is a Sanity system field. Remove this field definition.`\n : `Field names starting with \"${prefix}\" are reserved. Use a different name.`,\n })\n break\n }\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Rule: array-missing-constraints\n *\n * Array fields should have constraints (min, max, unique) to prevent\n * unbounded data and ensure data quality.\n */\nexport const arrayMissingConstraints: SchemaRule = {\n id: 'array-missing-constraints',\n name: 'Array missing constraints',\n description: 'Array fields should have min/max/unique validation constraints',\n severity: 'info',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n if (field.type !== 'array') {\n continue\n }\n\n // Skip if field has validation (we trust it has constraints)\n if (field.hasValidation) {\n continue\n }\n\n context.report({\n message: `Array field \"${field.name}\" has no validation constraints`,\n severity: 'info',\n ...(field.span && { span: field.span }),\n help: 'Consider adding validation: (rule) => rule.min(1).max(10).unique() to prevent unbounded arrays',\n })\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Patterns that suggest heading level storage\n */\nconst HEADING_LEVEL_PATTERNS = [/^(heading|header)Level$/i, /^h[1-6]$/i, /Level$/]\n\n/**\n * Values that suggest heading level options\n */\nconst HEADING_LEVEL_VALUES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']\n\n/**\n * Rule: heading-level-in-schema\n *\n * Heading levels (h1, h2, etc.) should be computed dynamically in components,\n * not stored in the schema.\n */\nexport const headingLevelInSchema: SchemaRule = {\n id: 'heading-level-in-schema',\n name: 'Heading level in schema',\n description: 'Heading levels should be computed dynamically, not stored in schema',\n severity: 'warning',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n // Check field name\n for (const pattern of HEADING_LEVEL_PATTERNS) {\n if (pattern.test(field.name)) {\n context.report({\n message: `Field \"${field.name}\" appears to store heading levels`,\n severity: 'warning',\n ...(field.span && { span: field.span }),\n help: 'Heading levels should be computed dynamically in frontend components based on document structure, not stored in content.',\n })\n break\n }\n }\n\n // Check options.list for heading level values\n if (field.options?.list && Array.isArray(field.options.list)) {\n const hasHeadingLevels = field.options.list.some((item) => {\n const value =\n typeof item === 'object' && item !== null ? (item as { value?: string }).value : item\n return typeof value === 'string' && HEADING_LEVEL_VALUES.includes(value.toLowerCase())\n })\n\n if (hasHeadingLevels) {\n context.report({\n message: `Field \"${field.name}\" contains heading level options (h1, h2, etc.)`,\n severity: 'warning',\n ...(field.span && { span: field.span }),\n help: 'Heading levels should be computed dynamically in frontend components based on document structure, not stored in content.',\n })\n }\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n/**\n * Patterns that suggest a type is shared/reusable content\n * (should NOT trigger the rule)\n */\nconst SHARED_TYPE_PATTERNS = [\n /^author$/i,\n /^category$/i,\n /^tag$/i,\n /^user$/i,\n /^person$/i,\n /^organization$/i,\n /^company$/i,\n /^brand$/i,\n /^product$/i,\n /^page$/i,\n /^post$/i,\n /^article$/i,\n /^media$/i,\n /^asset$/i,\n /^file$/i,\n /^image$/i,\n /^video$/i,\n /^document$/i,\n /^location$/i,\n /^venue$/i,\n /^event$/i,\n]\n\n/**\n * Suffixes that suggest non-shared, schema-specific content\n * (SHOULD trigger the rule)\n */\nconst NON_SHARED_SUFFIXES = [\n 'Settings',\n 'Config',\n 'Configuration',\n 'Options',\n 'Metadata',\n 'Data',\n 'Info',\n 'Details',\n 'Content',\n 'Block',\n 'Section',\n 'Item',\n 'Entry',\n]\n\nfunction isLikelySharedType(typeName: string): boolean {\n return SHARED_TYPE_PATTERNS.some((pattern) => pattern.test(typeName))\n}\n\nfunction hasNonSharedSuffix(typeName: string): boolean {\n return NON_SHARED_SUFFIXES.some(\n (suffix) => typeName.endsWith(suffix) && typeName.length > suffix.length\n )\n}\n\nfunction isTypeSpecificToParent(parentName: string, referencedType: string): boolean {\n // Check if referenced type name contains parent name\n // e.g., \"post\" parent with \"postAuthor\" reference\n const parentLower = parentName.toLowerCase()\n const refLower = referencedType.toLowerCase()\n\n return refLower.startsWith(parentLower) && refLower !== parentLower\n}\n\n/**\n * Rule: unnecessary-reference\n *\n * Warns about reference fields that might be better as embedded objects.\n * References are great for shared content, but embedded objects are simpler\n * for content that's specific to a single document type.\n */\nexport const unnecessaryReference: SchemaRule = {\n id: 'unnecessary-reference',\n name: 'Unnecessary reference',\n description: 'Consider using an embedded object instead of a reference for non-shared content',\n severity: 'info',\n category: 'style',\n\n check(schema, context) {\n if (!schema.fields) {\n return\n }\n\n for (const field of schema.fields) {\n if (field.type !== 'reference') {\n continue\n }\n\n // Check each referenced type\n if (!field.to || field.to.length === 0) {\n continue\n }\n\n for (const ref of field.to) {\n const refType = ref.type\n\n // Skip if it's clearly a shared type\n if (isLikelySharedType(refType)) {\n continue\n }\n\n // Check if the referenced type seems specific to this schema\n if (isTypeSpecificToParent(schema.name, refType)) {\n context.report({\n message: `Reference to \"${refType}\" may be unnecessary`,\n severity: 'info',\n ...(field.span && { span: field.span }),\n help: `\"${refType}\" appears specific to \"${schema.name}\". Consider embedding the object directly instead of using a reference.`,\n })\n continue\n }\n\n // Check for non-shared naming patterns\n if (hasNonSharedSuffix(refType)) {\n context.report({\n message: `Reference to \"${refType}\" may be unnecessary`,\n severity: 'info',\n ...(field.span && { span: field.span }),\n help: `Types ending in \"Settings\", \"Config\", etc. are often better as embedded objects unless shared across multiple documents.`,\n })\n }\n }\n }\n },\n}\n","import type { SchemaRule } from '../types'\n\n// Core rules\nimport { missingDefineType } from './missing-define-type'\nimport { missingDefineField } from './missing-define-field'\nimport { missingIcon } from './missing-icon'\nimport { missingTitle } from './missing-title'\nimport { missingDescription } from './missing-description'\nimport { presentationFieldName } from './presentation-field-name'\n\n// Field rules\nimport { booleanInsteadOfList } from './boolean-instead-of-list'\nimport { missingSlugSource } from './missing-slug-source'\nimport { missingRequiredValidation } from './missing-required-validation'\nimport { reservedFieldName } from './reserved-field-name'\n\n// Array & Reference rules\nimport { arrayMissingConstraints } from './array-missing-constraints'\nimport { headingLevelInSchema } from './heading-level-in-schema'\nimport { unnecessaryReference } from './unnecessary-reference'\n\n/**\n * All available schema lint rules (13 total)\n */\nexport const rules: SchemaRule[] = [\n // Core rules\n missingDefineType,\n missingDefineField,\n missingIcon,\n missingTitle,\n missingDescription,\n presentationFieldName,\n\n // Field rules\n booleanInsteadOfList,\n missingSlugSource,\n missingRequiredValidation,\n reservedFieldName,\n\n // Array & Reference rules\n arrayMissingConstraints,\n headingLevelInSchema,\n unnecessaryReference,\n]\n\n// Named exports for direct imports\nexport {\n // Core rules\n missingDefineType,\n missingDefineField,\n missingIcon,\n missingTitle,\n missingDescription,\n presentationFieldName,\n // Field rules\n booleanInsteadOfList,\n missingSlugSource,\n missingRequiredValidation,\n reservedFieldName,\n // Array & Reference rules\n arrayMissingConstraints,\n headingLevelInSchema,\n unnecessaryReference,\n}\n"],"mappings":"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","names":["rules"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { S as SchemaType, a as SchemaRule, b as SchemaLinterConfig } from './types-C3OVyCP6.cjs';
|
|
2
|
+
export { c as SchemaField, e as SchemaRuleConfig, d as SchemaRuleContext } from './types-C3OVyCP6.cjs';
|
|
3
|
+
import { Finding } from '@sanity/lint-core';
|
|
4
|
+
|
|
5
|
+
interface LintOptions {
|
|
6
|
+
/** Specific rules to run (if not provided, runs all) */
|
|
7
|
+
rules?: SchemaRule[];
|
|
8
|
+
/** Configuration for rules */
|
|
9
|
+
config?: SchemaLinterConfig;
|
|
10
|
+
/** File path for context */
|
|
11
|
+
filePath?: string;
|
|
12
|
+
}
|
|
13
|
+
interface LintResult {
|
|
14
|
+
/** The findings from all rules */
|
|
15
|
+
findings: Finding[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Lint a schema type definition
|
|
19
|
+
*
|
|
20
|
+
* @param schema - The schema to lint
|
|
21
|
+
* @param allRules - All available rules
|
|
22
|
+
* @param options - Lint options
|
|
23
|
+
* @returns Lint result with findings
|
|
24
|
+
*/
|
|
25
|
+
declare function lint(schema: SchemaType, allRules: SchemaRule[], options?: LintOptions): LintResult;
|
|
26
|
+
/**
|
|
27
|
+
* Lint multiple schema types
|
|
28
|
+
*/
|
|
29
|
+
declare function lintSchemas(schemas: SchemaType[], allRules: SchemaRule[], options?: LintOptions): LintResult;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Rule: missing-define-type
|
|
33
|
+
*
|
|
34
|
+
* Schema types should be wrapped with defineType() for proper type inference
|
|
35
|
+
* and Studio integration.
|
|
36
|
+
*/
|
|
37
|
+
declare const missingDefineType: SchemaRule;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Rule: missing-define-field
|
|
41
|
+
*
|
|
42
|
+
* Fields should be wrapped with defineField() for proper type inference.
|
|
43
|
+
*/
|
|
44
|
+
declare const missingDefineField: SchemaRule;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Rule: missing-icon
|
|
48
|
+
*
|
|
49
|
+
* Document and object types should have an icon for better Studio UX.
|
|
50
|
+
*/
|
|
51
|
+
declare const missingIcon: SchemaRule;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Rule: missing-title
|
|
55
|
+
*
|
|
56
|
+
* Schema types should have a human-readable title.
|
|
57
|
+
*/
|
|
58
|
+
declare const missingTitle: SchemaRule;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Rule: missing-description
|
|
62
|
+
*
|
|
63
|
+
* Fields should have descriptions to help content editors.
|
|
64
|
+
*/
|
|
65
|
+
declare const missingDescription: SchemaRule;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Rule: presentation-field-name
|
|
69
|
+
*
|
|
70
|
+
* Field names should be semantic, not presentation-focused.
|
|
71
|
+
*/
|
|
72
|
+
declare const presentationFieldName: SchemaRule;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Rule: boolean-instead-of-list
|
|
76
|
+
*
|
|
77
|
+
* Some boolean fields might be better represented as a string field
|
|
78
|
+
* with options.list for future expandability.
|
|
79
|
+
*/
|
|
80
|
+
declare const booleanInsteadOfList: SchemaRule;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Rule: missing-slug-source
|
|
84
|
+
*
|
|
85
|
+
* Slug fields should have options.source for auto-generation.
|
|
86
|
+
*/
|
|
87
|
+
declare const missingSlugSource: SchemaRule;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Rule: missing-required-validation
|
|
91
|
+
*
|
|
92
|
+
* Critical fields like title, name, and slug should have validation rules.
|
|
93
|
+
*/
|
|
94
|
+
declare const missingRequiredValidation: SchemaRule;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Rule: reserved-field-name
|
|
98
|
+
*
|
|
99
|
+
* Field names starting with underscore are reserved by Sanity.
|
|
100
|
+
*/
|
|
101
|
+
declare const reservedFieldName: SchemaRule;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Rule: array-missing-constraints
|
|
105
|
+
*
|
|
106
|
+
* Array fields should have constraints (min, max, unique) to prevent
|
|
107
|
+
* unbounded data and ensure data quality.
|
|
108
|
+
*/
|
|
109
|
+
declare const arrayMissingConstraints: SchemaRule;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Rule: heading-level-in-schema
|
|
113
|
+
*
|
|
114
|
+
* Heading levels (h1, h2, etc.) should be computed dynamically in components,
|
|
115
|
+
* not stored in the schema.
|
|
116
|
+
*/
|
|
117
|
+
declare const headingLevelInSchema: SchemaRule;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Rule: unnecessary-reference
|
|
121
|
+
*
|
|
122
|
+
* Warns about reference fields that might be better as embedded objects.
|
|
123
|
+
* References are great for shared content, but embedded objects are simpler
|
|
124
|
+
* for content that's specific to a single document type.
|
|
125
|
+
*/
|
|
126
|
+
declare const unnecessaryReference: SchemaRule;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* All available schema lint rules (13 total)
|
|
130
|
+
*/
|
|
131
|
+
declare const rules: SchemaRule[];
|
|
132
|
+
|
|
133
|
+
export { type LintOptions, type LintResult, SchemaLinterConfig, SchemaRule, SchemaType, arrayMissingConstraints, booleanInsteadOfList, headingLevelInSchema, lint, lintSchemas, missingDefineField, missingDefineType, missingDescription, missingIcon, missingRequiredValidation, missingSlugSource, missingTitle, presentationFieldName, reservedFieldName, rules, unnecessaryReference };
|