- Static compiler with STRC pattern (Static Template Resolution with
Compartmentalized Layers)
- Template syntax: { } interpolation, { s-for }, { s-if/s-elif/s-else
}
- File types: .strata, .compiler.sts, .service.sts, .api.sts, .sts,
.scss
- CLI tools: strata dev, strata build, strata g (generators)
- create-strata scaffolding CLI with Pokemon API example
- Dev server with WebSocket HMR (Hot Module Replacement)
- Documentation: README, ARCHITECTURE, CHANGELOG, CONTRIBUTING,
LICENSE
625 lines
19 KiB
Bash
Executable File
625 lines
19 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Strata Framework - Local Installation Script
|
|
# Usage: ./scripts/install.sh [options]
|
|
# --global Install globally to /usr/local
|
|
# --local Install locally only (default)
|
|
# --skip-deps Skip dependency checks
|
|
# --no-shell Skip shell configuration
|
|
# --help Show this help message
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
BOLD='\033[1m'
|
|
|
|
# Installation directories
|
|
STRATA_HOME="${STRATA_HOME:-$HOME/.strata}"
|
|
STRATA_BIN="$STRATA_HOME/bin"
|
|
STRATA_COMPLETIONS="$STRATA_HOME/completions"
|
|
STRATA_CONFIG="$STRATA_HOME/config"
|
|
LOCAL_BIN="/usr/local/bin"
|
|
|
|
# Script directory (where strata repo is)
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
|
|
|
# Default options
|
|
INSTALL_GLOBAL=false
|
|
SKIP_DEPS=false
|
|
SKIP_SHELL=false
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--global)
|
|
INSTALL_GLOBAL=true
|
|
shift
|
|
;;
|
|
--local)
|
|
INSTALL_GLOBAL=false
|
|
shift
|
|
;;
|
|
--skip-deps)
|
|
SKIP_DEPS=true
|
|
shift
|
|
;;
|
|
--no-shell)
|
|
SKIP_SHELL=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
echo "Strata Framework - Installation Script"
|
|
echo ""
|
|
echo "Usage: ./scripts/install.sh [options]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --global Install globally to /usr/local/bin (requires sudo)"
|
|
echo " --local Install locally to ~/.strata (default)"
|
|
echo " --skip-deps Skip dependency version checks"
|
|
echo " --no-shell Skip shell configuration (PATH, completions)"
|
|
echo " --help Show this help message"
|
|
echo ""
|
|
echo "Environment Variables:"
|
|
echo " STRATA_HOME Installation directory (default: ~/.strata)"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown option: $1${NC}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Print banner
|
|
print_banner() {
|
|
echo ""
|
|
echo -e "${CYAN}"
|
|
echo " ╔═══════════════════════════════════════════════════════╗"
|
|
echo " ║ ║"
|
|
echo " ║ ███████╗████████╗██████╗ █████╗ ████████╗ █████╗ ║"
|
|
echo " ║ ██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗ ║"
|
|
echo " ║ ███████╗ ██║ ██████╔╝███████║ ██║ ███████║ ║"
|
|
echo " ║ ╚════██║ ██║ ██╔══██╗██╔══██║ ██║ ██╔══██║ ║"
|
|
echo " ║ ███████║ ██║ ██║ ██║██║ ██║ ██║ ██║ ██║ ║"
|
|
echo " ║ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ║"
|
|
echo " ║ ║"
|
|
echo " ║ Static Template Rendering Architecture ║"
|
|
echo " ╚═══════════════════════════════════════════════════════╝"
|
|
echo -e "${NC}"
|
|
echo ""
|
|
}
|
|
|
|
# Print step
|
|
print_step() {
|
|
echo -e "${BLUE}▶${NC} $1"
|
|
}
|
|
|
|
# Print success
|
|
print_success() {
|
|
echo -e "${GREEN}✓${NC} $1"
|
|
}
|
|
|
|
# Print warning
|
|
print_warning() {
|
|
echo -e "${YELLOW}⚠${NC} $1"
|
|
}
|
|
|
|
# Print error
|
|
print_error() {
|
|
echo -e "${RED}✗${NC} $1"
|
|
}
|
|
|
|
# Check if command exists
|
|
command_exists() {
|
|
command -v "$1" &> /dev/null
|
|
}
|
|
|
|
# Get version number from version string
|
|
get_version() {
|
|
echo "$1" | grep -oE '[0-9]+\.[0-9]+' | head -1
|
|
}
|
|
|
|
# Compare versions (returns 0 if $1 >= $2)
|
|
version_gte() {
|
|
[ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
|
|
}
|
|
|
|
# Check system requirements
|
|
check_requirements() {
|
|
print_step "Checking system requirements..."
|
|
echo ""
|
|
|
|
local requirements_met=true
|
|
|
|
# Check Go
|
|
if command_exists go; then
|
|
GO_VERSION=$(go version | grep -oE 'go[0-9]+\.[0-9]+' | sed 's/go//')
|
|
if version_gte "$GO_VERSION" "1.21"; then
|
|
print_success "Go $GO_VERSION (required: >= 1.21)"
|
|
else
|
|
print_warning "Go $GO_VERSION found, but >= 1.21 is recommended"
|
|
fi
|
|
else
|
|
print_error "Go is not installed"
|
|
echo " Install from: https://go.dev/dl/"
|
|
echo " Or use: brew install go (macOS)"
|
|
echo " sudo apt install golang-go (Ubuntu/Debian)"
|
|
requirements_met=false
|
|
fi
|
|
|
|
# Check Node.js
|
|
if command_exists node; then
|
|
NODE_VERSION=$(node -v | sed 's/v//')
|
|
NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
|
|
if [ "$NODE_MAJOR" -ge 18 ]; then
|
|
print_success "Node.js $NODE_VERSION (required: >= 18.0)"
|
|
else
|
|
print_warning "Node.js $NODE_VERSION found, but >= 18.0 is required"
|
|
requirements_met=false
|
|
fi
|
|
else
|
|
print_error "Node.js is not installed"
|
|
echo " Install from: https://nodejs.org/"
|
|
echo " Or use: brew install node (macOS)"
|
|
echo " nvm install 20 (using nvm)"
|
|
requirements_met=false
|
|
fi
|
|
|
|
# Check npm
|
|
if command_exists npm; then
|
|
NPM_VERSION=$(npm -v)
|
|
print_success "npm $NPM_VERSION"
|
|
else
|
|
print_error "npm is not installed"
|
|
requirements_met=false
|
|
fi
|
|
|
|
# Check git
|
|
if command_exists git; then
|
|
GIT_VERSION=$(git --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
|
print_success "Git $GIT_VERSION"
|
|
else
|
|
print_warning "Git is not installed (optional, but recommended)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
if [ "$requirements_met" = false ] && [ "$SKIP_DEPS" = false ]; then
|
|
print_error "Some requirements are not met. Install missing dependencies and try again."
|
|
echo " Or run with --skip-deps to continue anyway (not recommended)."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Create directory structure
|
|
create_directories() {
|
|
print_step "Creating Strata directories..."
|
|
|
|
mkdir -p "$STRATA_HOME"
|
|
mkdir -p "$STRATA_BIN"
|
|
mkdir -p "$STRATA_COMPLETIONS"
|
|
mkdir -p "$STRATA_CONFIG"
|
|
mkdir -p "$REPO_DIR/bin"
|
|
|
|
print_success "Created $STRATA_HOME"
|
|
}
|
|
|
|
# Build Go compiler
|
|
build_compiler() {
|
|
print_step "Building Strata compiler..."
|
|
|
|
cd "$REPO_DIR/compiler"
|
|
|
|
# Download Go dependencies
|
|
echo " Downloading Go dependencies..."
|
|
go mod tidy
|
|
go mod download
|
|
|
|
# Build the compiler
|
|
echo " Compiling..."
|
|
go build -ldflags="-s -w" -o "$REPO_DIR/bin/strata" ./cmd/strata
|
|
|
|
# Copy to strata home
|
|
cp "$REPO_DIR/bin/strata" "$STRATA_BIN/strata"
|
|
chmod +x "$STRATA_BIN/strata"
|
|
|
|
# Copy create-strata CLI
|
|
if [ -f "$REPO_DIR/bin/create-strata" ]; then
|
|
cp "$REPO_DIR/bin/create-strata" "$STRATA_BIN/create-strata"
|
|
chmod +x "$STRATA_BIN/create-strata"
|
|
fi
|
|
|
|
cd "$REPO_DIR"
|
|
|
|
print_success "Compiler built successfully"
|
|
}
|
|
|
|
# Install npm dependencies
|
|
install_npm_deps() {
|
|
print_step "Installing npm dependencies..."
|
|
|
|
cd "$REPO_DIR"
|
|
npm install --silent
|
|
|
|
print_success "npm dependencies installed"
|
|
}
|
|
|
|
# Install globally
|
|
install_global() {
|
|
if [ "$INSTALL_GLOBAL" = true ]; then
|
|
print_step "Installing globally to $LOCAL_BIN..."
|
|
|
|
if [ -w "$LOCAL_BIN" ]; then
|
|
ln -sf "$STRATA_BIN/strata" "$LOCAL_BIN/strata"
|
|
print_success "Linked strata to $LOCAL_BIN/strata"
|
|
else
|
|
echo " Requires sudo to write to $LOCAL_BIN"
|
|
sudo ln -sf "$STRATA_BIN/strata" "$LOCAL_BIN/strata"
|
|
print_success "Linked strata to $LOCAL_BIN/strata (with sudo)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Detect shell (use $SHELL env var which reflects user's login shell)
|
|
detect_shell() {
|
|
basename "${SHELL:-/bin/bash}"
|
|
}
|
|
|
|
# Get shell config file
|
|
get_shell_config() {
|
|
local shell_type="$1"
|
|
case "$shell_type" in
|
|
zsh)
|
|
echo "$HOME/.zshrc"
|
|
;;
|
|
bash)
|
|
if [ -f "$HOME/.bash_profile" ]; then
|
|
echo "$HOME/.bash_profile"
|
|
else
|
|
echo "$HOME/.bashrc"
|
|
fi
|
|
;;
|
|
fish)
|
|
echo "$HOME/.config/fish/config.fish"
|
|
;;
|
|
*)
|
|
echo "$HOME/.profile"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Configure shell
|
|
configure_shell() {
|
|
if [ "$SKIP_SHELL" = true ]; then
|
|
return
|
|
fi
|
|
|
|
print_step "Configuring shell..."
|
|
|
|
local shell_type=$(detect_shell)
|
|
local shell_config=$(get_shell_config "$shell_type")
|
|
local strata_marker="# Strata Framework"
|
|
|
|
# Check if already configured
|
|
if [ -f "$shell_config" ] && grep -q "$strata_marker" "$shell_config"; then
|
|
print_success "Shell already configured in $shell_config"
|
|
return
|
|
fi
|
|
|
|
# Create backup
|
|
if [ -f "$shell_config" ]; then
|
|
cp "$shell_config" "${shell_config}.backup.$(date +%Y%m%d%H%M%S)"
|
|
fi
|
|
|
|
# Add Strata configuration
|
|
cat >> "$shell_config" << 'SHELL_CONFIG'
|
|
|
|
# Strata Framework
|
|
export STRATA_HOME="$HOME/.strata"
|
|
export PATH="$STRATA_HOME/bin:$PATH"
|
|
|
|
# Strata aliases
|
|
alias st='strata'
|
|
alias stdev='strata dev'
|
|
alias stbuild='strata build'
|
|
alias stgen='strata generate'
|
|
alias stnew='create-strata'
|
|
|
|
# Strata completions
|
|
SHELL_CONFIG
|
|
|
|
# Add shell-specific completion loading
|
|
case "$shell_type" in
|
|
zsh)
|
|
cat >> "$shell_config" << 'ZSH_COMPLETION'
|
|
if [ -f "$STRATA_HOME/completions/_strata" ]; then
|
|
fpath=($STRATA_HOME/completions $fpath)
|
|
autoload -Uz compinit && compinit
|
|
fi
|
|
ZSH_COMPLETION
|
|
;;
|
|
bash)
|
|
cat >> "$shell_config" << 'BASH_COMPLETION'
|
|
if [ -f "$STRATA_HOME/completions/strata.bash" ]; then
|
|
source "$STRATA_HOME/completions/strata.bash"
|
|
fi
|
|
BASH_COMPLETION
|
|
;;
|
|
fish)
|
|
cat >> "$shell_config" << 'FISH_COMPLETION'
|
|
if test -f "$STRATA_HOME/completions/strata.fish"
|
|
source "$STRATA_HOME/completions/strata.fish"
|
|
end
|
|
FISH_COMPLETION
|
|
;;
|
|
esac
|
|
|
|
print_success "Added Strata configuration to $shell_config"
|
|
}
|
|
|
|
# Generate and install completions
|
|
install_completions() {
|
|
if [ "$SKIP_SHELL" = true ]; then
|
|
return
|
|
fi
|
|
|
|
print_step "Installing shell completions..."
|
|
|
|
# Generate bash completion
|
|
cat > "$STRATA_COMPLETIONS/strata.bash" << 'BASH_COMP'
|
|
# Strata bash completion
|
|
|
|
_strata_completions() {
|
|
local cur prev opts
|
|
COMPREPLY=()
|
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
|
|
# Main commands
|
|
local commands="dev build preview generate init help version"
|
|
|
|
# Generate subcommands
|
|
local generate_types="component page store layout middleware"
|
|
|
|
case "$prev" in
|
|
strata|st)
|
|
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
|
|
return 0
|
|
;;
|
|
generate|g)
|
|
COMPREPLY=( $(compgen -W "$generate_types" -- "$cur") )
|
|
return 0
|
|
;;
|
|
dev)
|
|
COMPREPLY=( $(compgen -W "--port --open --host" -- "$cur") )
|
|
return 0
|
|
;;
|
|
build)
|
|
COMPREPLY=( $(compgen -W "--analyze --watch --minify --sourcemap" -- "$cur") )
|
|
return 0
|
|
;;
|
|
preview)
|
|
COMPREPLY=( $(compgen -W "--port --host" -- "$cur") )
|
|
return 0
|
|
;;
|
|
--port)
|
|
COMPREPLY=( $(compgen -W "3000 3001 4000 5000 8080" -- "$cur") )
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
# Default: show all commands
|
|
if [[ "$cur" == -* ]]; then
|
|
COMPREPLY=( $(compgen -W "--help --version" -- "$cur") )
|
|
else
|
|
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
|
|
fi
|
|
}
|
|
|
|
complete -F _strata_completions strata
|
|
complete -F _strata_completions st
|
|
BASH_COMP
|
|
|
|
# Generate zsh completion
|
|
cat > "$STRATA_COMPLETIONS/_strata" << 'ZSH_COMP'
|
|
#compdef strata st
|
|
|
|
# Strata zsh completion
|
|
|
|
_strata() {
|
|
local -a commands
|
|
local -a generate_types
|
|
|
|
commands=(
|
|
'dev:Start development server with hot reload'
|
|
'build:Build for production'
|
|
'preview:Preview production build'
|
|
'generate:Generate component, page, or store'
|
|
'init:Initialize new Strata project'
|
|
'help:Show help information'
|
|
'version:Show version information'
|
|
)
|
|
|
|
generate_types=(
|
|
'component:Generate a new component'
|
|
'page:Generate a new page'
|
|
'store:Generate a new store'
|
|
'layout:Generate a new layout'
|
|
'middleware:Generate a new middleware'
|
|
)
|
|
|
|
_arguments -C \
|
|
'1: :->command' \
|
|
'*: :->args'
|
|
|
|
case "$state" in
|
|
command)
|
|
_describe -t commands 'strata commands' commands
|
|
;;
|
|
args)
|
|
case "$words[2]" in
|
|
generate|g)
|
|
if [[ $CURRENT -eq 3 ]]; then
|
|
_describe -t generate_types 'generate types' generate_types
|
|
else
|
|
_files
|
|
fi
|
|
;;
|
|
dev)
|
|
_arguments \
|
|
'--port[Port number]:port:(3000 3001 4000 5000 8080)' \
|
|
'--open[Open browser automatically]' \
|
|
'--host[Host to bind]:host:(localhost 0.0.0.0)'
|
|
;;
|
|
build)
|
|
_arguments \
|
|
'--analyze[Analyze bundle size]' \
|
|
'--watch[Watch for changes]' \
|
|
'--minify[Minify output]' \
|
|
'--sourcemap[Generate sourcemaps]'
|
|
;;
|
|
preview)
|
|
_arguments \
|
|
'--port[Port number]:port:(4000 5000 8080)' \
|
|
'--host[Host to bind]:host:(localhost 0.0.0.0)'
|
|
;;
|
|
*)
|
|
_files
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_strata "$@"
|
|
ZSH_COMP
|
|
|
|
# Generate fish completion
|
|
cat > "$STRATA_COMPLETIONS/strata.fish" << 'FISH_COMP'
|
|
# Strata fish completion
|
|
|
|
# Main commands
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "dev" -d "Start development server"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "build" -d "Build for production"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "preview" -d "Preview production build"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "generate" -d "Generate component/page/store"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "init" -d "Initialize new project"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "help" -d "Show help"
|
|
complete -c strata -f -n "__fish_use_subcommand" -a "version" -d "Show version"
|
|
|
|
# Generate subcommands
|
|
complete -c strata -f -n "__fish_seen_subcommand_from generate" -a "component" -d "Generate component"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from generate" -a "page" -d "Generate page"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from generate" -a "store" -d "Generate store"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from generate" -a "layout" -d "Generate layout"
|
|
|
|
# Dev options
|
|
complete -c strata -f -n "__fish_seen_subcommand_from dev" -l port -d "Port number"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from dev" -l open -d "Open browser"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from dev" -l host -d "Host to bind"
|
|
|
|
# Build options
|
|
complete -c strata -f -n "__fish_seen_subcommand_from build" -l analyze -d "Analyze bundle"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from build" -l watch -d "Watch mode"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from build" -l minify -d "Minify output"
|
|
complete -c strata -f -n "__fish_seen_subcommand_from build" -l sourcemap -d "Generate sourcemaps"
|
|
|
|
# Alias
|
|
complete -c st -w strata
|
|
FISH_COMP
|
|
|
|
print_success "Shell completions installed"
|
|
}
|
|
|
|
# Create config file
|
|
create_config() {
|
|
print_step "Creating configuration..."
|
|
|
|
# Create global strata config
|
|
cat > "$STRATA_CONFIG/strata.json" << CONFIG
|
|
{
|
|
"version": "0.1.0",
|
|
"installPath": "$STRATA_HOME",
|
|
"repoPath": "$REPO_DIR",
|
|
"installedAt": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
"shell": {
|
|
"configured": $([ "$SKIP_SHELL" = true ] && echo "false" || echo "true"),
|
|
"completions": $([ "$SKIP_SHELL" = true ] && echo "false" || echo "true")
|
|
},
|
|
"global": $INSTALL_GLOBAL
|
|
}
|
|
CONFIG
|
|
|
|
print_success "Configuration created at $STRATA_CONFIG/strata.json"
|
|
}
|
|
|
|
# Print success message
|
|
print_final() {
|
|
echo ""
|
|
echo -e "${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} Installation Complete! ${NC}"
|
|
echo -e "${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
echo -e " ${BOLD}Strata has been installed to:${NC} $STRATA_HOME"
|
|
echo ""
|
|
echo -e " ${BOLD}Quick Start:${NC}"
|
|
echo ""
|
|
echo " 1. Restart your terminal or run:"
|
|
echo -e " ${CYAN}source $(get_shell_config $(detect_shell))${NC}"
|
|
echo ""
|
|
echo " 2. Create a new project:"
|
|
echo -e " ${CYAN}npx create-strata my-app${NC}"
|
|
echo -e " ${CYAN}cd my-app${NC}"
|
|
echo -e " ${CYAN}npm install${NC}"
|
|
echo -e " ${CYAN}strata dev${NC}"
|
|
echo ""
|
|
echo " Or try the example app:"
|
|
echo -e " ${CYAN}cd $REPO_DIR/examples/basic-app${NC}"
|
|
echo -e " ${CYAN}strata dev${NC}"
|
|
echo ""
|
|
echo -e " ${BOLD}Available Commands:${NC}"
|
|
echo ""
|
|
echo " strata dev Start dev server with hot reload"
|
|
echo " strata build Build for production"
|
|
echo " strata preview Preview production build"
|
|
echo " strata generate Generate component/page/store"
|
|
echo ""
|
|
echo -e " ${BOLD}Aliases:${NC}"
|
|
echo ""
|
|
echo " st → strata"
|
|
echo " stdev → strata dev"
|
|
echo " stbuild → strata build"
|
|
echo " stgen → strata generate"
|
|
echo " stnew → npx create-strata"
|
|
echo ""
|
|
echo -e " ${BOLD}Documentation:${NC} https://stratajs.dev/docs"
|
|
echo -e " ${BOLD}GitHub:${NC} https://github.com/strata/strata"
|
|
echo ""
|
|
}
|
|
|
|
# Main installation
|
|
main() {
|
|
print_banner
|
|
|
|
check_requirements
|
|
create_directories
|
|
build_compiler
|
|
install_npm_deps
|
|
install_global
|
|
configure_shell
|
|
install_completions
|
|
create_config
|
|
|
|
print_final
|
|
}
|
|
|
|
# Run main
|
|
main
|