create-gardener 2.1.6 → 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/.env +1 -1
- package/template/build/backend/controllers/gardener/addComponent.d.ts +8 -0
- package/template/build/backend/controllers/gardener/addComponent.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/addComponent.js +19 -0
- package/template/build/backend/controllers/gardener/addComponent.js.map +1 -0
- package/template/build/backend/controllers/gardener/addPage.d.ts +3 -0
- package/template/build/backend/controllers/gardener/addPage.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/addPage.js +86 -0
- package/template/build/backend/controllers/gardener/addPage.js.map +1 -0
- package/template/build/backend/controllers/gardener/createStatic.d.ts +2 -0
- package/template/build/backend/controllers/gardener/createStatic.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/createStatic.js +83 -0
- package/template/build/backend/controllers/gardener/createStatic.js.map +1 -0
- package/template/build/backend/controllers/gardener/hotReload.d.ts +3 -0
- package/template/build/backend/controllers/gardener/hotReload.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/hotReload.js +29 -0
- package/template/build/backend/controllers/gardener/hotReload.js.map +1 -0
- package/template/build/backend/controllers/gardener/imageOptimiser.d.ts +3 -0
- package/template/build/backend/controllers/gardener/imageOptimiser.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/imageOptimiser.js +123 -0
- package/template/build/backend/controllers/gardener/imageOptimiser.js.map +1 -0
- package/template/build/backend/controllers/gardener/index.d.ts +6 -0
- package/template/build/backend/controllers/gardener/index.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/index.js +6 -0
- package/template/build/backend/controllers/gardener/index.js.map +1 -0
- package/template/build/backend/controllers/gardener/saveTemplate.d.ts +3 -0
- package/template/build/backend/controllers/gardener/saveTemplate.d.ts.map +1 -0
- package/template/build/backend/controllers/gardener/saveTemplate.js +36 -0
- package/template/build/backend/controllers/gardener/saveTemplate.js.map +1 -0
- package/template/build/backend/libs/generateWebp.d.ts +2 -0
- package/template/build/backend/libs/generateWebp.d.ts.map +1 -0
- package/template/build/backend/libs/generateWebp.js +16 -0
- package/template/build/backend/libs/generateWebp.js.map +1 -0
- package/template/build/backend/routes/gardener.route.d.ts +4 -0
- package/template/build/backend/routes/gardener.route.d.ts.map +1 -0
- package/template/build/backend/routes/gardener.route.js +13 -0
- package/template/build/backend/routes/gardener.route.js.map +1 -0
- package/template/build/backend/server.d.ts +2 -0
- package/template/build/backend/server.d.ts.map +1 -0
- package/template/build/backend/server.js +26 -0
- package/template/build/backend/server.js.map +1 -0
- package/template/build/frontend/assets/favicon.png +0 -0
- package/template/build/frontend/assets/gardener.jpg +0 -0
- package/template/build/frontend/assets/remote/betterway.jpg +0 -0
- package/template/build/frontend/static/bundle/bundle._.js +1 -0
- package/template/build/frontend/static/cache/favicon_50x50.webp +0 -0
- package/template/build/frontend/static/cache/gardener_50x50.webp +0 -0
- package/template/build/frontend/static/style.css +2 -0
- package/template/build/frontend/static/style2.css +26 -0
- package/template/build/frontend/tailwind.css +1 -0
- package/template/build/frontend/views/_.ejs +137 -0
- package/template/build/frontend/views/partials/icons/clipboard.ejs +1 -0
- package/template/build/frontend/views/partials/icons/clipboardok.ejs +1 -0
- package/template/buildHelper.js +5 -5
- package/template/src/backend/server.ts +5 -4
- package/template/src/frontend/static/cache/betterway_200x200.webp +0 -0
- package/template/src/frontend/static/cache/favicon_50x50.webp +0 -0
- package/template/src/frontend/static/gardenerConfig.js +5 -1
- package/template/src/frontend/static/style.css +1093 -1
- package/template/src/frontend/tailwind.css +1 -1
- package/template/src/frontend/template/template._.ejs +101 -89
- package/template/src/frontend/views/_.ejs +1 -1
- package/template/src/frontend/style.css +0 -1045
package/package.json
CHANGED
package/template/.env
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
interface AddComponentBody {
|
|
3
|
+
path: string;
|
|
4
|
+
component: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function addComponent(req: Request<{}, {}, AddComponentBody>, res: Response): Promise<void>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=addComponent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addComponent.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/addComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAIjD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,gBAAgB,CAAC,EAAE,GAAG,EAAE,QAAQ,iBAWvF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fsp from "fs/promises";
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
const frontendDir = path.resolve(__dirname, '..', '..', '..', 'frontend');
|
|
7
|
+
export async function addComponent(req, res) {
|
|
8
|
+
try {
|
|
9
|
+
const { path: filePath, component } = req.body;
|
|
10
|
+
await fsp.mkdir(path.join(frontendDir, 'static', 'components'), { recursive: true });
|
|
11
|
+
await fsp.writeFile(path.join(frontendDir, `${filePath}`), component, "utf8");
|
|
12
|
+
res.json({ success: true });
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
const error = err;
|
|
16
|
+
res.json({ success: false, msg: error.message });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=addComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addComponent.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/addComponent.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAsC,EAAE,GAAa;IACtF,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QAC/C,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC9E,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAY,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addPage.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/addPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA8CjD,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,iBAyCxD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fsp from "fs/promises";
|
|
2
|
+
import { access } from "fs/promises";
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const frontendDir = path.resolve(__dirname, '..', '..', '..', 'frontend');
|
|
8
|
+
const templateDir = path.join(frontendDir, 'template');
|
|
9
|
+
async function findTemplate(fileName) {
|
|
10
|
+
try {
|
|
11
|
+
while (fileName.length !== 0) {
|
|
12
|
+
console.log(fileName);
|
|
13
|
+
const searchFile = `template.${fileName}.ejs`;
|
|
14
|
+
console.log(searchFile);
|
|
15
|
+
const searchPath = path.join(templateDir, searchFile);
|
|
16
|
+
console.log(searchPath);
|
|
17
|
+
try {
|
|
18
|
+
await access(searchPath); // ✅ checks if file exists
|
|
19
|
+
return searchPath; // return full path immediately
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// file does not exist → continue
|
|
23
|
+
}
|
|
24
|
+
let lastUnderscore = fileName.lastIndexOf('_');
|
|
25
|
+
if (lastUnderscore === -1)
|
|
26
|
+
break;
|
|
27
|
+
if (lastUnderscore === 0)
|
|
28
|
+
lastUnderscore += 1;
|
|
29
|
+
fileName = fileName.substring(0, lastUnderscore);
|
|
30
|
+
console.log(fileName);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw new Error("Template not found");
|
|
35
|
+
}
|
|
36
|
+
// ❗ explicit failure instead of silent bug
|
|
37
|
+
}
|
|
38
|
+
export async function addPage(req, res) {
|
|
39
|
+
try {
|
|
40
|
+
const pagename = req.body.page;
|
|
41
|
+
const name = pagename.replaceAll('/', '_');
|
|
42
|
+
const templatePath = await findTemplate(name); //path.join(frontendDir, findTemplate(name)); //path.join(frontendDir, 'frontendtemplate.ejs');
|
|
43
|
+
if (!templatePath)
|
|
44
|
+
throw new Error('no template found');
|
|
45
|
+
const viewPath = path.join(frontendDir, `views`, `${name}.ejs`);
|
|
46
|
+
const routePath = path.resolve(__dirname, '..', '..', 'routes', 'gardener.route.ts');
|
|
47
|
+
const jsDir = path.join(frontendDir, 'static/pages');
|
|
48
|
+
const jsFilePath = path.join(jsDir, `pages.${name}.js`);
|
|
49
|
+
const bundleDir = path.join(frontendDir, 'bundle');
|
|
50
|
+
const templateContent = await fsp.readFile(templatePath, 'utf8');
|
|
51
|
+
await fsp.writeFile(viewPath, templateContent, "utf8");
|
|
52
|
+
await replaceLastOccurrence(viewPath, '<script', `<script src="/static/pages/pages.${name}.js" type='module'></script>`);
|
|
53
|
+
const routeEntry = `router.route("${pagename}").get((req: Request, res: Response) => res.render("${name}",{fileName:"${name}"}));\n`;
|
|
54
|
+
await fsp.appendFile(routePath, routeEntry, "utf8");
|
|
55
|
+
await fsp.mkdir(jsDir, { recursive: true });
|
|
56
|
+
const jsContent = 'import { gardener, fetchElement, replaceElement, appendElement } from "../gardener.js";\n import {log, parser, addEl, State} from "../gardenerDev.js"';
|
|
57
|
+
await fsp.writeFile(jsFilePath, jsContent, "utf8");
|
|
58
|
+
await fsp.mkdir(bundleDir, { recursive: true });
|
|
59
|
+
const bundleContent = `import '../static/global.js';import '../static/pages/pages.${name}.js'; `;
|
|
60
|
+
await fsp.writeFile(path.join(bundleDir, `bundle.${name}.js`), bundleContent, "utf8");
|
|
61
|
+
res.json({ success: true });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const error = err;
|
|
65
|
+
res.json({ success: false, msg: error.message });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function replaceLastOccurrence(filePath, searchPattern, replacementLine) {
|
|
69
|
+
const content = await fsp.readFile(filePath, 'utf8');
|
|
70
|
+
const lines = content.split('\n');
|
|
71
|
+
let found = false;
|
|
72
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
73
|
+
if (lines[i].includes(searchPattern)) {
|
|
74
|
+
lines[i] = `${replacementLine}\n${lines[i]}`;
|
|
75
|
+
found = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (found) {
|
|
80
|
+
await fsp.writeFile(filePath, lines.join('\n'), 'utf8');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.warn(`Pattern "${searchPattern}" not found in ${filePath}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=addPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addPage.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/addPage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStatic.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/createStatic.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fsp from "fs/promises";
|
|
3
|
+
import ejs from "ejs";
|
|
4
|
+
import { build } from "esbuild";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const frontendDir = path.resolve(__dirname, "..", "..", "..", "frontend");
|
|
9
|
+
async function generateStatic() {
|
|
10
|
+
const viewsDir = path.join(frontendDir, "views");
|
|
11
|
+
const outDir = path.resolve("src/tempfrontend");
|
|
12
|
+
const finalOut = path.resolve("src/frontendStatic");
|
|
13
|
+
await fsp.mkdir(outDir, { recursive: true });
|
|
14
|
+
await fsp.mkdir(finalOut, { recursive: true });
|
|
15
|
+
const entries = await fsp.readdir(viewsDir, { withFileTypes: true });
|
|
16
|
+
const rendered = [];
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
if (!entry.isFile())
|
|
19
|
+
continue;
|
|
20
|
+
if (!entry.name.endsWith(".ejs"))
|
|
21
|
+
continue;
|
|
22
|
+
const inputPath = path.join(viewsDir, entry.name);
|
|
23
|
+
const outputName = entry.name.replace(/\.ejs$/, ".html");
|
|
24
|
+
const outputPath = path.join(outDir, outputName);
|
|
25
|
+
const html = await ejs.renderFile(inputPath, {
|
|
26
|
+
fileName: entry.name.slice(0, -4)
|
|
27
|
+
}, {
|
|
28
|
+
views: [viewsDir],
|
|
29
|
+
});
|
|
30
|
+
await fsp.writeFile(outputPath, html, "utf8");
|
|
31
|
+
rendered.push(outputName);
|
|
32
|
+
}
|
|
33
|
+
const entries3 = await fsp.readdir(outDir, { withFileTypes: true });
|
|
34
|
+
for (const entry of entries3) {
|
|
35
|
+
const parts = entry.name
|
|
36
|
+
.replace(/^_/, "")
|
|
37
|
+
.replace(/\.html$/, "")
|
|
38
|
+
.split("_");
|
|
39
|
+
const targetDir = path.join(finalOut, ...parts);
|
|
40
|
+
const targetFile = path.join(targetDir, "index.html");
|
|
41
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
42
|
+
await fsp.copyFile(path.join(outDir, entry.name), targetFile);
|
|
43
|
+
}
|
|
44
|
+
await fsp.rm(outDir, { recursive: true, force: true });
|
|
45
|
+
await fsp.mkdir(path.join(finalOut, "static"), { recursive: true });
|
|
46
|
+
await fsp.cp(path.join(frontendDir, "static", 'cache'), path.join(finalOut, "static", 'cache'), { recursive: true });
|
|
47
|
+
await fsp.cp(path.join(frontendDir, "static", 'style.css'), path.join(finalOut, "static", 'style.css'), { recursive: true });
|
|
48
|
+
await fsp.cp(path.join(frontendDir, "static", 'style2.css'), path.join(finalOut, "static", 'style2.css'), { recursive: true });
|
|
49
|
+
const srcBundleDir = path.join(frontendDir, "bundle");
|
|
50
|
+
const destBundleDir = path.join(finalOut, "static", "bundle");
|
|
51
|
+
try {
|
|
52
|
+
const bundleFiles = await fsp.readdir(srcBundleDir);
|
|
53
|
+
if (bundleFiles.length) {
|
|
54
|
+
await fsp.mkdir(destBundleDir, { recursive: true });
|
|
55
|
+
for (const file of bundleFiles) {
|
|
56
|
+
const srcFile = path.join(srcBundleDir, file);
|
|
57
|
+
const destFile = path.join(destBundleDir, file);
|
|
58
|
+
await build({
|
|
59
|
+
entryPoints: [srcFile],
|
|
60
|
+
bundle: true,
|
|
61
|
+
minify: true,
|
|
62
|
+
format: "esm",
|
|
63
|
+
outfile: destFile,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const error = err;
|
|
70
|
+
if (error.code !== "ENOENT") {
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
console.log("Static pages generated:", rendered);
|
|
75
|
+
console.log("Output directory:", finalOut);
|
|
76
|
+
}
|
|
77
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
78
|
+
generateStatic().catch((err) => {
|
|
79
|
+
console.error("Static build failed:", err);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=createStatic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStatic.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/createStatic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotReload.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/hotReload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA6BjD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,QAE3D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
// ── Version token ─────────────────────────────────────────────
|
|
4
|
+
// Monotonically-increasing timestamp updated whenever a file
|
|
5
|
+
// in src/frontend/ changes. The frontend stores the first value
|
|
6
|
+
// it sees and reloads as soon as it receives a different one.
|
|
7
|
+
let version = Date.now();
|
|
8
|
+
// ── File watcher ──────────────────────────────────────────────
|
|
9
|
+
const watchTarget = path.resolve('src', 'frontend');
|
|
10
|
+
let debounce = null;
|
|
11
|
+
fs.watch(watchTarget, { recursive: true }, (_event, filename) => {
|
|
12
|
+
// Ignore hidden files and node_modules
|
|
13
|
+
if (!filename || filename.startsWith('.'))
|
|
14
|
+
return;
|
|
15
|
+
if (debounce)
|
|
16
|
+
clearTimeout(debounce);
|
|
17
|
+
debounce = setTimeout(() => {
|
|
18
|
+
version = Date.now();
|
|
19
|
+
// console.log(`[gardener] file changed: ${filename} → version ${version}`);
|
|
20
|
+
}, 100);
|
|
21
|
+
});
|
|
22
|
+
console.log(`[gardener] watching ${watchTarget} for changes…`);
|
|
23
|
+
// ── Route handler ─────────────────────────────────────────────
|
|
24
|
+
// GET /__gardener/hot-reload
|
|
25
|
+
// Returns { version: <number> }
|
|
26
|
+
export function hotReloadHandler(req, res) {
|
|
27
|
+
res.json({ version });
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=hotReload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotReload.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/hotReload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,iEAAiE;AACjE,6DAA6D;AAC7D,gEAAgE;AAChE,8DAA8D;AAC9D,IAAI,OAAO,GAAW,IAAI,CAAC,GAAG,EAAE,CAAC;AAEjC,iEAAiE;AACjE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AAEpD,IAAI,QAAQ,GAAyC,IAAI,CAAC;AAE1D,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;IAC9D,uCAAuC;IACvC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO;IAElD,IAAI,QAAQ;QAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IACrC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;QACzB,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrB,4EAA4E;IAC9E,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,GAAG,CAAC,uBAAuB,WAAW,eAAe,CAAC,CAAC;AAE/D,iEAAiE;AACjE,6BAA6B;AAC7B,gCAAgC;AAChC,MAAM,UAAU,gBAAgB,CAAC,GAAY,EAAE,GAAa;IAC1D,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageOptimiser.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/imageOptimiser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAmEjD,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,sDAwF/D"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import fsp from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import generateWebP from "../../libs/generateWebp.js";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
// Whitelist of allowed remote image domains.
|
|
8
|
+
// Set GARDENER_IMAGE_DOMAINS=example.com,cdn.mysite.com in your .env
|
|
9
|
+
function getAllowedDomains() {
|
|
10
|
+
const raw = process.env.GARDENER_IMAGE_DOMAINS ?? "";
|
|
11
|
+
return raw
|
|
12
|
+
.split(",")
|
|
13
|
+
.map((d) => d.trim().toLowerCase())
|
|
14
|
+
.filter(Boolean);
|
|
15
|
+
}
|
|
16
|
+
function isAllowedUrl(rawUrl) {
|
|
17
|
+
let parsed;
|
|
18
|
+
try {
|
|
19
|
+
parsed = new URL(rawUrl);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return { ok: false, reason: "Malformed URL." };
|
|
23
|
+
}
|
|
24
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
25
|
+
return { ok: false, reason: "Only http/https URLs are allowed." };
|
|
26
|
+
}
|
|
27
|
+
const allowedDomains = getAllowedDomains();
|
|
28
|
+
if (allowedDomains.length === 0) {
|
|
29
|
+
return { ok: false, reason: "No allowed image domains configured. Set GARDENER_IMAGE_DOMAINS in your .env" };
|
|
30
|
+
}
|
|
31
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
32
|
+
const isAllowed = allowedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
|
|
33
|
+
if (!isAllowed) {
|
|
34
|
+
return { ok: false, reason: `Domain '${hostname}' is not in the allowed list.` };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true };
|
|
37
|
+
}
|
|
38
|
+
async function downloadRemoteImage(remoteUrl, destPath) {
|
|
39
|
+
const response = await fetch(remoteUrl);
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error(`Remote fetch failed: ${response.status} ${response.statusText}`);
|
|
42
|
+
}
|
|
43
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
44
|
+
if (!contentType.startsWith("image/")) {
|
|
45
|
+
throw new Error(`Remote URL did not return an image (got: ${contentType})`);
|
|
46
|
+
}
|
|
47
|
+
const buffer = await response.arrayBuffer();
|
|
48
|
+
await fsp.writeFile(destPath, Buffer.from(buffer));
|
|
49
|
+
}
|
|
50
|
+
export async function imageOptimiser(req, res) {
|
|
51
|
+
try {
|
|
52
|
+
const { name } = req.params;
|
|
53
|
+
if (typeof name !== "string") {
|
|
54
|
+
return res.status(400).json({ success: false, message: "invalid path" });
|
|
55
|
+
}
|
|
56
|
+
// name format: baseName_{width}x{height}.webp
|
|
57
|
+
const match = name.match(/^(.+?)_(\d+)x(\d+)\.webp$/);
|
|
58
|
+
if (!match) {
|
|
59
|
+
return res.status(400).json({ error: "Invalid image format. Expected: name_{w}x{h}.webp" });
|
|
60
|
+
}
|
|
61
|
+
const [, baseName, widthStr, heightStr] = match;
|
|
62
|
+
const width = parseInt(widthStr, 10);
|
|
63
|
+
const height = parseInt(heightStr, 10);
|
|
64
|
+
// ── 1. Serve from cache if already converted ────────────────────────────
|
|
65
|
+
const cacheDir = path.join(__dirname, "..", "..", "..", "frontend", "static", "cache");
|
|
66
|
+
await fsp.mkdir(cacheDir, { recursive: true });
|
|
67
|
+
const outputPath = path.join(cacheDir, name);
|
|
68
|
+
try {
|
|
69
|
+
await fsp.access(outputPath);
|
|
70
|
+
return res.sendFile(path.basename(outputPath), { root: path.dirname(outputPath) });
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// not cached → continue
|
|
74
|
+
}
|
|
75
|
+
// ── 2. Locate source image in assets/ (local) ───────────────────────────
|
|
76
|
+
const assetsDir = path.resolve(__dirname, "..", "..", "..", "frontend", "assets");
|
|
77
|
+
await fsp.mkdir(assetsDir, { recursive: true });
|
|
78
|
+
let inputPath = null;
|
|
79
|
+
const localFiles = await fsp.readdir(assetsDir);
|
|
80
|
+
const localMatch = localFiles.find((file) => path.parse(file).name === baseName);
|
|
81
|
+
if (localMatch) {
|
|
82
|
+
inputPath = path.join(assetsDir, localMatch);
|
|
83
|
+
}
|
|
84
|
+
// ── 3. Check assets/remote/ if not found locally ────────────────────────
|
|
85
|
+
const remoteAssetsDir = path.join(assetsDir, "remote");
|
|
86
|
+
await fsp.mkdir(remoteAssetsDir, { recursive: true });
|
|
87
|
+
if (!inputPath) {
|
|
88
|
+
const remoteFiles = await fsp.readdir(remoteAssetsDir);
|
|
89
|
+
const remoteMatch = remoteFiles.find((file) => path.parse(file).name === baseName);
|
|
90
|
+
if (remoteMatch) {
|
|
91
|
+
inputPath = path.join(remoteAssetsDir, remoteMatch);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ── 4. Download from remote URL if provided and still not found ──────────
|
|
95
|
+
if (!inputPath) {
|
|
96
|
+
const remoteUrl = req.query.url;
|
|
97
|
+
if (typeof remoteUrl !== "string" || !remoteUrl) {
|
|
98
|
+
return res.status(404).json({
|
|
99
|
+
error: "Source image not found. Provide ?url=<imageUrl> to use a remote source.",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const urlCheck = isAllowedUrl(remoteUrl);
|
|
103
|
+
if (!urlCheck.ok) {
|
|
104
|
+
return res.status(400).json({ error: urlCheck.reason });
|
|
105
|
+
}
|
|
106
|
+
// Infer extension from URL (fallback to .jpg)
|
|
107
|
+
const urlPathname = new URL(remoteUrl).pathname;
|
|
108
|
+
const remoteExt = path.extname(urlPathname) || ".jpg";
|
|
109
|
+
const destFilename = `${baseName}${remoteExt}`;
|
|
110
|
+
const destPath = path.join(remoteAssetsDir, destFilename);
|
|
111
|
+
await downloadRemoteImage(remoteUrl, destPath);
|
|
112
|
+
inputPath = destPath;
|
|
113
|
+
}
|
|
114
|
+
// ── 5. Convert & cache ───────────────────────────────────────────────────
|
|
115
|
+
await generateWebP(inputPath, outputPath, width, height);
|
|
116
|
+
return res.sendFile(path.basename(outputPath), { root: path.dirname(outputPath) });
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.error(err);
|
|
120
|
+
return res.status(500).json({ error: "Image optimisation failed", detail: String(err) });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=imageOptimiser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageOptimiser.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/imageOptimiser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saveTemplate.d.ts","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/saveTemplate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAWjD,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,+CA8B7D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fsp from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
const frontendDir = path.resolve(__dirname, "..", "..", "..", "frontend");
|
|
7
|
+
const templateDir = path.join(frontendDir, "template");
|
|
8
|
+
export async function saveTemplate(req, res) {
|
|
9
|
+
try {
|
|
10
|
+
const { path: reqPath } = req.body; // ✅ renamed
|
|
11
|
+
const name = reqPath;
|
|
12
|
+
const sourceFile = path.join(frontendDir, 'views', `${name}.ejs`);
|
|
13
|
+
const sourceFileContent = await fsp.readFile(sourceFile, "utf-8");
|
|
14
|
+
const targetFileContent = replaceLastOccurrence(sourceFileContent, `/static/pages/pages.${name}.js`, "");
|
|
15
|
+
// ✅ ensure directory exists
|
|
16
|
+
await fsp.mkdir(templateDir, { recursive: true });
|
|
17
|
+
await fsp.writeFile(path.join(templateDir, `template.${name}.ejs`), targetFileContent, "utf-8");
|
|
18
|
+
return res.json({ message: "Template Saved Successfully" });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
console.error(err);
|
|
22
|
+
return res.status(500).json({ message: "Something went wrong" });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function replaceLastOccurrence(content, searchPattern, replacementLine) {
|
|
26
|
+
const lines = content.split("\n");
|
|
27
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
28
|
+
if (lines[i].includes(searchPattern)) {
|
|
29
|
+
lines[i] = replacementLine; // ✅ replace cleanly
|
|
30
|
+
return lines.join("\n"); // ✅ return result
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
console.warn(`Pattern not found: ${searchPattern}`);
|
|
34
|
+
return content; // fallback
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=saveTemplate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saveTemplate.js","sourceRoot":"","sources":["../../../../src/backend/controllers/gardener/saveTemplate.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY,EAAE,GAAa;IAC5D,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,YAAY;QAEhD,MAAM,IAAI,GAAG,OAAO,CAAC;QAErB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QAElE,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAElE,MAAM,iBAAiB,GAAG,qBAAqB,CAC7C,iBAAiB,EACjB,uBAAuB,IAAI,KAAK,EAChC,EAAE,CACH,CAAC;QAEF,4BAA4B;QAC5B,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAElD,MAAM,GAAG,CAAC,SAAS,CACjB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,IAAI,MAAM,CAAC,EAC9C,iBAAiB,EACjB,OAAO,CACR,CAAC;QAEF,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,OAAe,EACf,aAAqB,EACrB,eAAuB;IAEvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACtC,KAAK,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,oBAAoB;YAChD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAI,kBAAkB;QAChD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,sBAAsB,aAAa,EAAE,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,CAAC,WAAW;AAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateWebp.d.ts","sourceRoot":"","sources":["../../../src/backend/libs/generateWebp.ts"],"names":[],"mappings":"AAIA,wBAA8B,YAAY,CACxC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fsp from "fs/promises";
|
|
3
|
+
import sharp from "sharp";
|
|
4
|
+
export default async function generateWebP(inputPath, outputPath, width, height) {
|
|
5
|
+
const cacheDir = path.dirname(outputPath);
|
|
6
|
+
await fsp.mkdir(cacheDir, { recursive: true });
|
|
7
|
+
await sharp(inputPath)
|
|
8
|
+
.resize(width, height, {
|
|
9
|
+
fit: "inside",
|
|
10
|
+
withoutEnlargement: true,
|
|
11
|
+
})
|
|
12
|
+
.webp({ quality: 100 })
|
|
13
|
+
.toFile(outputPath);
|
|
14
|
+
console.log("✅ Image successfully generated");
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=generateWebp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateWebp.js","sourceRoot":"","sources":["../../../src/backend/libs/generateWebp.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,YAAY,CACxC,SAAiB,EACjB,UAAkB,EAClB,KAAa,EACb,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAG/C,MAAM,KAAK,CAAC,SAAS,CAAC;SACnB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE;QACrB,GAAG,EAAE,QAAQ;QACb,kBAAkB,EAAE,IAAI;KACzB,CAAC;SACD,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SACtB,MAAM,CAAC,UAAU,CAAC,CAAC;IAEtB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gardener.route.d.ts","sourceRoot":"","sources":["../../../src/backend/routes/gardener.route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,QAAA,MAAM,MAAM,EAAE,MAAiB,CAAC;AAChC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { addComponent, addPage, imageOptimiser, saveTemplate, hotReloadHandler } from "../controllers/gardener/index.js";
|
|
3
|
+
const router = Router();
|
|
4
|
+
export default router;
|
|
5
|
+
router.route("/static/cache/:name").get(imageOptimiser);
|
|
6
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
7
|
+
router.route('/addcomponent').post(addComponent);
|
|
8
|
+
router.route('/addpage').post(addPage);
|
|
9
|
+
router.route('/savetemplate').post(saveTemplate);
|
|
10
|
+
router.route('/__gardener/hot-reload').get(hotReloadHandler);
|
|
11
|
+
}
|
|
12
|
+
router.route('/').get((req, res) => res.render('_', { fileName: '_' }));
|
|
13
|
+
//# sourceMappingURL=gardener.route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gardener.route.js","sourceRoot":"","sources":["../../../src/backend/routes/gardener.route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzH,MAAM,MAAM,GAAW,MAAM,EAAE,CAAC;AAChC,eAAe,MAAM,CAAC;AAKtB,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAExD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAMD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/backend/server.ts"],"names":[],"mappings":"AAEA,OAAO,eAAe,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import frontendRoute from './routes/gardener.route.js';
|
|
4
|
+
import path from "path";
|
|
5
|
+
const app = express();
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const staticFiles = path.resolve(__dirname, '..', 'frontend');
|
|
10
|
+
app.set('views', path.join(staticFiles, 'views'));
|
|
11
|
+
app.set("view engine", "ejs");
|
|
12
|
+
app.use(express.static(staticFiles));
|
|
13
|
+
app.use(express.json());
|
|
14
|
+
app.use(frontendRoute);
|
|
15
|
+
app.use((err, req, res, next) => {
|
|
16
|
+
console.error(err.stack);
|
|
17
|
+
res.status(err.status || 500).json({
|
|
18
|
+
success: false,
|
|
19
|
+
message: err.message || "Internal Server Error",
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
const PORT = process.env.PORT || 3000;
|
|
23
|
+
app.listen(PORT, () => {
|
|
24
|
+
console.log("server listening 🚀🚀🚀 PORT:", PORT);
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=server.js.map
|