From aa4ed06d7f0a7f08e8607ebeb4bc4a7afc842360 Mon Sep 17 00:00:00 2001 From: glenneth Date: Thu, 6 Nov 2025 10:11:04 +0300 Subject: [PATCH] experiment: Add ParenScript setup and utilities - Add parenscript dependency to asteroid.asd - Create parenscript-utils.lisp with helper functions and macros - Add PARENSCRIPT-EXPERIMENT.org documenting the conversion plan - Goal: Replace all JavaScript with ParenScript for full-stack Lisp --- PARENSCRIPT-EXPERIMENT.org | 74 ++++++++++++++++++++++++++++++++++++++ asteroid.asd | 15 ++++---- parenscript-utils.lisp | 33 +++++++++++++++++ 3 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 PARENSCRIPT-EXPERIMENT.org create mode 100644 parenscript-utils.lisp diff --git a/PARENSCRIPT-EXPERIMENT.org b/PARENSCRIPT-EXPERIMENT.org new file mode 100644 index 0000000..1ed0a32 --- /dev/null +++ b/PARENSCRIPT-EXPERIMENT.org @@ -0,0 +1,74 @@ +#+TITLE: ParenScript Conversion Experiment +#+AUTHOR: Glenn +#+DATE: 2025-11-06 + +* Overview + +This branch experiments with converting all JavaScript files to ParenScript, allowing us to write client-side code in Common Lisp that compiles to JavaScript. + +* Goals + +- Replace all =.js= files with ParenScript equivalents +- Maintain same functionality +- Improve code maintainability by using one language (Lisp) for both frontend and backend +- Take advantage of Lisp macros for client-side code generation + +* Current JavaScript Files + +- =static/js/admin.js= - Admin dashboard functionality +- =static/js/auth-ui.js= - Authentication UI +- =static/js/front-page.js= - Front page interactions +- =static/js/player.js= - Audio player controls +- =static/js/profile.js= - User profile page +- =static/js/users.js= - User management + +* Implementation Plan + +** Phase 1: Setup [DONE] +- [X] Add ParenScript dependency to =asteroid.asd= +- [X] Create =parenscript-utils.lisp= with helper functions +- [X] Create experimental branch + +** Phase 2: Convert Simple Files First +- [ ] Convert =auth-ui.js= (smallest, simplest) +- [ ] Convert =profile.js= +- [ ] Convert =users.js= + +** Phase 3: Convert Complex Files +- [ ] Convert =player.js= (audio player logic) +- [ ] Convert =front-page.js= (pop-out player, frameset mode) +- [ ] Convert =admin.js= (queue management, track controls) + +** Phase 4: Testing & Refinement +- [ ] Test all functionality +- [ ] Optimize generated JavaScript +- [ ] Document ParenScript patterns used + +* Benefits + +** Code Reuse +- Share utility functions between frontend and backend +- Use same data structures and validation logic + +** Macros +- Create domain-specific macros for common UI patterns +- Generate repetitive JavaScript code programmatically + +** Type Safety +- Catch more errors at compile time +- Better IDE support with Lisp tooling + +** Maintainability +- Single language for entire stack +- Easier refactoring across frontend/backend boundary + +* ParenScript Resources + +- [[https://parenscript.common-lisp.dev/][ParenScript Documentation]] +- [[https://github.com/vsedach/Parenscript][ParenScript GitHub]] + +* Notes + +This is an EXPERIMENTAL branch. The goal is to evaluate ParenScript for this project, not to immediately replace all JavaScript. + +If successful, we can merge incrementally, one file at a time. diff --git a/asteroid.asd b/asteroid.asd index a4ad468..a0254d2 100644 --- a/asteroid.asd +++ b/asteroid.asd @@ -11,10 +11,15 @@ :class "radiance:virtual-module" :depends-on (:slynk :lparallel - :alexandria - :cl-json :radiance + :i-log4cl + :r-clip + :r-simple-rate + :r-simple-profile :lass + :parenscript + :cl-json + :alexandria :local-time :taglib :ironclad @@ -23,12 +28,7 @@ :bordeaux-threads :drakma ;; radiance interfaces - :i-log4cl - ;; :i-postmodern - :r-clip :r-data-model - :r-simple-profile - :r-simple-rate (:interface :auth) (:interface :database) (:interface :relational-database) @@ -41,6 +41,7 @@ (:file "conditions") (:file "database") (:file "template-utils") + (:file "parenscript-utils") (:file "stream-media") (:file "user-management") (:file "playlist-management") diff --git a/parenscript-utils.lisp b/parenscript-utils.lisp new file mode 100644 index 0000000..510a352 --- /dev/null +++ b/parenscript-utils.lisp @@ -0,0 +1,33 @@ +;;;; parenscript-utils.lisp +;;;; Utilities for generating JavaScript from ParenScript + +(in-package :asteroid) + +;;; ParenScript compilation utilities + +(defun compile-ps-to-js (ps-code) + "Compile ParenScript code to JavaScript string" + (ps:ps* ps-code)) + +(defmacro define-js-route (name (&rest args) &body parenscript-body) + "Define a route that serves compiled ParenScript as JavaScript" + `(define-page ,name (,@args) + (:content-type "application/javascript") + (ps:ps ,@parenscript-body))) + +;;; Common ParenScript macros and utilities + +(defmacro ps-defun (name args &body body) + "Define a ParenScript function" + `(ps:defun ,name ,args ,@body)) + +(defmacro ps-api-call (endpoint method data success-callback error-callback) + "Generate ParenScript for making API calls with fetch" + `(ps:ps + (fetch ,endpoint + (ps:create :method ,method + :headers (ps:create "Content-Type" "application/json") + :body (ps:chain -j-s-o-n (stringify ,data)))) + (then (lambda (response) (ps:chain response (json)))) + (then ,success-callback) + (catch ,error-callback)))