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};