Skip to content

Commit

Permalink
feat: deno specifier and workspace support (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret authored Aug 30, 2023
1 parent 93fd943 commit 3f6b8ca
Show file tree
Hide file tree
Showing 21 changed files with 2,523 additions and 173 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type_tracing = ["deno_ast/transforms", "deno_ast/visit", "deno_ast/utils"]

[dependencies]
anyhow = "1.0.43"
async-trait = "0.1.68"
data-url = "0.3.0"
deno_ast = { version = "0.28.0", features = ["dep_graph", "module_specifier"] }
deno_semver = "0.4.0"
Expand Down
4 changes: 4 additions & 0 deletions js/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export type {
TypesDependency,
} from "./types.d.ts";

// note: keep this in line with deno_cache
export type CacheSetting = "only" | "use" | "reload";

export interface CreateGraphOptions {
/**
* A callback that is called with the URL string of the resource to be loaded
Expand All @@ -55,6 +58,7 @@ export interface CreateGraphOptions {
load?(
specifier: string,
isDynamic: boolean,
cacheSetting: CacheSetting,
): Promise<LoadResponse | undefined>;
/** The type of graph to build. `"all"` includes all dependencies of the
* roots. `"typesOnly"` skips any code only dependencies that do not impact
Expand Down
13 changes: 11 additions & 2 deletions lib/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use deno_graph::source::load_data_url;
use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::Loader;
use deno_graph::source::LoaderCacheSetting;
use deno_graph::source::Resolver;
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
use deno_graph::BuildOptions;
Expand Down Expand Up @@ -59,10 +60,11 @@ impl Loader for JsLoader {
}
}

fn load(
fn load_with_cache_setting(
&mut self,
specifier: &ModuleSpecifier,
is_dynamic: bool,
cache_setting: LoaderCacheSetting,
) -> LoadFuture {
if specifier.scheme() == "data" {
Box::pin(future::ready(load_data_url(specifier)))
Expand All @@ -71,7 +73,13 @@ impl Loader for JsLoader {
let context = JsValue::null();
let arg1 = JsValue::from(specifier.to_string());
let arg2 = JsValue::from(is_dynamic);
let result = self.load.call2(&context, &arg1, &arg2);
let arg3 = JsValue::from(match cache_setting {
// note: keep these values aligned with deno_cache
LoaderCacheSetting::Only => "only",
LoaderCacheSetting::Prefer => "prefer",
LoaderCacheSetting::Reload => "reload",
});
let result = self.load.call3(&context, &arg1, &arg2, &arg3);
let f = async move {
let response = match result {
Ok(result) => {
Expand Down Expand Up @@ -247,6 +255,7 @@ pub async fn js_create_graph(
module_analyzer: None,
imports,
reporter: None,
workspace_members: Vec::new(),
},
)
.await;
Expand Down
7 changes: 7 additions & 0 deletions src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ pub struct PositionRange {
}

impl PositionRange {
pub fn zeroed() -> Self {
Self {
start: Position::zeroed(),
end: Position::zeroed(),
}
}

pub fn from_source_range(
range: SourceRange,
text_info: &SourceTextInfo,
Expand Down
90 changes: 90 additions & 0 deletions src/deno.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.

use std::collections::BTreeMap;
use std::collections::HashMap;

use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq;
use deno_semver::Version;
use deno_semver::VersionReq;
use serde::Deserialize;
use serde::Serialize;

use crate::ModuleInfo;

#[derive(Serialize, Deserialize, Clone)]
pub struct DenoPackageInfo {
pub versions: HashMap<Version, DenoPackageInfoVersion>,
}

#[derive(Serialize, Deserialize, Clone, Default)]
pub struct DenoPackageInfoVersion {
// currently not supported because it doesn't work in workspaces
// pub main: Option<String>,
}

#[derive(Serialize, Deserialize, Clone, Default)]
pub struct DenoPackageVersionInfo {
#[serde(rename = "moduleGraph1")]
pub module_graph: Option<serde_json::Value>,
}

impl DenoPackageVersionInfo {
pub fn module_info(&self, specifier: &str) -> Option<ModuleInfo> {
let module_graph = self.module_graph.as_ref()?.as_object()?;
let module_info = module_graph.get(specifier)?;
serde_json::from_value(module_info.clone()).ok()
}
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct DenoSpecifierSnapshot {
#[serde(flatten)]
package_reqs: BTreeMap<PackageReq, PackageNv>,
#[serde(skip_serializing)]
packages_by_name: HashMap<String, Vec<PackageNv>>,
}

impl DenoSpecifierSnapshot {
pub fn is_empty(&self) -> bool {
self.package_reqs.is_empty()
}

pub fn add(&mut self, package_req: PackageReq, nv: PackageNv) {
let nvs = self
.packages_by_name
.entry(package_req.name.clone())
.or_default();
if !nvs.contains(&nv) {
nvs.push(nv.clone());
}
self.package_reqs.insert(package_req, nv);
}

pub fn versions_by_name(&self, name: &str) -> Option<&Vec<PackageNv>> {
self.packages_by_name.get(name)
}

pub fn mappings(&self) -> impl Iterator<Item = (&PackageReq, &PackageNv)> {
self.package_reqs.iter()
}
}

pub fn resolve_version<'a>(
version_req: &VersionReq,
versions: impl Iterator<Item = &'a Version>,
) -> Option<&'a Version> {
let mut maybe_best_version: Option<&Version> = None;
for version in versions {
if version_req.matches(version) {
let is_best_version = maybe_best_version
.as_ref()
.map(|best_version| (*best_version).cmp(version).is_lt())
.unwrap_or(true);
if is_best_version {
maybe_best_version = Some(version);
}
}
}
maybe_best_version
}
Loading

0 comments on commit 3f6b8ca

Please sign in to comment.