diff --git a/.gitignore b/.gitignore
index 3c3629e..172b172 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
node_modules
+.DS_Store
+dbs
diff --git a/index.js b/index.js
index 2ea2328..1949442 100644
--- a/index.js
+++ b/index.js
@@ -3,6 +3,7 @@ const vm = require("node:vm");
const path = require("path");
const express = require("express");
const session = require("express-session");
+const fileUpload = require("express-fileupload");
const SQLiteStore = require("better-sqlite3-session-store")(session);
const betterSqlite3 = require("better-sqlite3");
const { Eta } = require("eta");
@@ -20,6 +21,7 @@ const routes = { GET: [], POST: [], PUT: [], DELETE: [] };
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
+app.use(fileUpload());
const db = betterSqlite3("./prime.db");
@@ -209,12 +211,42 @@ function updateDb(db, appDb) {
db.prepare(sql).run(...values);
}
+function updateTemplate(db, template) {
+ const fields = ["content", "name", "test_object"];
+ const values = fields.map((field) => template[field]);
+ const placeholders = fields.map((field) => `${field} = ?`).join(", ");
+
+ const sql = `UPDATE templates SET ${placeholders} WHERE id = ?`;
+ values.push(template.id);
+ db.prepare(sql).run(...values);
+}
+
function getTemplates(db, structureId) {
return db
.prepare("SELECT * from templates where structure_id = ?")
.all(structureId);
}
+function getTemplate(db, templateId) {
+ return db.prepare("SELECT * from templates where id = ?").get(templateId);
+}
+
+function getTemplateContentByName(db, structId, name) {
+ return db
+ .prepare(
+ "SELECT content from templates where structure_id = ? AND name = ?"
+ )
+ .get(structId, name);
+}
+
+function createTemplate(db, structureId, name, content, testObjectString) {
+ return db
+ .prepare(
+ "INSERT INTO templates (structure_id, name, content, test_object) VALUES (?, ?, ?, ?)"
+ )
+ .run(structureId, name, content, testObjectString).lastInsertRowid;
+}
+
function getDbsForStructure(db, structureId) {
return db
.prepare(
@@ -280,8 +312,6 @@ function createDb(db, structId, name) {
}
const { LRUCache } = require("lru-cache");
-const { templateSettings } = require("dot");
-// we'll figure out max size later
const templateCache = new LRUCache({ max: 100 });
function getTemplater(structId) {
@@ -293,7 +323,7 @@ function getTemplater(structId) {
return path;
};
etaInstance.readFile = function (templateAlias) {
- return getTemplateString(db, templateAlias, structId);
+ return getTemplateContentByName(db, structId, templateAlias).content;
};
templateCache.set(structId, etaInstance);
}
@@ -315,9 +345,8 @@ function getDbInstance(dbId) {
return dbInstance;
}
-function bootstrapTemplateWithHTMXetc(htmlString, blissRoute) {
- console.log(htmlString);
- if (htmlString.startsWith("")) {
+function bootstrapTemplateWithHTMXetc(htmlString, blissRoute, wrapHTML) {
+ if (htmlString.startsWith("") || wrapHTML) {
const $ = cheerio.load(htmlString);
let head = $("head");
@@ -487,6 +516,63 @@ app.post("/workshop/:structure_id/db/:db_id/repl", (req, res) => {
}
});
+app.post("/workshop/:structure_id/template", (req, res) => {
+ let name = req.body.name;
+
+ const template = createTemplate(
+ db,
+ req.params.structure_id,
+ name,
+ "
henlo <%= it.name %>
",
+ "it = { name: 'templates!' };"
+ );
+
+ return smartRedirect(
+ req,
+ res,
+ `/workshop/${req.params.structure_id}/template/${template}`
+ );
+});
+
+app.put("/workshop/:structure_id/template/:template_id", (req, res) => {
+ let id = req.params.template_id;
+ let content = req.body.content;
+ let test_object = req.body.test_object;
+
+ updateTemplate(db, { ...getTemplate(db, id), content, test_object });
+
+ return res.send("good");
+});
+
+app.get("/workshop/:structure_id/template/:template_id", (req, res) => {
+ const template = getTemplate(db, req.params.template_id);
+
+ return res.send(
+ bootstrapTemplateWithHTMXetc(
+ eta.render("workshop/template", {
+ template: template,
+ ...sidebarStuff(db, req.params.structure_id),
+ })
+ )
+ );
+});
+
+app.get("/workshop/:structure_id/template/:template_id/preview", (req, res) => {
+ const template = getTemplate(db, req.params.template_id);
+ const eta = getTemplater(req.params.structure_id);
+
+ const context = vm.createContext({ it: null });
+ vm.runInContext(template.test_object, context);
+
+ return res.send(
+ bootstrapTemplateWithHTMXetc(
+ eta.render(template.name, context.it),
+ null,
+ true
+ )
+ );
+});
+
app.get("/workshop/:structure_id/route/:id", (req, res) => {
const route = getRoute(db, req.params.id);
return res.send(
@@ -581,7 +667,6 @@ app.all("*", (req, res) => {
res.rawSend = res.send;
res.send = (...args) => {
- console.log(args[0], args[1], "bingo")
res.rawSend(
bootstrapTemplateWithHTMXetc(
args[0],
@@ -589,6 +674,10 @@ app.all("*", (req, res) => {
)
);
};
+ res.render = (template, context) => {
+ const eta = getTemplater(route.structure_id);
+ res.send(bootstrapTemplateWithHTMXetc(eta.render(template, context)));
+ };
return vm.runInContext(
(route.handler += `\n\nhandler(req, res)`),
context
diff --git a/migrations/000_bootstrap_db.sql b/migrations/000_bootstrap_db.sql
index eba2524..bd91527 100644
--- a/migrations/000_bootstrap_db.sql
+++ b/migrations/000_bootstrap_db.sql
@@ -32,13 +32,13 @@ CREATE TABLE templates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
content TEXT,
- user_id INTEGER,
structure_id INTEGER,
+ test_object TEXT DEFAULT "it = {}",
engine TEXT NOT NULL DEFAULT "eta",
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY(user_id) REFERENCES users(id),
FOREIGN KEY(structure_id) REFERENCES structures(id)
+ UNIQUE(name, structure_id)
);
CREATE TABLE routes (
diff --git a/package-lock.json b/package-lock.json
index a438cc8..2d751cf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"ejs": "^3.1.9",
"eta": "^3.2.0",
"express": "^4.18.2",
+ "express-fileupload": "^1.5.0",
"express-session": "^1.18.0",
"jsdom": "^24.1.0",
"lru-cache": "^10.2.0",
@@ -290,6 +291,17 @@
"ieee754": "^1.1.13"
}
},
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -829,6 +841,17 @@
"node": ">= 0.10.0"
}
},
+ "node_modules/express-fileupload": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.0.tgz",
+ "integrity": "sha512-jSW3w9evqM37VWkEPkL2Ck5wUo2a8qa03MH+Ou/0ZSTpNlQFBvSLjU12k2nYcHhaMPv4JVvv6+Ac1OuLgUZb7w==",
+ "dependencies": {
+ "busboy": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/express-session": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz",
@@ -2189,6 +2212,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -2711,6 +2742,14 @@
"ieee754": "^1.1.13"
}
},
+ "busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "requires": {
+ "streamsearch": "^1.1.0"
+ }
+ },
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -3136,6 +3175,14 @@
}
}
},
+ "express-fileupload": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.5.0.tgz",
+ "integrity": "sha512-jSW3w9evqM37VWkEPkL2Ck5wUo2a8qa03MH+Ou/0ZSTpNlQFBvSLjU12k2nYcHhaMPv4JVvv6+Ac1OuLgUZb7w==",
+ "requires": {
+ "busboy": "^1.6.0"
+ }
+ },
"express-session": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz",
@@ -4075,6 +4122,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
},
+ "streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
+ },
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
diff --git a/package.json b/package.json
index 8957a79..b87ffa7 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"ejs": "^3.1.9",
"eta": "^3.2.0",
"express": "^4.18.2",
+ "express-fileupload": "^1.5.0",
"express-session": "^1.18.0",
"jsdom": "^24.1.0",
"lru-cache": "^10.2.0",
diff --git a/views/workshop/new_template_modal.eta b/views/workshop/new_template_modal.eta
index 21f5138..7f6cdf7 100644
--- a/views/workshop/new_template_modal.eta
+++ b/views/workshop/new_template_modal.eta
@@ -1,16 +1,22 @@
-
-
-
Command Prompt
-
-
-
-
+
+
-
-
Microsoft❮R❯ Windows DOS
- ❮C❯ Copyright Microsoft Corp 1990-2001.
- C:\WINDOWS\SYSTEM32> You can build a command line easily with a window and pre tag
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/views/workshop/sidebar.eta b/views/workshop/sidebar.eta
index cb753ba..294abbb 100644
--- a/views/workshop/sidebar.eta
+++ b/views/workshop/sidebar.eta
@@ -24,7 +24,9 @@
<% it.templates.map(template => { %>
- <%= template.alias %>
+
+ <%= template.name %>
+
<% }) %>
@@ -41,8 +43,8 @@
<% it.dbs.map(db => { %>
-
- <%= db.alias %>
+
+ <%= db.alias %>
<% }) %>
diff --git a/views/workshop/template.eta b/views/workshop/template.eta
new file mode 100644
index 0000000..fbe00f1
--- /dev/null
+++ b/views/workshop/template.eta
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
Workshop - <%~ include('/workshop/structure_name', {structure: it.structure}) %>
+
+
+
+
+ <%~ include('/workshop/sidebar', it) %>
+
+
+
+ Template
+
<%= it.template.content %>
+ Test Object
+
<%= it.template.test_object %>
+
Save
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file