summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md7
-rw-r--r--.github/workflows/ci.yml20
-rw-r--r--.gitignore14
-rw-r--r--LICENSE22
-rw-r--r--README.md41
-rw-r--r--build/Dockerfile13
-rw-r--r--composer.json43
-rw-r--r--docker-compose.yml11
-rw-r--r--phel-config.php24
-rw-r--r--public/css/style.css35
-rw-r--r--public/images/favicon-32.pngbin0 -> 1254 bytes
-rw-r--r--public/images/logo.svg5
-rw-r--r--public/index.php17
-rw-r--r--src/app.phel15
-rw-r--r--src/controller/routes.phel13
-rw-r--r--src/module/greet.phel4
-rw-r--r--src/view/main.phel30
-rw-r--r--tests/module/greet-test.phel6
18 files changed, 320 insertions, 0 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..96a2bad
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+## 📚 Description
+
+Replace this text with a short description of your feature/bugfix.
+
+## 🔖 Changes
+
+- List individual changes in more detail
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..9d5feee
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,20 @@
+on: [push]
+
+name: CI
+
+jobs:
+ tests:
+ name: Tests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 8.3
+ coverage: none
+ - name: Install dependencies
+ run: composer update --no-interaction --no-ansi --no-progress
+ - name: Run phel tests
+ run: vendor/bin/phel test
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0355937
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+.idea/
+.vscode/
+data/
+out/
+PhelGenerated/
+var/
+vendor/
+
+!PhelGenerated/.gitkeep
+*.cache
+composer.lock
+.phel-repl-history
+phel-config-local.php
+gacela*.php
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f3a7459
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2023 Jens Haase
+ Jose Maria Valera Reales
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c2b43ae
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# Phel Web Skeleton
+
+[Phel](https://phel-lang.org/) is a functional programming language that compiles to PHP.
+
+This repository provides you the basic setup to start coding a website using phel.
+
+## Getting started
+
+### Requirements
+
+Phel requires at least PHP 8.3 and Composer.
+
+#### Locally (no Docker)
+
+1. Ensure you have PHP >=8.3 (Some help about how to install multiple PHP versions locally on [linux](https://github.com/phpbrew/phpbrew) and [Mac](https://github.com/shivammathur/homebrew-php))
+1. Ensure you have [composer](https://getcomposer.org/composer-stable.phar)
+1. Clone this repo
+1. Install the dependencies | `composer install`
+
+#### Using Docker
+
+1. Clone this repo
+1. Build the image | `docker-compose up -d --build`
+1. Go inside the console | `docker exec -ti -u dev phel_web_skeleton bash`
+1. Install the dependencies | `composer install`
+
+### Phel code
+
+1. Write your phel code in `src/`
+2. Run your web server with
+ - `composer run:dev`: it will recompile the code on every request
+ - `composer run:prod`: it will run the same compiled code on every request
+
+### Tests
+
+1. Write your phel tests in `tests/`
+1. Execute your tests with `composer test`
+
+## More about starting with phel
+
+Find more information about how to start with phel in [getting started](https://phel-lang.org/documentation/getting-started/).
diff --git a/build/Dockerfile b/build/Dockerfile
new file mode 100644
index 0000000..0fb5af1
--- /dev/null
+++ b/build/Dockerfile
@@ -0,0 +1,13 @@
+FROM php:8.3-fpm
+
+RUN apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install -y git
+
+RUN pecl install -o -f xdebug \
+ && rm -rf /tmp/pear \
+ && docker-php-ext-enable xdebug
+
+COPY --from=composer /usr/bin/composer /usr/bin/composer
+RUN useradd -m dev
+WORKDIR /srv/phel-web-skeleton
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..27eccef
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,43 @@
+{
+ "name": "phel-lang/web-skeleton",
+ "description": "A minimalistic skeleton to build your web-app using Phel Lang.",
+ "keywords": [
+ "phel",
+ "lisp",
+ "functional",
+ "language"
+ ],
+ "homepage": "https://phel-lang.org/",
+ "license": "MIT",
+ "type": "project",
+ "require": {
+ "php": ">=8.3",
+ "phel-lang/phel-lang": ">=0.24",
+ "phel-lang/router": "^0.8"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^6.4"
+ },
+ "autoload": {
+ "psr-4": {
+ "PhelGenerated\\": "src/PhelGenerated"
+ }
+ },
+ "scripts": {
+ "run:dev": [
+ "Composer\\Config::disableProcessTimeout",
+ "rm -rf out && php -S localhost:8080 -t public"
+ ],
+ "run:prod": [
+ "Composer\\Config::disableProcessTimeout",
+ "composer build && php -S localhost:8080 -t public"
+ ],
+ "build": "vendor/bin/phel build --no-cache",
+ "format": "vendor/bin/phel format",
+ "test": "vendor/bin/phel test",
+ "repl": [
+ "Composer\\Config::disableProcessTimeout",
+ "vendor/bin/phel repl"
+ ]
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..74089e8
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,11 @@
+version: "3.8"
+
+services:
+ phel_web_skeleton:
+ build:
+ context: .
+ dockerfile: build/Dockerfile
+ container_name: phel_web_skeleton
+ hostname: php
+ volumes:
+ - .:/srv/phel-web-skeleton:delegated
diff --git a/phel-config.php b/phel-config.php
new file mode 100644
index 0000000..779f65c
--- /dev/null
+++ b/phel-config.php
@@ -0,0 +1,24 @@
+<?php
+
+declare(strict_types=1);
+
+use Phel\Config\PhelConfig;
+use Phel\Config\PhelExportConfig;
+use Phel\Config\PhelBuildConfig;
+
+return (new PhelConfig())
+ ->setSrcDirs(['src'])
+ ->setTestDirs(['tests'])
+ ->setVendorDir('vendor')
+ ->setKeepGeneratedTempFiles(false)
+ ->setFormatDirs(['src', 'tests'])
+ ->setBuildConfig((new PhelBuildConfig())
+ ->setMainPhelNamespace('web-skeleton\app')
+ ->setMainPhpPath('out/index.php'))
+ ->setExportConfig((new PhelExportConfig())
+ ->setFromDirectories(['src/phel'])
+ ->setNamespacePrefix('PhelGenerated')
+ ->setTargetDirectory('src/PhelGenerated'))
+ ->setIgnoreWhenBuilding(['local.phel'])
+ ->setNoCacheWhenBuilding(['web_skeleton/app'])
+;
diff --git a/public/css/style.css b/public/css/style.css
new file mode 100644
index 0000000..edc12ff
--- /dev/null
+++ b/public/css/style.css
@@ -0,0 +1,35 @@
+html, body {
+ font-family: "Helvetica", "Arial", sans-serif;
+ font-weight: 200;
+}
+
+.full-height {
+ height: 80vh;
+}
+
+.flex-center {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+}
+
+.position-ref {
+ position: relative;
+}
+
+.content {
+ text-align: center;
+}
+
+.links > a {
+ color: #35157f;
+ padding: 0 15px;
+ font-weight: bolder;
+ font-size: larger;
+ letter-spacing: .1rem;
+ text-decoration: none;
+}
+
+.logo {
+ margin-bottom: 60px;
+} \ No newline at end of file
diff --git a/public/images/favicon-32.png b/public/images/favicon-32.png
new file mode 100644
index 0000000..a24adc4
--- /dev/null
+++ b/public/images/favicon-32.png
Binary files differ
diff --git a/public/images/logo.svg b/public/images/logo.svg
new file mode 100644
index 0000000..25ba931
--- /dev/null
+++ b/public/images/logo.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200.3 167.7">
+ <path d="M6 66l95 96h36V93l-36-74H42L6 56v106h36l24-35" fill="none" stroke="#512da8" stroke-width="3"/>
+ <path d="M137 93l58-3-12-58-32-26h-34l-16 13-23 9-12 22 46 52z" fill="none" stroke="#512da8" stroke-width="3"/>
+ <path d="M195 90l-12 57h-13l-2-56m2 56l-13-11h12" fill="none" stroke="#512da8" stroke-width="3"/>
+</svg>
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..92e0753
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+use Phel\Phel;
+
+$projectRootDir = dirname(__DIR__);
+require $projectRootDir . '/vendor/autoload.php';
+
+$appFile = $projectRootDir . "/out/index.php";
+
+if (file_exists($appFile)) {
+ require_once $appFile;
+} else {
+ Phel::run($projectRootDir, 'web-skeleton\app');
+}
+
diff --git a/src/app.phel b/src/app.phel
new file mode 100644
index 0000000..a9d8af3
--- /dev/null
+++ b/src/app.phel
@@ -0,0 +1,15 @@
+(ns web-skeleton\app
+ (:require web-skeleton\controller\routes)
+ (:require phel\router :as r)
+ (:require phel\http :as h))
+
+(def app
+ (r/handler
+ (r/router
+ [["/" {:handler routes/index-handler}]
+ ["/ping" {:name ::ping
+ :get {:handler routes/ping-handler}
+ :post {:handler routes/ping-handler}}]])))
+
+(when-not *build-mode*
+ (h/emit-response (app (h/request-from-globals))))
diff --git a/src/controller/routes.phel b/src/controller/routes.phel
new file mode 100644
index 0000000..ae0cdf1
--- /dev/null
+++ b/src/controller/routes.phel
@@ -0,0 +1,13 @@
+(ns web-skeleton\controller\routes
+ (:require web-skeleton\view\main :refer [index-html])
+ (:require web-skeleton\module\greet :as g)
+ (:require phel\router :as r)
+ (:require phel\http :as h))
+
+(defn index-handler [req]
+ (h/response-from-map {:status 200
+ :body index-html}))
+
+(defn ping-handler [req]
+ (h/response-from-map {:status 200
+ :body (g/greet (str "pong - " (rand)))}))
diff --git a/src/module/greet.phel b/src/module/greet.phel
new file mode 100644
index 0000000..239e425
--- /dev/null
+++ b/src/module/greet.phel
@@ -0,0 +1,4 @@
+(ns web-skeleton\module\greet)
+
+(defn greet [name]
+ (str "Hello, " name)) \ No newline at end of file
diff --git a/src/view/main.phel b/src/view/main.phel
new file mode 100644
index 0000000..34cb792
--- /dev/null
+++ b/src/view/main.phel
@@ -0,0 +1,30 @@
+(ns web-skeleton\view\main
+ (:require phel\html :refer [html doctype]))
+
+(def- head
+ [:head
+ [:meta {:charset "utf-8"}]
+ [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
+ [:link {:rel "stylesheet" :href "./css/style.css"}]
+ [:link {:rel "icon" :type "image/png" :href "./images/favicon-32.png"}]
+ [:title "Phel-lang"]])
+
+(def- logo
+ [:div {:class "logo"}
+ [:img {:src "./images/logo.svg" :width "360"}]])
+
+(def- links
+ [:div {:class "links"}
+ [:a {:href "https://phel-lang.org/"} "Homepage"]
+ [:a {:href "https://phel-lang.org/documentation/getting-started/"} "Getting started"]
+ [:a {:href "https://github.com/phel-lang/phel-lang"} "GitHub"]
+ [:a {:href "https://gitter.im/phel-lang/community"} "Community"]])
+
+(def- content
+ [:div {:class "flex-center position-ref full-height"}
+ [:div {:class "content"} logo links]])
+
+(def index-html (html
+ (doctype :html5)
+ head
+ content)) \ No newline at end of file
diff --git a/tests/module/greet-test.phel b/tests/module/greet-test.phel
new file mode 100644
index 0000000..1caef0f
--- /dev/null
+++ b/tests/module/greet-test.phel
@@ -0,0 +1,6 @@
+(ns phel-web-skeleton-tests\module\example-test
+ (:require web-skeleton\module\greet :as g)
+ (:require phel\test :refer [deftest is]))
+
+(deftest test-greet
+ (is (= "Hello, Name" (g/greet "Name"))))