Skip to content

Commit 3c67cff

Browse files
committed
Pull READMEs out of full index
Aside from index.json, the bundler creates a second _full index,_ which is an implementation detail of typst.app. This index has grown to 18MB due to the READMEs included within. This makes it annoying to work with: - Our CDN, Azure Front Door, does not automatically compress files larger than 8MB - Downloads from JavaScript and WebKit spuriously fail due to keepalives - The file occupies a relatively large amount of memory once loaded Instead, we factor out the READMEs into their own folder that can be loaded on demand. The new full index without the README field is called `index.extra.json`. To prevent disruption of running infrastructure, `index.full.json` is retained in storage but no longer updated. This exception can be removed soon. The new `readmes` folder is also an implementation detail of typst.app and should not be used by third parties.
1 parent 6739adb commit 3c67cff

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ jobs:
4444
--cache-control 'public, max-age=7776000' --put-md5
4545
4646
azcopy_v10 cp --recursive ./dist/* "https://$ACCOUNT_NAME.blob.core.windows.net/\$web" \
47-
--overwrite true --include-pattern '*.json' \
47+
--overwrite true --include-pattern '*.json' --exclude-pattern '*index.full.json' \
4848
--cache-control 'must-revalidate' --put-md5

bundler/src/main.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use self::timestamp::determine_timestamps;
2727

2828
const DIST: &str = "dist";
2929
const THUMBS_DIR: &str = "thumbnails";
30+
const READMES_DIR: &str = "readmes";
3031

3132
struct Config {
3233
out_dir: PathBuf,
@@ -84,6 +85,8 @@ fn main() -> anyhow::Result<()> {
8485
let mut package_errors = vec![];
8586
fs::create_dir_all(namespace_dir.join(THUMBS_DIR))
8687
.context("could not create output directory")?;
88+
fs::create_dir(namespace_dir.join(READMES_DIR))
89+
.context("could not create directory for READMEs")?;
8790

8891
for entry in walkdir::WalkDir::new(&path).min_depth(2).max_depth(2) {
8992
let entry = entry.with_context(|| {
@@ -142,16 +145,42 @@ fn main() -> anyhow::Result<()> {
142145
index.sort_by_key(|info| (info.package.name.clone(), info.package.version));
143146

144147
println!("Writing index.");
148+
149+
// This index is allowed to be used by third parties: Both the Typst CLI
150+
// and the web app download this index. However, we give no stability
151+
// guarantees.
145152
fs::write(
146153
namespace_dir.join("index.json"),
147154
serde_json::to_vec(&index.iter().map(IndexPackageInfo::from).collect::<Vec<_>>())
148155
.context("serialization of compact package index failed")?,
149156
)?;
157+
158+
// The index.extra.json is an implementation detail of typst.app. This
159+
// file should not be used by third parties: They should instead use
160+
// index.json.
150161
fs::write(
151-
namespace_dir.join("index.full.json"),
152-
serde_json::to_vec(&index).context("serialization of full package index failed")?,
162+
namespace_dir.join("index.extra.json"),
163+
serde_json::to_vec(
164+
&index
165+
.iter()
166+
.map(ExtraIndexPackageInfo::from)
167+
.collect::<Vec<_>>(),
168+
)
169+
.context("serialization of extra package index failed")?,
153170
)?;
154171

172+
println!("Writing READMEs.");
173+
174+
let readme_dir = namespace_dir.join(READMES_DIR);
175+
176+
// The README files are an implementation detail of typst.app. They
177+
// should not be used by third parties.
178+
for item in &index {
179+
let path =
180+
readme_dir.join(format!("{}-{}.md", item.package.name, item.package.version));
181+
fs::write(path, &item.readme)?;
182+
}
183+
155184
if !package_errors.is_empty() {
156185
namespace_errors.push((namespace.to_string(), package_errors));
157186
}

bundler/src/model.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl From<&FullIndexPackageInfo> for IndexPackageInfo {
2828
/// A parsed package manifest + extra metadata.
2929
#[derive(Debug, Clone, Serialize)]
3030
#[serde(rename_all = "camelCase")]
31-
pub struct FullIndexPackageInfo {
31+
pub struct ExtraIndexPackageInfo {
3232
/// The package information from the package manifest.
3333
#[serde(flatten)]
3434
pub package: PackageInfo,
@@ -37,6 +37,32 @@ pub struct FullIndexPackageInfo {
3737
pub template: Option<TemplateInfo>,
3838
/// The compressed archive size in bytes.
3939
pub size: usize,
40+
/// Release time of this version of the package.
41+
pub updated_at: u64,
42+
/// Release time of the first version of this package.
43+
pub released_at: u64,
44+
}
45+
46+
impl From<&FullIndexPackageInfo> for ExtraIndexPackageInfo {
47+
fn from(info: &FullIndexPackageInfo) -> Self {
48+
ExtraIndexPackageInfo {
49+
package: info.package.clone(),
50+
template: info.template.clone(),
51+
size: info.size,
52+
updated_at: info.updated_at,
53+
released_at: info.released_at,
54+
}
55+
}
56+
}
57+
58+
/// A parsed package manifest + extra metadata and the Readme.
59+
pub struct FullIndexPackageInfo {
60+
/// The package information from the package manifest.
61+
pub package: PackageInfo,
62+
/// The template information from the package manifest.
63+
pub template: Option<TemplateInfo>,
64+
/// The compressed archive size in bytes.
65+
pub size: usize,
4066
/// The unsanitized README markdown.
4167
pub readme: String,
4268
/// Release time of this version of the package.

0 commit comments

Comments
 (0)