1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
/*!
 * Perseus is a blazingly fast frontend web development framework built in Rust with support for major rendering strategies,
 * reactivity without a virtual DOM, and extreme customizability. It wraps the lower-level capabilities of[Sycamore](https://github.com/sycamore-rs/sycamore)
 * and provides a NextJS-like API!
 *
 * - ✨ Supports static generation (serving only static resources)
 * - ✨ Supports server-side rendering (serving dynamic resources)
 * - ✨ Supports revalidation after time and/or with custom logic (updating rendered pages)
 * - ✨ Supports incremental regeneration (build on demand)
 * - ✨ Open build matrix (use any rendering strategy with anything else, mostly)
 * - ✨ CLI harness that lets you build apps with ease and confidence
 *
 * This is the documentation for the Perseus CLI, but there's also [the core package](https://crates.io/crates/perseus) and [integrations](https://arctic-hen7.github.io/perseus/serving.html)
 * to make serving apps on other platforms easier!
 *
 * # Resources
 *
 * These docs will help you as a reference, but [the book](https://arctic-hen7.github.io/perseus/cli.html) should
 * be your first port of call for learning about how to use Perseus and how it works.
 *
 * - [The Book](https://arctic-hen7.github.io/perseus)
 * - [GitHub repository](https://github.com/arctic-hen7/perseus)
 * - [Crate page](https://crates.io/crates/perseus)
 * - [Gitter chat](https://gitter.im/perseus-framework/community)
 * - [Discord server channel](https://discord.com/channels/820400041332179004/883168134331256892) (for Sycamore-related stuff)
 */

#![deny(missing_docs)]

mod build;
mod cmd;
mod eject;
pub mod errors;
mod export;
/// Parsing utilities for arguments.
pub mod parse;
mod prepare;
mod serve;
mod serve_exported;
mod snoop;
mod thread;
mod tinker;

mod deploy;
mod extraction;

use errors::*;
use std::fs;
use std::path::PathBuf;

/// The current version of the CLI, extracted from the crate version.
pub const PERSEUS_VERSION: &str = env!("CARGO_PKG_VERSION");
pub use build::build;
pub use deploy::deploy;
pub use eject::{eject, has_ejected};
pub use export::export;
pub use prepare::{check_env, prepare};
pub use serve::serve;
pub use serve_exported::serve_exported;
pub use snoop::{snoop_build, snoop_server, snoop_wasm_build};
pub use tinker::tinker;

/// Deletes a corrupted '.perseus/' directory. This will be called on certain error types that would leave the user with a half-finished
/// product, which is better to delete for safety and sanity.
pub fn delete_bad_dir(dir: PathBuf) -> Result<(), PrepError> {
    let mut target = dir;
    target.extend([".perseus"]);
    // We'll only delete the directory if it exists, otherwise we're fine
    if target.exists() {
        if let Err(err) = fs::remove_dir_all(&target) {
            return Err(PrepError::RemoveBadDirFailed { source: err });
        }
    }
    Ok(())
}

/// Deletes build artifacts in `.perseus/dist/static` or `.perseus/dist/pkg` and replaces the directory.
pub fn delete_artifacts(dir: PathBuf, dir_to_remove: &str) -> Result<(), ExecutionError> {
    let mut target = dir;
    target.extend([".perseus", "dist", dir_to_remove]);
    // We'll only delete the directory if it exists, otherwise we're fine
    if target.exists() {
        if let Err(err) = fs::remove_dir_all(&target) {
            return Err(ExecutionError::RemoveArtifactsFailed {
                target: target.to_str().map(|s| s.to_string()),
                source: err,
            });
        }
    }
    // No matter what, it's gone now, so recreate it
    // We also create parent directories because that's an issue for some reason in Docker (see #69)
    if let Err(err) = fs::create_dir_all(&target) {
        return Err(ExecutionError::RemoveArtifactsFailed {
            target: target.to_str().map(|s| s.to_string()),
            source: err,
        });
    }

    Ok(())
}