-
Collection - treat directories and files as collections of data.
Kind of similar to the routing tree, but instead of routes it just takes a bunch of files and turns it into a dataset. Each directory is a "table" and is composed of zero or more files that form rows in the table. Supported file formats:
- foo.md - markdown with optional front matter
- foo.json - JSON record
- foo.yml - YAML record
API:
Articles = @app.collection('_articles/*.md') article = Articles.last_by(&:date) article.title #=> article.date #=> article.layout #=> article.render_proc #=> (load layout, apply article) article.render #=> (render to HTML) # there should also be methods for creating, updating and deleting of # articles/items. ...
-
Improve serving of static files:
- support for compression
- support for caching headers
- add `Request#render_static_file(route, fn)
- Logo
- Website
- [v] Frontend part of JSON API
- [v] Auto-refresh page when file changes
- [v] Examples
- [v] Reactive app - counter or some other simple app showing interaction with server
- What do we need to test?
- Routes
- Route responses
- Changes to state / DB
- can be implemented as separate gems
- can route requests to a different directory (i.e. inside the gem directory)
- simple way to instantiate and setup the applet
- as a first example, implement an auth/signin applet:
- session hook
- session persistence
- login page
- support for custom behaviour and custom workflows (2FA, signin using OTP etc.)
Example usage:
# /admin+.rb
require 'syntropy/admin'
export Syntropy::Admin.new(@ref, @env)Implementation:
# syntropy-admin/lib/syntropy/admin.rb
APP_ROOT = File.expand_path(File.join(__dir__, '../../app'))
class Syntropy::Admin < Syntropy::App
def new(mount_path, env)
super(env[:machine], APP_ROOT, mount_path, env)
end
endWe need a way to inject cookies into the response. This probably should be done in the TP2 code:
@@default_set_cookie_attr = 'HttpOnly'
def self.default_set_cookie_attr=(v)
@@default_set_cookie_attr = v
end
def set_cookie(key, value, attr = @@default_set_cookie_attr)
@buffered_headers ||= +''
@buffered_headers << format(
"Set-Cookie: %<key>s=%<value>s; %<attr>s\n",
key:, value:, attr:
)
end
def set_headers(headers)
@buffered_headers ||= +''
@buffered_headers << format_headers(headers)
end
...
req.set_cookie('at', 'foobar', 'SameSite=none; Secure; HttpOnly')Some standard middleware:
- request rewriter
- logger
- auth
- selector + terminator
# For the chainable DSL shown below, we need to create a custom class:
class Syntropy::Middleware::Selector
def initialize(select_proc, terminator_proc = nil)
@select_proc = select_proc
@terminator_proc = terminator_proc
end
def to_proc
->(req, proc) {
@select_proc.(req) ? @terminator_proc.(req) : proc(req)
}
end
def terminate(&proc)
@terminator_proc = proc
end
end# a _site.rb file can be used to wrap a whole app
# site/_site.rb
# this means we route according to the host header, with each
export Syntropy.route_by_host
# we can also rewrite requests:
rewriter = Syntropy
.select { it.host =~ /^tolkora\.(org|com)$/ }
.terminate { it.redirect_permanent('https://tolkora.net') }
# This is actuall a pretty interesting DSL design:
# a chain of operations that compose functions. So, we can select a
export rewriter.wrap(default_app)
# composing
export rewriter.wrap(Syntropy.some_custom_app.wrap(app))
# or maybe
export rewriter << some_other_middleware << app# clone a newly created repo
~/repo$ git clone https://github.com/foo/bar
...
~/repo$ syntropy setup bar
(syntropy banner)
Setting up Syntropy project in /home/sharon/repo/bar:
bar/
bin/
start
stop
restart
console
server
docker-compose.yml
Dockerfile
Gemfile
proxy/
README.md
site/
_layout/
default.rb
_lib/
about.md
articles/
long-form.md
assets/
js/
css/
style.css
img/
syntropy.png
index.rbSome of the files might need templating, but we can maybe do without, or at least make it as generic as possible.
syntropy setup steps:
- Verify existence of target directory
- Copy files from Syntropy template to target directory
- Do chmod +x for bin/*
- Do bundle install in the target directory
- Show some information with regard to how to get started working with the repo
syntropy provision steps:
- Verify Ubuntu 22.x or higher
- Install git, docker, docker-compose
syntropy deploy steps:
- Verify no uncommitted changes.
- SSH to remote machine. 2.1. If not exists, clone repo 2.2. Otherwise, verify remote machine repo is on same branch as local repo 2.3. Do a git pull (what about credentials?) 2.4. If gem bundle has changed, do a docker compose build 2.5. If docker compose services are running, restart 2.6. Otherwise, start services 2.7. Verify service is running correctly