Download codex-rs/core-plugins/src/npm_source.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 6.19 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core-plugins/src/npm_source.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/core-plugins/src/npm_source.rs
-
curl -L -o npm_source.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core-plugins/src/npm_source.rs
6.19 kB
| use crate::plugin_bundle_archive::unpack_plugin_bundle_tar_gz; | |
| use codex_utils_absolute_path::AbsolutePathBuf; | |
| use serde::Deserialize; | |
| use std::ffi::OsStr; | |
| use std::fs; | |
| use std::path::Path; | |
| use std::path::PathBuf; | |
| use std::process::Command; | |
| use tempfile::TempDir; | |
| const NPM_PLUGIN_SOURCE_STAGING_DIR: &str = "plugins/.marketplace-plugin-source-staging"; | |
| const NPM_PLUGIN_SOURCE_MAX_ARCHIVE_BYTES: u64 = 50 * 1024 * 1024; | |
| const NPM_PLUGIN_SOURCE_MAX_EXTRACTED_BYTES: u64 = 250 * 1024 * 1024; | |
| const NPM_PACKAGE_ARCHIVE_ROOT: &str = "package"; | |
| pub(crate) fn materialize_npm_plugin_source( | |
| codex_home: &Path, | |
| package: &str, | |
| version: Option<&str>, | |
| registry: Option<&str>, | |
| ) -> Result<(AbsolutePathBuf, TempDir), String> { | |
| materialize_npm_plugin_source_with_command( | |
| codex_home, | |
| package, | |
| version, | |
| registry, | |
| OsStr::new(npm_command()), | |
| ) | |
| } | |
| fn materialize_npm_plugin_source_with_command( | |
| codex_home: &Path, | |
| package: &str, | |
| version: Option<&str>, | |
| registry: Option<&str>, | |
| npm_command: &OsStr, | |
| ) -> Result<(AbsolutePathBuf, TempDir), String> { | |
| let staging_root = codex_home.join(NPM_PLUGIN_SOURCE_STAGING_DIR); | |
| fs::create_dir_all(&staging_root).map_err(|err| { | |
| format!( | |
| "failed to create marketplace plugin source staging directory {}: {err}", | |
| staging_root.display() | |
| ) | |
| })?; | |
| let tempdir = tempfile::Builder::new() | |
| .prefix("marketplace-plugin-source-") | |
| .tempdir_in(&staging_root) | |
| .map_err(|err| { | |
| format!( | |
| "failed to create marketplace plugin source staging directory in {}: {err}", | |
| staging_root.display() | |
| ) | |
| })?; | |
| pack_npm_package(tempdir.path(), package, version, registry, npm_command)?; | |
| let archive_path = find_npm_package_archive(tempdir.path())?; | |
| let archive_bytes = read_npm_package_archive(&archive_path)?; | |
| let extraction_root = tempdir.path().join("extracted"); | |
| unpack_plugin_bundle_tar_gz( | |
| &archive_bytes, | |
| &extraction_root, | |
| NPM_PLUGIN_SOURCE_MAX_EXTRACTED_BYTES, | |
| ) | |
| .map_err(|err| format!("failed to extract npm plugin package: {err}"))?; | |
| let plugin_root = extraction_root.join(NPM_PACKAGE_ARCHIVE_ROOT); | |
| if !plugin_root.is_dir() { | |
| return Err(format!( | |
| "npm pack completed without creating plugin package directory {}", | |
| plugin_root.display() | |
| )); | |
| } | |
| validate_npm_package_metadata(&plugin_root, package)?; | |
| let plugin_root = AbsolutePathBuf::try_from(plugin_root) | |
| .map_err(|err| format!("failed to resolve materialized plugin source path: {err}"))?; | |
| Ok((plugin_root, tempdir)) | |
| } | |
| fn pack_npm_package( | |
| destination: &Path, | |
| package: &str, | |
| version: Option<&str>, | |
| registry: Option<&str>, | |
| npm_command: &OsStr, | |
| ) -> Result<(), String> { | |
| let package_spec = version.map_or_else( | |
| || package.to_string(), | |
| |version| format!("{package}@{version}"), | |
| ); | |
| let mut command = Command::new(npm_command); | |
| command | |
| .current_dir(destination) | |
| .arg("pack") | |
| .arg("--ignore-scripts") | |
| .arg("--pack-destination") | |
| .arg(destination); | |
| if let Some(registry) = registry { | |
| command.arg("--registry").arg(registry); | |
| } | |
| command.arg("--").arg(package_spec); | |
| let output = command | |
| .output() | |
| .map_err(|err| format!("failed to run npm pack: {err}"))?; | |
| if output.status.success() { | |
| return Ok(()); | |
| } | |
| Err(format!( | |
| "npm pack failed with status {}\nstdout:\n{}\nstderr:\n{}", | |
| output.status, | |
| String::from_utf8_lossy(&output.stdout).trim(), | |
| String::from_utf8_lossy(&output.stderr).trim() | |
| )) | |
| } | |
| fn find_npm_package_archive(destination: &Path) -> Result<PathBuf, String> { | |
| let mut archives = fs::read_dir(destination) | |
| .map_err(|err| format!("failed to read npm pack destination: {err}"))? | |
| .filter_map(std::result::Result::ok) | |
| .filter_map(|entry| { | |
| let path = entry.path(); | |
| let is_file = entry.file_type().is_ok_and(|file_type| file_type.is_file()); | |
| (is_file && path.extension() == Some(OsStr::new("tgz"))).then_some(path) | |
| }) | |
| .collect::<Vec<_>>(); | |
| if archives.len() != 1 { | |
| return Err(format!( | |
| "npm pack completed with {} package archives; expected exactly one", | |
| archives.len() | |
| )); | |
| } | |
| Ok(archives.remove(0)) | |
| } | |
| fn read_npm_package_archive(archive_path: &Path) -> Result<Vec<u8>, String> { | |
| let archive_size = fs::metadata(archive_path) | |
| .map_err(|err| format!("failed to inspect npm package archive: {err}"))? | |
| .len(); | |
| if archive_size > NPM_PLUGIN_SOURCE_MAX_ARCHIVE_BYTES { | |
| return Err(format!( | |
| "npm package archive is {archive_size} bytes, exceeding maximum size of {NPM_PLUGIN_SOURCE_MAX_ARCHIVE_BYTES} bytes" | |
| )); | |
| } | |
| fs::read(archive_path).map_err(|err| format!("failed to read npm package archive: {err}")) | |
| } | |
| fn validate_npm_package_metadata(plugin_root: &Path, package: &str) -> Result<(), String> { | |
| struct NpmPackageMetadata { | |
| name: String, | |
| } | |
| let package_json_path = plugin_root.join("package.json"); | |
| let package_json = fs::read_to_string(&package_json_path).map_err(|err| { | |
| format!( | |
| "failed to read npm plugin package metadata {}: {err}", | |
| package_json_path.display() | |
| ) | |
| })?; | |
| let metadata: NpmPackageMetadata = serde_json::from_str(&package_json).map_err(|err| { | |
| format!( | |
| "failed to parse npm plugin package metadata {}: {err}", | |
| package_json_path.display() | |
| ) | |
| })?; | |
| if metadata.name != package { | |
| return Err(format!( | |
| "npm plugin package name '{}' does not match requested package '{package}'", | |
| metadata.name | |
| )); | |
| } | |
| Ok(()) | |
| } | |
| fn npm_command() -> &'static str { | |
| "npm.cmd" | |
| } | |
| fn npm_command() -> &'static str { | |
| "npm" | |
| } | |
| mod tests; | |