Initial template
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
.idea
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# newproject
|
||||||
|
|
||||||
|
One command that composes a project from the templates in this organization: `infra` at the root, then `backend-python`, `frontend-svelte` and `caddy` on top, each with its own answers file.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
newproject ~/projects/my-thing
|
||||||
|
```
|
||||||
|
|
||||||
|
Templates are read from `$TEMPLATES_DIR` (default `~/projects/templates`). Every part updates independently:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
copier update -a .copier-answers.backend.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Shapes it produces:
|
||||||
|
|
||||||
|
- infrastructure only: root `docker-compose.yml`, `Makefile`, `.env`, optional `caddy/`
|
||||||
|
- backend with one or many services, each `python -m <module>` from one image
|
||||||
|
- backend and frontend as separate containers behind Caddy
|
||||||
|
- backend serving the frontend's static build from the api
|
||||||
|
- frontend only
|
||||||
Executable
+72
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TEMPLATES="${TEMPLATES_DIR:-$HOME/projects/templates}"
|
||||||
|
dest="${1:?usage: newproject <dest> [copier options]}"
|
||||||
|
shift
|
||||||
|
copier_args=("$@")
|
||||||
|
|
||||||
|
ask() {
|
||||||
|
local prompt="$1" default="$2" answer
|
||||||
|
read -r -p "$prompt [$default]: " answer
|
||||||
|
printf '%s' "${answer:-$default}"
|
||||||
|
}
|
||||||
|
|
||||||
|
yes_no() {
|
||||||
|
local answer
|
||||||
|
answer=$(ask "$1" "$2")
|
||||||
|
[[ "$answer" =~ ^[Yy] ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
copy() {
|
||||||
|
uvx copier@latest copy --trust "${copier_args[@]}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
project_name=$(ask "Project name" "$(basename "$dest")")
|
||||||
|
default_slug=$(printf '%s' "$project_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/_/g')
|
||||||
|
project_slug=$(ask "Slug" "$default_slug")
|
||||||
|
author_name=$(git config user.name || true)
|
||||||
|
author_email=$(git config user.email || true)
|
||||||
|
|
||||||
|
parts=()
|
||||||
|
yes_no "Backend" y && parts+=(backend)
|
||||||
|
yes_no "Frontend" y && parts+=(frontend)
|
||||||
|
with_caddy=false
|
||||||
|
yes_no "Caddy" y && with_caddy=true
|
||||||
|
|
||||||
|
serve=bun
|
||||||
|
serve_spa=false
|
||||||
|
if [[ " ${parts[*]} " == *" frontend "* ]]; then
|
||||||
|
serve=$(ask "Frontend served by (bun | static | api)" "bun")
|
||||||
|
[[ "$serve" == api ]] && serve_spa=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
routes=()
|
||||||
|
[[ " ${parts[*]} " == *" backend "* ]] && routes+=(api)
|
||||||
|
[[ " ${parts[*]} " == *" frontend "* && "$serve" != api ]] && routes+=(frontend)
|
||||||
|
|
||||||
|
json_list() {
|
||||||
|
local out="[" sep=""
|
||||||
|
for item in "$@"; do out+="$sep\"$item\""; sep=","; done
|
||||||
|
printf '%s]' "$out"
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "$dest"
|
||||||
|
copy -d "parts=$(json_list "${parts[@]}")" "$TEMPLATES/infra" "$dest"
|
||||||
|
|
||||||
|
if [[ " ${parts[*]} " == *" backend "* ]]; then
|
||||||
|
copy -d "project_name=$project_name" -d "project_slug=$project_slug" \
|
||||||
|
-d "author_name=$author_name" -d "author_email=$author_email" \
|
||||||
|
-d "serve_spa=$serve_spa" "$TEMPLATES/backend-python" "$dest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ " ${parts[*]} " == *" frontend "* ]]; then
|
||||||
|
copy -d "project_name=$project_name" -d "project_slug=$project_slug" \
|
||||||
|
-d "serve=$serve" "$TEMPLATES/frontend-svelte" "$dest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $with_caddy; then
|
||||||
|
copy -d "project_slug=$project_slug" -d "routes=$(json_list "${routes[@]}")" "$TEMPLATES/caddy" "$dest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(cd "$dest" && make env)
|
||||||
Reference in New Issue
Block a user