diff --git a/.gitignore b/.gitignore index a1ec3038..241e3011 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /book/build +/book/src/api +/book/src/api.md /book/src/authoring-metadata.md /book/src/commands /book/src/commands.md @@ -12,9 +14,9 @@ /book/src/languages.md /book/src/lints.md /book/src/media-formats.md -/book/src/routes -/book/src/routes.md /book/src/unstable-features.md +/book/src/web +/book/src/web.md /book/src/yaml /book/src/yaml.md /flamegraph.svg diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 554e1d4e..a88ee960 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -19,6 +19,17 @@ Summary - [Alternatives and Prior Art](alternatives.md) # Reference +- [API](api.md) + - [/api/directory/\{hash\}](api/directory-hash.md) + - [/api/file/\{hash\}](api/file-hash.md) + - [/api/gc](api/gc.md) + - [/api/head/\{revision\}](api/head-revision.md) + - [/api/missing](api/missing.md) + - [/api/number/\{number\}](api/number-number.md) + - [/api/numbers](api/numbers.md) + - [/api/package/\{fingerprint\}](api/package-fingerprint.md) + - [/api/packages](api/packages.md) + - [/api/revision/\{revision\}](api/revision-revision.md) - [Commands](commands.md) - [filepack](commands/filepack.md) - [filepack archive](commands/filepack-archive.md) @@ -149,41 +160,6 @@ Summary - [Languages](languages.md) - [Lints](lints.md) - [Media Formats](media-formats.md) -- [Routes](routes.md) - - [/](routes/index.md) - - [/api/directory/\{hash\}](routes/api-directory-hash.md) - - [/api/file/\{hash\}](routes/api-file-hash.md) - - [/api/gc](routes/api-gc.md) - - [/api/head/\{revision\}](routes/api-head-revision.md) - - [/api/missing](routes/api-missing.md) - - [/api/number/\{number\}](routes/api-number-number.md) - - [/api/numbers](routes/api-numbers.md) - - [/api/package/\{fingerprint\}](routes/api-package-fingerprint.md) - - [/api/packages](routes/api-packages.md) - - [/api/revision/\{revision\}](routes/api-revision-revision.md) - - [/artwork/\{fingerprint\}](routes/artwork-fingerprint.md) - - [/artwork/\{fingerprint\}/thumbnail](routes/artwork-fingerprint-thumbnail.md) - - [/directory/\{hash\}](routes/directory-hash.md) - - [/favicon.ico](routes/favicon-ico.md) - - [/file/\{hash\}](routes/file-hash.md) - - [/file/\{hash\}/\{\*path\}](routes/file-hash-path.md) - - [/files](routes/files.md) - - [/install.sh](routes/install-sh.md) - - [/media/audio/\{fingerprint\}/item/\{item\}](routes/media-audio-fingerprint-item-item.md) - - [/media/image/\{fingerprint\}/item/\{item\}](routes/media-image-fingerprint-item-item.md) - - [/media/image/\{fingerprint\}/item/\{item\}/thumbnail](routes/media-image-fingerprint-item-item-thumbnail.md) - - [/media/video/\{fingerprint\}/item/\{item\}](routes/media-video-fingerprint-item-item.md) - - [/media/video/\{fingerprint\}/item/\{item\}/placeholder](routes/media-video-fingerprint-item-item-placeholder.md) - - [/media/video/\{fingerprint\}/item/\{item\}/placeholder/thumbnail](routes/media-video-fingerprint-item-item-placeholder-thumbnail.md) - - [/mount/\{package\}](routes/mount-package.md) - - [/mount/\{package\}/](routes/mount-package-index.md) - - [/mount/\{package\}/\{\*path\}](routes/mount-package-path.md) - - [/package/\{package\}](routes/package-package.md) - - [/package/\{package\}/history](routes/package-package-history.md) - - [/package/\{package\}/item/\{item\}](routes/package-package-item-item.md) - - [/package/\{package\}/media](routes/package-package-media.md) - - [/packages](routes/packages.md) - - [/static/\{\*path\}](routes/static-path.md) - [Tagged Hex](hex.md) - [hash](hex/hash.md) - [package](hex/package.md) @@ -193,6 +169,31 @@ Summary - [signature](hex/signature.md) - [token](hex/token.md) - [Unstable Features](unstable-features.md) +- [Web](web.md) + - [/](web/index.md) + - [/artwork/\{fingerprint\}](web/artwork-fingerprint.md) + - [/artwork/\{fingerprint\}/thumbnail](web/artwork-fingerprint-thumbnail.md) + - [/directory/\{hash\}](web/directory-hash.md) + - [/favicon.ico](web/favicon-ico.md) + - [/file/\{hash\}](web/file-hash.md) + - [/file/\{hash\}/\{\*path\}](web/file-hash-path.md) + - [/files](web/files.md) + - [/install.sh](web/install-sh.md) + - [/media/audio/\{fingerprint\}/item/\{item\}](web/media-audio-fingerprint-item-item.md) + - [/media/image/\{fingerprint\}/item/\{item\}](web/media-image-fingerprint-item-item.md) + - [/media/image/\{fingerprint\}/item/\{item\}/thumbnail](web/media-image-fingerprint-item-item-thumbnail.md) + - [/media/video/\{fingerprint\}/item/\{item\}](web/media-video-fingerprint-item-item.md) + - [/media/video/\{fingerprint\}/item/\{item\}/placeholder](web/media-video-fingerprint-item-item-placeholder.md) + - [/media/video/\{fingerprint\}/item/\{item\}/placeholder/thumbnail](web/media-video-fingerprint-item-item-placeholder-thumbnail.md) + - [/mount/\{package\}](web/mount-package.md) + - [/mount/\{package\}/](web/mount-package-index.md) + - [/mount/\{package\}/\{\*path\}](web/mount-package-path.md) + - [/package/\{package\}](web/package-package.md) + - [/package/\{package\}/history](web/package-package-history.md) + - [/package/\{package\}/item/\{item\}](web/package-package-item-item.md) + - [/package/\{package\}/media](web/package-package-media.md) + - [/packages](web/packages.md) + - [/static/\{\*path\}](web/static-path.md) - [YAML](yaml.md) - [Audio](yaml/audio.md) - [CheckedUrl](yaml/checked-url.md) diff --git a/book/src/server.md b/book/src/server.md index a1b94b49..241be090 100644 --- a/book/src/server.md +++ b/book/src/server.md @@ -7,12 +7,12 @@ available at [filepack.com](https://filepack.com). The server has a web frontend that can be used to browse packages, as well as an API for uploading and downloading packages. -See [Routes](routes.md) for documentation of both the web and API routes. +See [API](api.md) and [Web](web.md) for documentation of the API and web +routes. The server responds to requests for `/{fingerprint}`, `/{number}`, and -`/{revision}` which redirect to -[`/package/{package}`](routes/package-package.md), and can be used as -convenient shortcuts. +`/{revision}` which redirect to [`/package/{package}`](web/package-package.md), +and can be used as convenient shortcuts. Authorization ------------- @@ -85,7 +85,7 @@ access. API --- -API routes begin with `/api`. See [Routes](routes.md) for details. +API routes begin with `/api`. See [API](api.md) for details. Typed request and response bodies are encoded with [deco](deco.md). @@ -196,21 +196,20 @@ the server will accept the first and reject the second with `409 Conflict`. Package uploads are content-addressed and bottom up. Files, directories, and revisions are uploaded using [`PUT -/api/file/{hash}`](routes/api-file-hash.md#put). +/api/file/{hash}`](api/file-hash.md#put). Directories are verified using [`POST -/api/directory/{hash}`](routes/api-directory-hash.md#post), which requires that -all files have been uploaded and all subdirectories have been verified. +/api/directory/{hash}`](api/directory-hash.md#post), which requires that all +files have been uploaded and all subdirectories have been verified. The package is verified using [`POST -/api/package/{fingerprint}`](routes/api-package-fingerprint.md#post), which -requires that the package root directory has already been verified and package -metadata is valid. +/api/package/{fingerprint}`](api/package-fingerprint.md#post), which requires +that the package root directory has already been verified and package metadata +is valid. Finally, the revision is verified and the package number obtained using [`POST -/api/revision/{revision}`](routes/api-revision-revision.md#post), which -requires that the package has been verified and the revision has been uploaded -and is valid. +/api/revision/{revision}`](api/revision-revision.md#post), which requires that +the package has been verified and the revision has been uploaded and is valid. Downloading Packages -------------------- diff --git a/crates/generate/src/main.rs b/crates/generate/src/main.rs index 0dca9c0b..c319dadd 100644 --- a/crates/generate/src/main.rs +++ b/crates/generate/src/main.rs @@ -5,9 +5,9 @@ use { functions::{escape, list, path_parameter_type, route_link, route_path, write}, row::Row, templates::{ - AuthoringMetadataMd, CommandMd, CommandsMd, ContentTypesMd, DecoMd, DecoSchemaMd, HexMd, - JsonMd, JsonSchemaMd, LanguagesMd, LintsMd, MediaFormatsMd, RouteMd, RoutesMd, SummaryMd, - TagMd, UnstableFeaturesMd, YamlMd, + ApiMd, AuthoringMetadataMd, CommandMd, CommandsMd, ContentTypesMd, DecoMd, DecoSchemaMd, + HexMd, JsonMd, JsonSchemaMd, LanguagesMd, LintsMd, MediaFormatsMd, RouteMd, SummaryMd, TagMd, + UnstableFeaturesMd, WebMd, YamlMd, }, }, boilerplate::Boilerplate, @@ -123,17 +123,26 @@ fn main() { pages }; - let routes = { - let mut routes = BTreeMap::new(); - + let mut api = BTreeMap::new(); + let mut web = BTreeMap::new(); + { for (route_path, route) in &reference.routes { - let slug = if route_path.ends_with('/') { - format!("{route_path}index").to_kebab_case() + let relative = if route.api { + route_path.strip_prefix("/api").unwrap() + } else { + route_path.as_str() + }; + + let slug = if relative.ends_with('/') { + format!("{relative}index").to_kebab_case() } else { - route_path.to_kebab_case() + relative.to_kebab_case() }; - let path = Utf8PathBuf::from(format!("routes/{slug}.md")); + let path = Utf8PathBuf::from(format!( + "{}/{slug}.md", + if route.api { "api" } else { "web" }, + )); write( &path, @@ -144,11 +153,13 @@ fn main() { }, ); - routes.insert(route_path.as_str(), path); + if route.api { + api.insert(route_path.as_str(), path); + } else { + web.insert(route_path.as_str(), path); + } } - - routes - }; + } let json = { let mut pages = BTreeMap::new(); @@ -202,6 +213,14 @@ fn main() { pages }; + write( + "api.md", + ApiMd { + pages: &api, + routes: &reference.routes, + }, + ); + write("commands.md", CommandsMd { pages: &commands }); write( @@ -258,9 +277,9 @@ fn main() { ); write( - "routes.md", - RoutesMd { - pages: &routes, + "web.md", + WebMd { + pages: &web, routes: &reference.routes, }, ); @@ -289,11 +308,12 @@ fn main() { write( "SUMMARY.md", SummaryMd { + api, commands, deco, hex, json, - routes, + web, yaml, }, ); diff --git a/crates/generate/src/templates.rs b/crates/generate/src/templates.rs index 0cc490b1..dc1ef6d5 100644 --- a/crates/generate/src/templates.rs +++ b/crates/generate/src/templates.rs @@ -1,5 +1,11 @@ use super::*; +#[derive(Boilerplate)] +pub(crate) struct ApiMd<'a> { + pub(crate) pages: &'a BTreeMap<&'a str, Utf8PathBuf>, + pub(crate) routes: &'a BTreeMap, +} + #[derive(Boilerplate)] pub(crate) struct AuthoringMetadataMd<'a> { pub(crate) example: &'a yaml::Example, @@ -99,19 +105,14 @@ pub(crate) struct RouteMd<'a> { pub(crate) route: &'a Route, } -#[derive(Boilerplate)] -pub(crate) struct RoutesMd<'a> { - pub(crate) pages: &'a BTreeMap<&'a str, Utf8PathBuf>, - pub(crate) routes: &'a BTreeMap, -} - #[derive(Boilerplate)] pub(crate) struct SummaryMd<'a> { + pub(crate) api: BTreeMap<&'a str, Utf8PathBuf>, pub(crate) commands: BTreeMap, pub(crate) deco: BTreeMap<&'a str, Utf8PathBuf>, pub(crate) hex: BTreeMap<&'a str, Utf8PathBuf>, pub(crate) json: BTreeMap<&'a str, Utf8PathBuf>, - pub(crate) routes: BTreeMap<&'a str, Utf8PathBuf>, + pub(crate) web: BTreeMap<&'a str, Utf8PathBuf>, pub(crate) yaml: BTreeMap<&'a str, Utf8PathBuf>, } @@ -126,6 +127,12 @@ pub(crate) struct UnstableFeaturesMd<'a> { pub(crate) features: &'a BTreeMap, } +#[derive(Boilerplate)] +pub(crate) struct WebMd<'a> { + pub(crate) pages: &'a BTreeMap<&'a str, Utf8PathBuf>, + pub(crate) routes: &'a BTreeMap, +} + #[derive(Boilerplate)] pub(crate) struct YamlMd<'a> { pub(crate) yaml: &'a json::Registry, diff --git a/crates/generate/templates/api.md b/crates/generate/templates/api.md new file mode 100644 index 00000000..d2b4d5c2 --- /dev/null +++ b/crates/generate/templates/api.md @@ -0,0 +1,16 @@ +API +=== + +The Filepack server responds to the following API routes: + +| method | path | description | +|--------|------|-------------| +%% for (path, page) in self.pages { +%% for (method, endpoint) in &self.routes[*path].methods { +{{ Row(( + method, + route_link(path, page), + &endpoint.description, +)) }} +%% } +%% } diff --git a/crates/generate/templates/routes.md b/crates/generate/templates/routes.md deleted file mode 100644 index cdda21ef..00000000 --- a/crates/generate/templates/routes.md +++ /dev/null @@ -1,40 +0,0 @@ -Routes -====== - -The Filepack server responds to the following API routes: - -| method | path | description | -|--------|------|-------------| -%% for (path, route) in self.routes.iter().filter(|(_, route)| route.api) { -%% for (method, endpoint) in &route.methods { -{{ Row(( - method, - route_link(path, &self.pages[path.as_str()]), - &endpoint.description, -)) }} -%% } -%% } - -And the following web routes: - -| method | path | description | -|--------|------|-------------| -%% for (path, route) in self.routes.iter().filter(|(_, route)| !route.api) { -%% for (method, endpoint) in &route.methods { -{{ Row(( - method, - route_link(path, &self.pages[path.as_str()]), - &endpoint.description, -)) }} -%% } -%% } - -And the following fallback routes, if no other route matches: - -| method | path | description | -|--------|------|-------------| -| GET | `/{fingerprint}` | Redirect to [`/package/{fingerprint}`](routes/package-package.md) | -| GET | `/{number}` | Redirect to [`/package/{number}`](routes/package-package.md) | -| GET | `/{revision}` | Redirect to [`/package/{revision}`](routes/package-package.md) | -| GET | `/{name}/` | Serve `static/index.html` of mounted web package with `name` | -| GET | `/{name}/{*path}` | Serve file at `static/{path}` of mounted web package with `name` | diff --git a/crates/generate/templates/summary.md b/crates/generate/templates/summary.md index 62c06141..297c6cdc 100644 --- a/crates/generate/templates/summary.md +++ b/crates/generate/templates/summary.md @@ -19,6 +19,10 @@ Summary - [Alternatives and Prior Art](alternatives.md) # Reference +- [API](api.md) +%% for (path, page) in &self.api { + - [{{ escape(path) }}]({{ page }}) +%% } - [Commands](commands.md) %% for (name, (_command, path)) in &self.commands { - [{{ name }}]({{ path }}) @@ -35,15 +39,15 @@ Summary - [Languages](languages.md) - [Lints](lints.md) - [Media Formats](media-formats.md) -- [Routes](routes.md) -%% for (path, relative) in &self.routes { - - [{{ escape(path) }}]({{ relative }}) -%% } - [Tagged Hex](hex.md) %% for (tag, path) in &self.hex { - [{{ tag }}]({{ path }}) %% } - [Unstable Features](unstable-features.md) +- [Web](web.md) +%% for (path, page) in &self.web { + - [{{ escape(path) }}]({{ page }}) +%% } - [YAML](yaml.md) %% for (name, path) in &self.yaml { - [{{ escape(name) }}]({{ path }}) diff --git a/crates/generate/templates/web.md b/crates/generate/templates/web.md new file mode 100644 index 00000000..1e284a9a --- /dev/null +++ b/crates/generate/templates/web.md @@ -0,0 +1,26 @@ +Web +=== + +The Filepack server responds to the following web routes: + +| method | path | description | +|--------|------|-------------| +%% for (path, page) in self.pages { +%% for (method, endpoint) in &self.routes[*path].methods { +{{ Row(( + method, + route_link(path, page), + &endpoint.description, +)) }} +%% } +%% } + +And the following fallback routes, if no other route matches: + +| method | path | description | +|--------|------|-------------| +| GET | `/{fingerprint}` | Redirect to [`/package/{fingerprint}`](web/package-package.md) | +| GET | `/{number}` | Redirect to [`/package/{number}`](web/package-package.md) | +| GET | `/{revision}` | Redirect to [`/package/{revision}`](web/package-package.md) | +| GET | `/{name}/` | Serve `static/index.html` of mounted web package with `name` | +| GET | `/{name}/{*path}` | Serve file at `static/{path}` of mounted web package with `name` |