tinymist_package/
registry.rs1use std::num::NonZeroUsize;
4use std::path::PathBuf;
5use std::{path::Path, sync::Arc};
6
7use ecow::EcoString;
8use serde::Deserialize;
9use tinymist_std::time::UtcDateTime;
10pub use typst::diag::PackageError;
11pub use typst::syntax::package::PackageSpec;
12use typst::syntax::package::{PackageInfo, TemplateInfo};
13
14mod dummy;
15pub use dummy::*;
16
17mod memory;
18pub use memory::*;
19
20#[cfg(feature = "browser")]
21mod browser;
22#[cfg(feature = "browser")]
23pub use browser::*;
24
25#[cfg(feature = "http-registry")]
26mod http;
27#[cfg(feature = "http-registry")]
28pub use http::*;
29
30pub const DEFAULT_REGISTRY: &str = "https://packages.typst.org";
32
33pub trait PackageRegistry {
35 fn reset(&mut self) {}
37
38 fn revision(&self) -> Option<NonZeroUsize> {
42 None
43 }
44
45 fn resolve(&self, spec: &PackageSpec) -> Result<Arc<Path>, PackageError>;
47
48 fn packages(&self) -> &[PackageIndexEntry] {
55 &[]
56 }
57}
58
59#[derive(Debug, Clone, Deserialize)]
61pub struct PackageIndexEntry {
62 #[serde(default)]
64 pub namespace: EcoString,
65 #[serde(flatten)]
67 pub package: PackageInfo,
68 #[serde(default)]
70 pub template: Option<TemplateInfo>,
71 #[serde(rename = "updatedAt", deserialize_with = "deserialize_timestamp")]
73 pub updated_at: Option<UtcDateTime>,
74 #[serde(default)]
76 pub path: Option<PathBuf>,
77}
78
79impl PackageIndexEntry {
80 pub fn spec(&self) -> PackageSpec {
82 PackageSpec {
83 namespace: self.namespace.clone(),
84 name: self.package.name.clone(),
85 version: self.package.version,
86 }
87 }
88}
89
90fn deserialize_timestamp<'de, D>(deserializer: D) -> Result<Option<UtcDateTime>, D::Error>
91where
92 D: serde::Deserializer<'de>,
93{
94 let timestamp = i64::deserialize(deserializer)?;
95 Ok(UtcDateTime::from_unix_timestamp(timestamp).ok())
96}
97
98pub trait Notifier {
100 fn downloading(&self, _spec: &PackageSpec) {}
102}
103
104#[derive(Debug, Default, Clone, Copy, Hash)]
106pub struct DummyNotifier;
107
108impl Notifier for DummyNotifier {}