automate database init from CLI. add sqlite_history
may god bless simon willison
This commit is contained in:
parent
0110cc17e2
commit
c226669a09
5 changed files with 146 additions and 3 deletions
16
Makefile
Normal file
16
Makefile
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
.PHONY: tidy
|
||||
tidy:
|
||||
clojure-lsp clean-ns && clojure-lsp format && clojure-lsp diagnostics
|
||||
|
||||
.PHONY: storage/site.db
|
||||
storage/site.db:
|
||||
rm -f storage/*
|
||||
sqlite3 storage/site.db 'PRAGMA journal_mode=WAL;'
|
||||
clj -M dev/migration.clj
|
||||
uv run dev/sqlite-history.py
|
||||
|
||||
.PHONY: db
|
||||
db: storage/site.db
|
||||
|
||||
repl: storage/site.db
|
||||
clj -M:dev dev
|
||||
15
dev/migration.clj
Normal file
15
dev/migration.clj
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(ns migration
|
||||
#_{:clj-kondo/ignore [:unused-namespace]}
|
||||
(:require [migratus.core :as migratus]
|
||||
[taoensso.telemere.timbre :as log]))
|
||||
|
||||
(def config {:store :database
|
||||
:migration-dir "migrations/"
|
||||
:db {:dbtype "sqlite"
|
||||
:dbname "storage/site.db"}})
|
||||
|
||||
;initialize the database using the 'init.sql' script
|
||||
;; (migratus/init config)
|
||||
|
||||
;apply pending migrations
|
||||
(migratus/migrate config)
|
||||
70
dev/sqlite-history.py
Normal file
70
dev/sqlite-history.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# /// script
|
||||
# requires-python = ">=3.13"
|
||||
# dependencies = [
|
||||
# "sqlite-history",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
|
||||
import sqlite_history
|
||||
import sqlite3
|
||||
|
||||
|
||||
def configure_triggers(database_path, tables):
|
||||
db = sqlite3.connect(database_path)
|
||||
for table in tables:
|
||||
if table.startswith("_") and table.endswith("_history"):
|
||||
continue
|
||||
# Does a history table exist already?
|
||||
history_table_name = f"_{table}_history"
|
||||
cursor = db.execute(
|
||||
f"SELECT name FROM sqlite_master WHERE type='table' AND name='{history_table_name}';"
|
||||
)
|
||||
if cursor.fetchone():
|
||||
print(f"History table {history_table_name} already exists - skipping.")
|
||||
continue
|
||||
sqlite_history.configure_history(db, table)
|
||||
print(f"configured trigger for {table}")
|
||||
|
||||
|
||||
def all_regular_tables(database_path):
|
||||
"""'Regular' excludes FTS and related tables."""
|
||||
conn = sqlite3.connect(database_path)
|
||||
cursor = conn.cursor()
|
||||
hidden_tables = [
|
||||
r[0]
|
||||
for r in (
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT NAME FROM sqlite_master
|
||||
WHERE type = 'table'
|
||||
AND (
|
||||
sql LIKE '%VIRTUAL TABLE%USING FTS%'
|
||||
) OR name IN ('sqlite_stat1', 'sqlite_stat2', 'sqlite_stat3', 'sqlite_stat4')
|
||||
"""
|
||||
)
|
||||
).fetchall()
|
||||
]
|
||||
hidden_tables_copy = hidden_tables[:]
|
||||
regular_tables = []
|
||||
for row in cursor.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table';"
|
||||
).fetchall():
|
||||
table_name = row[0]
|
||||
should_be_hidden = any(
|
||||
table_name.startswith(hidden_table) for hidden_table in hidden_tables_copy
|
||||
)
|
||||
if not should_be_hidden:
|
||||
regular_tables.append(table_name)
|
||||
return regular_tables
|
||||
|
||||
|
||||
def main() -> None:
|
||||
database_path = "storage/site.db"
|
||||
tables = all_regular_tables(database_path)
|
||||
|
||||
configure_triggers(database_path, tables)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
45
dev/tasks.clj
Normal file
45
dev/tasks.clj
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
(ns tasks
|
||||
(:require [com.biffweb.task-runner :refer [run-task]]
|
||||
[com.biffweb.tasks :as tasks]
|
||||
[com.biffweb.tasks.lazy.babashka.fs :as fs]
|
||||
[com.biffweb.tasks.lazy.babashka.process :refer [shell]]
|
||||
[com.biffweb.tasks.lazy.clojure.java.io :as io]
|
||||
[com.biffweb.tasks.lazy.com.biffweb.config :as config]))
|
||||
|
||||
(def config (delay (config/use-aero-config {:biff.config/skip-validation true})))
|
||||
|
||||
(defn dev
|
||||
"Starts the app locally.
|
||||
|
||||
After running, wait for the `System started` message. Connect your editor to
|
||||
nrepl port 7888 (by default). Whenever you save a file, Biff will:
|
||||
|
||||
- Evaluate any changed Clojure files
|
||||
- Regenerate static HTML files
|
||||
- Run tests"
|
||||
[]
|
||||
(if-not (fs/exists? "target/resources")
|
||||
;; This is an awful hack. We have to run the app in a new process, otherwise
|
||||
;; target/resources won't be included in the classpath. Downside of not
|
||||
;; using bb tasks anymore -- no longer have a lightweight parent process
|
||||
;; that can create the directory before starting the JVM.
|
||||
(do
|
||||
(io/make-parents "target/resources/_")
|
||||
(shell "clj" "-M:dev" "dev"))
|
||||
(let [{:keys [biff.tasks/main-ns biff.nrepl/port] :as _ctx} @config]
|
||||
|
||||
(when-not (fs/exists? "config.env")
|
||||
(run-task "generate-config"))
|
||||
(when (fs/exists? "package.json")
|
||||
(shell "npm install"))
|
||||
(spit ".nrepl-port" port)
|
||||
((requiring-resolve (symbol (str main-ns) "-main"))))))
|
||||
|
||||
;; Tasks should be vars (#'hello instead of hello) so that `clj -M:dev help` can
|
||||
;; print their docstrings.
|
||||
(def custom-tasks
|
||||
{"dev" #'dev})
|
||||
|
||||
(def tasks (merge tasks/tasks custom-tasks))
|
||||
|
||||
(comment tasks)
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
[clojure.test :as test]
|
||||
[com.biffweb :as biff]
|
||||
[com.biffweb.my-project.app :as app]
|
||||
[com.biffweb.my-project.email :as email]
|
||||
[com.biffweb.my-project.middleware :as mid]
|
||||
[com.biffweb.my-project.ui :as ui]
|
||||
[migratus.core :as migratus]
|
||||
|
|
@ -40,7 +39,6 @@
|
|||
(def initial-system
|
||||
{:biff/modules #'modules
|
||||
:biff/merge-context-fn identity
|
||||
:biff/send-email #'email/send-email
|
||||
:biff/handler #'handler
|
||||
:biff.beholder/on-save #'on-save
|
||||
:biff.middleware/on-error #'ui/on-error
|
||||
|
|
@ -51,7 +49,6 @@
|
|||
(defn ctx->migratus-config [ctx]
|
||||
{:store :database
|
||||
:migration-dir "migrations/"
|
||||
:migration-table-name "migrations"
|
||||
:db {:connection (jdbc/get-connection (:example/db-url ctx))
|
||||
:managed-connection? true}})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue