fob_graph/analysis/extractors/
common.rs

1//! Common types and traits for framework extractors.
2//!
3//! This module defines the unified interface for extracting JavaScript/TypeScript
4//! from framework-specific file formats (Astro, Svelte, Vue).
5
6/// Represents JavaScript/TypeScript source code extracted from a framework file.
7///
8/// This is a unified type that replaces framework-specific `JavaScriptSource` types.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ExtractedScript<'a> {
11    /// The extracted JavaScript/TypeScript source code
12    pub source_text: &'a str,
13
14    /// Byte offset from the start of the original file
15    ///
16    /// This offset points to the beginning of the script content.
17    /// Used to translate parse errors back to the original file location.
18    pub source_offset: usize,
19
20    /// Context information about this script block
21    pub context: ScriptContext,
22
23    /// Language identifier (js, ts, jsx, tsx)
24    pub lang: &'a str,
25}
26
27impl<'a> ExtractedScript<'a> {
28    /// Creates a new extracted script with the given parameters.
29    pub fn new(
30        source_text: &'a str,
31        source_offset: usize,
32        context: ScriptContext,
33        lang: &'a str,
34    ) -> Self {
35        Self {
36            source_text,
37            source_offset,
38            context,
39            lang,
40        }
41    }
42}
43
44/// Context information about an extracted script block.
45///
46/// Different frameworks use different contexts to distinguish script blocks:
47/// - Astro: Frontmatter vs script tags
48/// - Svelte: Module context vs component instance
49/// - Vue: Setup script vs regular script
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum ScriptContext {
52    /// Astro frontmatter block (runs on server during build/SSR)
53    AstroFrontmatter,
54    /// Astro script tag (runs in browser)
55    AstroScript,
56    /// Svelte module context block (runs once when module is imported)
57    SvelteModule,
58    /// Svelte component instance script (runs for each component instance)
59    SvelteComponent,
60    /// Vue setup script (Composition API with compile-time sugar)
61    VueSetup,
62    /// Vue regular script (Options API or general setup)
63    VueRegular,
64}
65
66/// Unified error type for all extractors.
67#[derive(Debug, thiserror::Error)]
68pub enum ExtractorError {
69    /// File exceeds maximum allowed size
70    #[error("File too large: {size} bytes (max: {max} bytes)")]
71    FileTooLarge {
72        /// Actual file size in bytes
73        size: usize,
74        /// Maximum allowed size in bytes
75        max: usize,
76    },
77
78    /// Too many script tags found in the file
79    #[error("Too many script tags: {count} found (max: {max} allowed)")]
80    TooManyScriptTags {
81        /// Number of script tags found
82        count: usize,
83        /// Maximum allowed script tags
84        max: usize,
85    },
86
87    /// Script tag opened but never closed
88    #[error("Unclosed script tag starting at byte position {position}")]
89    UnclosedScriptTag {
90        /// Byte position where the unclosed tag begins
91        position: usize,
92    },
93
94    /// Frontmatter opened but never closed (Astro-specific)
95    #[error("Unclosed frontmatter starting at byte position {position}")]
96    UnclosedFrontmatter {
97        /// Byte position where the unclosed frontmatter begins
98        position: usize,
99    },
100
101    /// File contains invalid UTF-8
102    #[error("Invalid UTF-8 encoding in file")]
103    InvalidUtf8,
104
105    /// I/O error reading the file
106    #[error("I/O error: {0}")]
107    Io(#[from] std::io::Error),
108}
109
110/// Trait for framework-specific extractors.
111///
112/// Each framework (Astro, Svelte, Vue) implements this trait to provide
113/// script extraction capabilities.
114pub trait Extractor {
115    /// Extract JavaScript/TypeScript scripts from the given source code.
116    ///
117    /// # Arguments
118    ///
119    /// * `source` - The complete file content
120    ///
121    /// # Returns
122    ///
123    /// A vector of extracted scripts, or an error if extraction fails.
124    fn extract<'a>(&self, source: &'a str) -> Result<Vec<ExtractedScript<'a>>, ExtractorError>;
125
126    /// Get the file extension this extractor handles (e.g., ".astro", ".svelte", ".vue").
127    fn file_extension(&self) -> &'static str;
128}
129
130// Constants moved to crate::config module
131// Re-export for backward compatibility
132pub use crate::analysis::config::{MAX_FILE_SIZE, MAX_SCRIPT_TAGS};