Skip to main content

hyperlight_js/
script.rs

1/*
2Copyright 2026  The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16use std::path::{Path, PathBuf};
17use std::sync::Arc;
18
19use crate::{new_error, Result};
20
21/// Represents a JavaScript immutable handler script with metadata about its source location.
22/// The source location metadata is required to resolve relative locations when the script imports
23/// other modules using relative paths.
24#[derive(Debug, Clone)]
25pub struct Script {
26    /// The script content
27    content: Arc<str>,
28    /// base path for resolving module imports
29    base_path: Option<PathBuf>,
30}
31
32impl Script {
33    /// Create a script from a string with no base path for module resolution
34    pub fn from_content(content: impl Into<String>) -> Self {
35        // TODO(tandr): Consider validating the script content using oxc_parser or similar
36        Self {
37            content: Arc::from(content.into()),
38            base_path: None,
39        }
40    }
41
42    /// Create a script by reading from a file
43    ///
44    /// The base path is automatically set to the directory containing the file
45    pub fn from_file(path: impl AsRef<Path>) -> Result<Self> {
46        let path = path.as_ref();
47
48        let content = std::fs::read_to_string(path)
49            .map_err(|e| new_error!("Failed to read script from '{}': {}", path.display(), e))?;
50
51        let base_path = path.parent().map(|p| p.to_path_buf());
52        Ok(Self {
53            content: Arc::from(content),
54            base_path,
55        })
56    }
57
58    /// Set a virtual base path for module resolution.
59    pub fn with_virtual_base(mut self, path: impl AsRef<str>) -> Self {
60        self.base_path = Some(PathBuf::from(path.as_ref()));
61        self
62    }
63
64    /// Get the script content
65    pub fn content(&self) -> &str {
66        &self.content
67    }
68
69    /// Get the base path for module resolution, if any
70    pub fn base_path(&self) -> Option<&Path> {
71        self.base_path.as_deref()
72    }
73}
74
75impl From<String> for Script {
76    fn from(content: String) -> Self {
77        Self::from_content(content)
78    }
79}
80
81impl From<&str> for Script {
82    fn from(content: &str) -> Self {
83        Self::from_content(content)
84    }
85}
86
87impl TryFrom<&Path> for Script {
88    type Error = hyperlight_host::HyperlightError;
89    fn try_from(path: &Path) -> Result<Self> {
90        Self::from_file(path)
91    }
92}