-
Notifications
You must be signed in to change notification settings - Fork 136
/
Copy pathlib.rs
134 lines (126 loc) · 5.1 KB
/
lib.rs
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
//! [SQLPage](https://sql-page.com) is a high-performance web server that converts SQL queries
//! into dynamic web applications by rendering [handlebars templates](https://sql-page.com/custom_components.sql)
//! with data coming from SQL queries declared in `.sql` files.
//!
//! # Overview
//!
//! `SQLPage` is a web server that lets you build data-centric applications using only SQL queries.
//! It automatically converts database queries into professional-looking web pages using pre-built components
//! for common UI patterns like [tables](https://sql-page.com/component.sql?component=table),
//! [charts](https://sql-page.com/component.sql?component=chart),
//! [forms](https://sql-page.com/component.sql?component=form), and more.
//!
//! # Key Features
//!
//! - **SQL-Only Development**: Build full web applications without HTML, CSS, or JavaScript
//! - **Built-in Components**: Rich library of [pre-made UI components](https://sql-page.com/documentation.sql)
//! - **Security**: Protection against [SQL injection, XSS and other vulnerabilities](https://sql-page.com/safety.sql)
//! - **Performance**: [Optimized request handling and rendering](https://sql-page.com/performance.sql)
//! - **Database Support**: Works with `SQLite`, `PostgreSQL`, `MySQL`, and MS SQL Server
//!
//! # Architecture
//!
//! The crate is organized into several key modules:
//!
//! - [`webserver`]: Core HTTP server implementation using actix-web
//! - [`render`]: Component rendering system, streaming rendering of the handlebars templates with data
//! - [`templates`]: Pre-defined UI component definitions
//! - [`file_cache`]: Caching layer for SQL file parsing
//! - [`filesystem`]: Abstract interface for disk and DB-stored files
//! - [`app_config`]: Configuration and environment handling
//!
//! # Query Processing Pipeline
//!
//! When processing a request, `SQLPage`:
//!
//! 1. Parses the SQL using sqlparser-rs. Once a SQL file is parsed, it is cached for later reuse.
//! 2. Executes queries through sqlx.
//! 3. Finds the requested component's handlebars template in the database or in the filesystem.
//! 4. Maps results to the component template, using handlebars-rs.
//! 5. Streams rendered HTML to the client.
//!
//! # Extended Functionality
//!
//! - [Custom SQL Functions](https://sql-page.com/functions.sql)
//! - [Custom Components](https://sql-page.com/custom_components.sql)
//! - [Authentication & Sessions](https://sql-page.com/examples/authentication)
//! - [File Uploads](https://sql-page.com/examples/handle_picture_upload.sql)
//!
//! # Example
//!
//! ```sql
//! -- Open a data list component
//! SELECT 'list' as component, 'Users' as title;
//!
//! -- Populate it with data
//! SELECT
//! name as title,
//! email as description
//! FROM users
//! ORDER BY created_at DESC;
//! ```
//!
//! For more examples and documentation, visit:
//! - [Getting Started Guide](https://sql-page.com/get%20started.sql)
//! - [Component Reference](https://sql-page.com/components.sql)
//! - [Example Gallery](https://sql-page.com/examples/tabs)
extern crate core;
pub mod app_config;
pub mod dynamic_component;
pub mod file_cache;
pub mod filesystem;
pub mod render;
pub mod template_helpers;
pub mod templates;
pub mod utils;
pub mod webserver;
use crate::app_config::AppConfig;
use crate::filesystem::FileSystem;
use crate::webserver::database::ParsedSqlFile;
use file_cache::FileCache;
use std::path::{Path, PathBuf};
use templates::AllTemplates;
use webserver::Database;
/// `TEMPLATES_DIR` is the directory where .handlebars files are stored
/// When a template is requested, it is looked up in `sqlpage/templates/component_name.handlebars` in the database,
/// or in `$SQLPAGE_CONFIGURATION_DIRECTORY/templates/component_name.handlebars` in the filesystem.
pub const TEMPLATES_DIR: &str = "sqlpage/templates/";
pub const MIGRATIONS_DIR: &str = "migrations";
pub const ON_CONNECT_FILE: &str = "on_connect.sql";
pub const ON_RESET_FILE: &str = "on_reset.sql";
pub struct AppState {
pub db: Database,
all_templates: AllTemplates,
sql_file_cache: FileCache<ParsedSqlFile>,
file_system: FileSystem,
config: AppConfig,
}
impl AppState {
pub async fn init(config: &AppConfig) -> anyhow::Result<Self> {
let db = Database::init(config).await?;
Self::init_with_db(config, db).await
}
pub async fn init_with_db(config: &AppConfig, db: Database) -> anyhow::Result<Self> {
let all_templates = AllTemplates::init(config)?;
let mut sql_file_cache = FileCache::new();
let file_system = FileSystem::init(&config.web_root, &db).await;
sql_file_cache.add_static(
PathBuf::from("index.sql"),
ParsedSqlFile::new(&db, include_str!("../index.sql"), Path::new("index.sql")),
);
Ok(AppState {
db,
all_templates,
sql_file_cache,
file_system,
config: config.clone(),
})
}
}
impl std::fmt::Debug for AppState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AppState").finish()
}
}