feat: ora funge tutto benissimo per qualche motivo

next
Antonio De Lucreziis 2 years ago
parent be57412c40
commit 2b47950556

@ -0,0 +1,2 @@
# Needed by pnpm to work with "@preact/preset-vite"
shamefully-hoist=true

@ -6,5 +6,5 @@ test:
.PHONY: build
build:
go run -v ./cmd/build
pnpm run build --emptyOutDir
pnpm run build
go build -o ./out/bin/server ./cmd/server

@ -29,11 +29,6 @@ func main() {
log.Fatal(err)
}
dev, err := sl.Use(l, dev.Slot)
if err != nil {
log.Fatal(err)
}
f, err := os.Create("out/routes.json")
if err != nil {
log.Fatal(err)
@ -41,7 +36,7 @@ func main() {
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
if err := enc.Encode(dev.HtmlRouteBindings); err != nil {
if err := enc.Encode(dev.UseRoutesMetadata(l)); err != nil {
log.Fatal(err)
}

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ .Title }} &bull; Articoli &bull; PHC</title>
<link rel="stylesheet" href="/styles/main.scss" />
<link rel="stylesheet" href="./typography.scss" />
</head>
<body>
<h1>Articolo "{{ .Example }}"</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque, quasi...</p>
</body>
</html>

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Articoli &bull; PHC</title>
<link rel="stylesheet" href="/styles/main.scss" />
</head>
<body>
<h1>Articoli</h1>
{{ .Example }}
</body>
</html>

@ -0,0 +1,5 @@
*,
*::before,
*::after {
box-sizing: border-box;
}

@ -0,0 +1,18 @@
import fetch from 'node-fetch'
import { readFile } from 'fs/promises'
export async function getBuildRoutesMetadata(file) {
console.log('Loading routes from disk...')
const routesRaw = await readFile(file, 'utf8')
return JSON.parse(routesRaw)
}
export async function getDevRoutesMetadata(url) {
console.log('Loading routes from go server...')
const routesReq = await fetch(url)
const routes = await routesReq.json()
return routes
}

@ -3,12 +3,14 @@
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
"build": "vite build"
"dev": "node server.js",
"build": "vite build --emptyOutDir"
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
"axios": "^1.2.6",
"express": "^4.18.2",
"morgan": "^1.10.0",
"node-fetch": "^3.3.0",
"sass": "^1.57.1",
"vite": "^4.0.4"

@ -3,6 +3,8 @@ lockfileVersion: 5.4
specifiers:
'@preact/preset-vite': ^2.5.0
axios: ^1.2.6
express: ^4.18.2
morgan: ^1.10.0
node-fetch: ^3.3.0
preact: ^10.11.3
sass: ^1.57.1
@ -14,6 +16,8 @@ dependencies:
devDependencies:
'@preact/preset-vite': 2.5.0_preact@10.11.3+vite@4.0.4
axios: 1.2.6
express: 4.18.2
morgan: 1.10.0
node-fetch: 3.3.0
sass: 1.57.1
vite: 4.0.4_sass@1.57.1
@ -562,6 +566,14 @@ packages:
picomatch: 2.3.1
dev: true
/accepts/1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
dependencies:
mime-types: 2.1.35
negotiator: 0.6.3
dev: true
/ansi-styles/3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
@ -577,6 +589,10 @@ packages:
picomatch: 2.3.1
dev: true
/array-flatten/1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
dev: true
/asynckit/0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: true
@ -597,11 +613,38 @@ packages:
'@babel/core': ^7.12.10
dev: true
/basic-auth/2.0.1:
resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
engines: {node: '>= 0.8'}
dependencies:
safe-buffer: 5.1.2
dev: true
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
dev: true
/body-parser/1.20.1:
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dependencies:
bytes: 3.1.2
content-type: 1.0.5
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.11.0
raw-body: 2.5.1
type-is: 1.6.18
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: true
/braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
@ -620,6 +663,18 @@ packages:
update-browserslist-db: 1.0.10_browserslist@4.21.5
dev: true
/bytes/3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
dev: true
/call-bind/1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies:
function-bind: 1.1.1
get-intrinsic: 1.2.0
dev: true
/caniuse-lite/1.0.30001449:
resolution: {integrity: sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==}
dev: true
@ -665,15 +720,47 @@ packages:
delayed-stream: 1.0.0
dev: true
/content-disposition/0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
dependencies:
safe-buffer: 5.2.1
dev: true
/content-type/1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
dev: true
/convert-source-map/1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
dev: true
/cookie-signature/1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
dev: true
/cookie/0.5.0:
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
engines: {node: '>= 0.6'}
dev: true
/data-uri-to-buffer/4.0.1:
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
engines: {node: '>= 12'}
dev: true
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: true
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@ -691,10 +778,29 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
/depd/2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dev: true
/destroy/1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dev: true
/ee-first/1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
dev: true
/electron-to-chromium/1.4.284:
resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==}
dev: true
/encodeurl/1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'}
dev: true
/esbuild/0.16.17:
resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
engines: {node: '>=12'}
@ -730,6 +836,10 @@ packages:
engines: {node: '>=6'}
dev: true
/escape-html/1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
dev: true
/escape-string-regexp/1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
@ -739,6 +849,50 @@ packages:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
/etag/1.8.1:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
dev: true
/express/4.18.2:
resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
engines: {node: '>= 0.10.0'}
dependencies:
accepts: 1.3.8
array-flatten: 1.1.1
body-parser: 1.20.1
content-disposition: 0.5.4
content-type: 1.0.5
cookie: 0.5.0
cookie-signature: 1.0.6
debug: 2.6.9
depd: 2.0.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
finalhandler: 1.2.0
fresh: 0.5.2
http-errors: 2.0.0
merge-descriptors: 1.0.1
methods: 1.1.2
on-finished: 2.4.1
parseurl: 1.3.3
path-to-regexp: 0.1.7
proxy-addr: 2.0.7
qs: 6.11.0
range-parser: 1.2.1
safe-buffer: 5.2.1
send: 0.18.0
serve-static: 1.15.0
setprototypeof: 1.2.0
statuses: 2.0.1
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
transitivePeerDependencies:
- supports-color
dev: true
/fetch-blob/3.2.0:
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
engines: {node: ^12.20 || >= 14.13}
@ -754,6 +908,21 @@ packages:
to-regex-range: 5.0.1
dev: true
/finalhandler/1.2.0:
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
engines: {node: '>= 0.8'}
dependencies:
debug: 2.6.9
encodeurl: 1.0.2
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
statuses: 2.0.1
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: true
/follow-redirects/1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
@ -780,6 +949,16 @@ packages:
fetch-blob: 3.2.0
dev: true
/forwarded/0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
dev: true
/fresh/0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
dev: true
/fsevents/2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@ -797,6 +976,14 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
/get-intrinsic/1.2.0:
resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
has-symbols: 1.0.3
dev: true
/glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@ -814,6 +1001,11 @@ packages:
engines: {node: '>=4'}
dev: true
/has-symbols/1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
dev: true
/has/1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
@ -821,10 +1013,37 @@ packages:
function-bind: 1.1.1
dev: true
/http-errors/2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.1
toidentifier: 1.0.1
dev: true
/iconv-lite/0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
dependencies:
safer-buffer: 2.1.2
dev: true
/immutable/4.2.2:
resolution: {integrity: sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==}
dev: true
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/ipaddr.js/1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
dev: true
/is-binary-path/2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
@ -881,6 +1100,20 @@ packages:
yallist: 3.1.1
dev: true
/media-typer/0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
dev: true
/merge-descriptors/1.0.1:
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
dev: true
/methods/1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
dev: true
/mime-db/1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
@ -893,16 +1126,48 @@ packages:
mime-db: 1.52.0
dev: true
/mime/1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
dev: true
/morgan/1.10.0:
resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==}
engines: {node: '>= 0.8.0'}
dependencies:
basic-auth: 2.0.1
debug: 2.6.9
depd: 2.0.0
on-finished: 2.3.0
on-headers: 1.0.2
transitivePeerDependencies:
- supports-color
dev: true
/ms/2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
dev: true
/ms/2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/ms/2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: true
/nanoid/3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
/negotiator/0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
dev: true
/node-domexception/1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'}
@ -926,10 +1191,42 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/object-inspect/1.12.3:
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
dev: true
/on-finished/2.3.0:
resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
engines: {node: '>= 0.8'}
dependencies:
ee-first: 1.1.1
dev: true
/on-finished/2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
dependencies:
ee-first: 1.1.1
dev: true
/on-headers/1.0.2:
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
engines: {node: '>= 0.8'}
dev: true
/parseurl/1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
dev: true
/path-parse/1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path-to-regexp/0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
dev: true
/picocolors/1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: true
@ -951,10 +1248,40 @@ packages:
/preact/10.11.3:
resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
/proxy-addr/2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
dependencies:
forwarded: 0.2.0
ipaddr.js: 1.9.1
dev: true
/proxy-from-env/1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: true
/qs/6.11.0:
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
engines: {node: '>=0.6'}
dependencies:
side-channel: 1.0.4
dev: true
/range-parser/1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
dev: true
/raw-body/2.5.1:
resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
engines: {node: '>= 0.8'}
dependencies:
bytes: 3.1.2
http-errors: 2.0.0
iconv-lite: 0.4.24
unpipe: 1.0.0
dev: true
/readdirp/3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
@ -979,6 +1306,18 @@ packages:
fsevents: 2.3.2
dev: true
/safe-buffer/5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: true
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: true
/safer-buffer/2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: true
/sass/1.57.1:
resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==}
engines: {node: '>=12.0.0'}
@ -994,11 +1333,61 @@ packages:
hasBin: true
dev: true
/send/0.18.0:
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
engines: {node: '>= 0.8.0'}
dependencies:
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.0
mime: 1.6.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
transitivePeerDependencies:
- supports-color
dev: true
/serve-static/1.15.0:
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
engines: {node: '>= 0.8.0'}
dependencies:
encodeurl: 1.0.2
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.18.0
transitivePeerDependencies:
- supports-color
dev: true
/setprototypeof/1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
dev: true
/side-channel/1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.2.0
object-inspect: 1.12.3
dev: true
/source-map-js/1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
dev: true
/statuses/2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
dev: true
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@ -1023,6 +1412,24 @@ packages:
is-number: 7.0.0
dev: true
/toidentifier/1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
dev: true
/type-is/1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
dependencies:
media-typer: 0.3.0
mime-types: 2.1.35
dev: true
/unpipe/1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
dev: true
/update-browserslist-db/1.0.10_browserslist@4.21.5:
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
hasBin: true
@ -1034,6 +1441,16 @@ packages:
picocolors: 1.0.0
dev: true
/utils-merge/1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
dev: true
/vary/1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
dev: true
/vite/4.0.4_sass@1.57.1:
resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
engines: {node: ^14.18.0 || >=16.0.0}

@ -0,0 +1,76 @@
import express from 'express'
import { createServer as createViteServer } from 'vite'
import { getDevRoutesMetadata } from './meta/routes.js'
import fetch from 'node-fetch'
import { readFile } from 'fs/promises'
import { dirname, resolve } from 'path'
import morgan from 'morgan'
import { fileURLToPath } from 'url'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
async function main() {
const routes = await getDevRoutesMetadata('http://127.0.0.1:4000/api/development/routes')
console.dir(routes)
const app = express()
app.use(morgan(':method :url :status :response-time ms - :res[content-length]'))
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom',
})
app.use(vite.middlewares)
Object.entries(routes.static).forEach(([route, file]) => {
app.get(route, async (_req, res) => {
let htmlPage = await readFile(resolve(__dirname, './frontend/', file), 'utf8')
htmlPage = htmlPage.replace(/\.\//g, '/' + dirname(file) + '/')
const html = await vite.transformIndexHtml(file, htmlPage)
console.dir(file)
res.writeHead(200, { 'Content-Type': 'text/html' }).end(html)
})
})
Object.entries(routes.dynamic).forEach(([route, file]) => {
app.get(route, async (req, res) => {
let htmlPage = await readFile(resolve(__dirname, './frontend/', file), 'utf8')
htmlPage = htmlPage.replace(/\.\//g, '/' + dirname(file) + '/')
const html = await vite.transformIndexHtml(file, htmlPage)
console.log('req.url = ', req.url)
console.log('req.originalUrl = ', req.originalUrl)
const templateHtmlReq = await fetch('http://127.0.0.1:4000/api/development/render', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
route,
page: html,
request: {
params: req.params,
query: req.query,
},
}),
})
const renderedHtml = await templateHtmlReq.json()
res.writeHead(200, { 'Content-Type': 'text/html' }).end(renderedHtml)
})
})
app.listen(3000, () => {
console.log(`Listening on port 3000...`)
})
}
main()

@ -0,0 +1,57 @@
package articles
import (
"html/template"
"phc/website/services/server/dev"
"phc/website/services/server/router"
"phc/website/sl"
)
func Configure(l *sl.ServiceLocator) error {
router.UseRouteTemplatedPage(l, "/articles",
"pages/articles/index.html",
func(w dev.ResponseWriter, r dev.Request) error {
tmpl := template.New("")
tmpl, err := tmpl.Parse(string(r.Page()))
if err != nil {
return err
}
ctx := map[string]any{
"Example": "Bla bla",
}
if err := tmpl.Execute(w, ctx); err != nil {
return err
}
return nil
},
)
router.UseRouteTemplatedPage(l, "/articles/:slug",
"pages/articles/article.html",
func(w dev.ResponseWriter, r dev.Request) error {
tmpl := template.New("")
tmpl, err := tmpl.Parse(string(r.Page()))
if err != nil {
return err
}
ctx := map[string]any{
"Title": r.Param("slug"),
"Example": "Bla bla " + r.Param("slug"),
}
if err := tmpl.Execute(w, ctx); err != nil {
return err
}
return nil
},
)
return nil
}

@ -1,49 +1,157 @@
package dev
import (
"bytes"
"fmt"
"io"
"log"
"path"
"phc/website/services/server/routes"
"phc/website/sl"
"github.com/alecthomas/repr"
"github.com/gofiber/fiber/v2"
)
var Slot = sl.NewSlot[*Dev]()
// slot represents a private "write only" service
var slot = sl.NewSlot[*devService]()
type Dev struct {
HtmlRouteBindings map[string]string
// InjectInto a [*sl.ServiceLocator] an instance of the dev service
func InjectInto(l *sl.ServiceLocator) {
sl.InjectLazy(l, slot, Configure)
}
func New(l *sl.ServiceLocator) (*Dev, error) {
dev := &Dev{
func UseRoutesMetadata(l *sl.ServiceLocator) map[string]any {
dev, err := sl.Use(l, slot)
if err != nil {
log.Fatal(err)
}
return map[string]any{
"static": dev.staticRoutes,
"dynamic": dev.dynamicRoutes,
}
}
type Request interface {
Page() []byte
Param(key string) string
Query(key string) string
}
type ResponseWriter interface {
io.Writer
}
// devServerRequest is used when handling request from the dev server where params and queries are parsed by express
type devServerRequest struct {
page []byte
params map[string]string
query map[string]string
}
func (r devServerRequest) Page() []byte {
return r.page
}
func (r devServerRequest) Param(key string) string {
return r.params[key]
}
func (r devServerRequest) Query(key string) string {
return r.query[key]
}
// Handler is a custom routes handler
type Handler func(ResponseWriter, Request) error
type devService struct {
staticRoutes map[string]string
dynamicRoutes map[string]string
dynamicRoutesHandlers map[string]Handler
}
func Configure(l *sl.ServiceLocator) (*devService, error) {
d := &devService{
map[string]string{},
map[string]string{},
map[string]Handler{},
}
router, err := sl.Use(l, routes.Api)
api, err := sl.Use(l, routes.Api)
if err != nil {
return nil, err
}
router.Get("/dev/routes", func(c *fiber.Ctx) error {
return c.JSON(dev.HtmlRouteBindings)
api.Get("/development/routes", func(c *fiber.Ctx) error {
return c.JSON(map[string]any{
"static": d.staticRoutes,
"dynamic": d.dynamicRoutes,
})
})
return dev, nil
api.Post("/development/render", func(c *fiber.Ctx) error {
var data struct {
Route string `json:"route"`
Page string `json:"page"`
Request struct {
ParamsMap map[string]string `json:"params"`
QueryMap map[string]string `json:"query"`
} `json:"request"`
}
if err := c.BodyParser(&data); err != nil {
return err
}
repr.Print(data)
handler, ok := d.dynamicRoutesHandlers[data.Route]
if !ok {
return fmt.Errorf(`no handler for "%s"`, data.Route)
}
var buf bytes.Buffer
if err := handler(&buf, devServerRequest{
[]byte(data.Page),
data.Request.ParamsMap,
data.Request.QueryMap,
}); err != nil {
return err
}
return c.JSON(buf.String())
})
return d, nil
}
// UseVitePage this hook will link the provided "mountPoint" to the "frontendHtml" page
func UseVitePage(l *sl.ServiceLocator, mountPoint, frontendHtml string) func(c *fiber.Ctx) error {
log.Printf(`registering vite route %q for %q`, frontendHtml, mountPoint)
// RegisterRoute will register the provided "mountPoint" to the "frontendHtml" page
func RegisterRoute(l *sl.ServiceLocator, mountPoint, frontendFile string) {
log.Printf(`registering vite route %q for %q`, frontendFile, mountPoint)
dev, err := sl.Use(l, Slot)
dev, err := sl.Use(l, slot)
if err != nil {
log.Fatal(err)
}
dev.HtmlRouteBindings[mountPoint] = frontendHtml
dev.staticRoutes[mountPoint] = frontendFile
log.Print(dev)
}
return func(c *fiber.Ctx) error {
return c.SendFile(path.Join("./out/frontend/", frontendHtml))
func RegisterDynamicRoute(l *sl.ServiceLocator, mountPoint, frontendFile string, handler Handler) {
log.Printf(`registering vite route %q for %q`, frontendFile, mountPoint)
dev, err := sl.Use(l, slot)
if err != nil {
log.Fatal(err)
}
dev.dynamicRoutes[mountPoint] = frontendFile
dev.dynamicRoutesHandlers[mountPoint] = handler
}
func GetArtifactPath(frontendFile string) string {
return path.Join("./out/frontend/", frontendFile)
}

@ -1,8 +1,8 @@
package lista_utenti
package listaUtenti
import (
"phc/website/services/database"
"phc/website/services/server/dev"
"phc/website/services/server/router"
"phc/website/services/server/routes"
"phc/website/sl"
@ -10,21 +10,19 @@ import (
)
func Configure(l *sl.ServiceLocator) error {
router.UseRoutePage(l, "/utenti", "pages/lista-utenti/index.html")
db, err := sl.Use(l, database.Slot)
if err != nil {
return err
}
r, err := sl.Use(l, routes.Root)
api, err := sl.Use(l, routes.Api)
if err != nil {
return err
}
r.Get("/utenti",
dev.UseVitePage(l, "/utenti", "pages/lista-utenti/index.html"),
)
r.Get("/api/lista-utenti", func(c *fiber.Ctx) error {
api.Get("/lista-utenti", func(c *fiber.Ctx) error {
users, err := db.ReadUsers()
if err != nil {
return err

@ -1,4 +1,4 @@
package lista_utenti_test
package listaUtenti_test
import (
"context"

@ -0,0 +1,72 @@
package router
import (
"bytes"
"log"
"os"
"phc/website/services/server/dev"
"phc/website/services/server/routes"
"phc/website/sl"
"github.com/gofiber/fiber/v2"
)
// assert type of [ServerRequest] is [dev.Request]
var _ dev.Request = ServerRequest{}
// ServerRequest is used when the request is directly for the Go server
type ServerRequest struct {
page []byte
fiberContext *fiber.Ctx
}
func (r ServerRequest) Page() []byte {
return r.page
}
func (ctx ServerRequest) Param(key string) string {
return ctx.fiberContext.Params(key)
}
func (ctx ServerRequest) Query(key string) string {
return ctx.fiberContext.Query(key)
}
func UseRoutePage(l *sl.ServiceLocator, route, frontendFile string) {
root, err := sl.Use(l, routes.Root)
if err != nil {
log.Fatal(err)
}
dev.RegisterRoute(l, route, frontendFile)
root.Get(route, func(c *fiber.Ctx) error {
return c.SendFile(dev.GetArtifactPath(frontendFile))
})
}
func UseRouteTemplatedPage(l *sl.ServiceLocator, route, frontendFile string, handler dev.Handler) {
r, err := sl.Use(l, routes.Root)
if err != nil {
log.Fatal(err)
}
dev.RegisterDynamicRoute(l, route, frontendFile, handler)
r.Get(route, func(c *fiber.Ctx) error {
rawPage, err := os.ReadFile(dev.GetArtifactPath(frontendFile))
if err != nil {
return err
}
var buf bytes.Buffer
if err := handler(&buf, ServerRequest{
rawPage,
c,
}); err != nil {
return err
}
return c.Type(".html").Send(buf.Bytes())
})
}

@ -7,5 +7,4 @@ import (
)
var Root = sl.NewSlot[fiber.Router]()
var Api = sl.NewSlot[fiber.Router]()

@ -1,8 +1,9 @@
package server
import (
"phc/website/services/server/articles"
"phc/website/services/server/dev"
lista_utenti "phc/website/services/server/lista-utenti"
"phc/website/services/server/listaUtenti"
"phc/website/services/server/routes"
"phc/website/sl"
@ -13,17 +14,17 @@ type Server struct{ Router *fiber.App }
func Configure(l *sl.ServiceLocator) (*Server, error) {
r := fiber.New(fiber.Config{})
r.Static("/assets", "./out/frontend/assets")
sl.InjectValue(l, routes.Root, r.Group("/"))
dev.InjectInto(l)
sl.InjectValue(l, routes.Root, fiber.Router(r))
sl.InjectValue(l, routes.Api, r.Group("/api"))
devServerInterop, err := dev.New(l)
if err != nil {
if err := listaUtenti.Configure(l); err != nil {
return nil, err
}
sl.InjectValue(l, dev.Slot, devServerInterop)
if err := lista_utenti.Configure(l); err != nil {
if err := articles.Configure(l); err != nil {
return nil, err
}

@ -28,6 +28,7 @@ func (s *slot) checkInitialized(l *ServiceLocator) error {
log.Printf(`initialized lazy value of type %T for slot of type %s`, v, s.typ)
s.created = true
s.value = v
}
@ -47,7 +48,12 @@ func New() *ServiceLocator {
func InjectValue[T any](l *ServiceLocator, slotKey SlotKey[T], value T) T {
log.Printf(`injected value of type %T for slot of type %s`, value, getTypeName[T]())
l.providers[slotKey] = &slot{nil, true, value, getTypeName[T]()}
l.providers[slotKey] = &slot{
nil,
true,
value,
getTypeName[T](),
}
return value
}

@ -1,68 +1,58 @@
import { defineConfig } from 'vite'
import fetch from 'node-fetch'
import { readFile } from 'fs/promises'
import { dirname, resolve } from 'path'
import { dirname, join, resolve } from 'path'
import preactPlugin from '@preact/preset-vite'
import { getBuildRoutesMetadata } from './meta/routes.js'
const retriveGoRoutes = {
async build() {
console.log('Loading routes from disk...')
const routesRaw = await readFile('out/routes.json', 'utf8')
return JSON.parse(routesRaw)
},
async serve() {
console.log('Loading routes from go server...')
import crypto from 'crypto'
const routesReq = await fetch('http://127.0.0.1:4000/api/dev/routes')
const routes = await routesReq.json()
/** @type {import('vite').UserConfig} */
const sharedConfig = {
root: './frontend',
plugins: [preactPlugin()],
}
return routes
},
function routesToRollupInput([route, file]) {
const chunkName =
file
.replaceAll('.html', '')
.replaceAll('index', '')
.replace(/^\/|\/$/, '')
.replaceAll('/', '-') +
'-' +
crypto.createHash('md5').update(route).update(file).digest('hex').slice(0, 8)
return [chunkName, join(__dirname, 'frontend', file)]
}
export default defineConfig(async config => {
let routes = await retriveGoRoutes[config.command]()
console.dir(routes)
return {
root: 'frontend',
build: {
outDir: '../out/frontend',
rollupOptions: {
input: {
'main': resolve(__dirname, 'frontend/pages/index.html'),
'lista-utenti': resolve(__dirname, 'frontend/pages/lista-utenti/index.html'),
if (config.command === 'build') {
const routes = await getBuildRoutesMetadata('out/routes.json')
const input = Object.fromEntries(
[...Object.entries(routes.static), ...Object.entries(routes.dynamic).map(([route, { htmlFile }]) => [route, htmlFile])].map(
routesToRollupInput
)
)
console.dir(input)
return {
...sharedConfig,
build: {
outDir: '../out/frontend',
rollupOptions: {
input,
},
},
},
server: {
port: 3000,
proxy: {
'/api': 'http://localhost:4000/',
},
},
plugins: [
preactPlugin(),
{
name: 'custom-router',
configureServer(server) {
Object.entries(routes).forEach(([route, file]) => {
server.middlewares.use(route, async (req, res, next) => {
let htmlPage = await readFile(resolve(__dirname, './frontend/', file), 'utf8')
htmlPage = htmlPage.replace(/\.\//g, '/' + dirname(file) + '/')
const url = file
const html = await server.transformIndexHtml(url, htmlPage)
console.log(url)
res.writeHead(200, { 'Content-Type': 'text/html' }).end(html)
})
})
}
} else {
return {
...sharedConfig,
server: {
port: 3000,
proxy: {
'/api': 'http://localhost:4000/',
},
},
],
}
}
})

Loading…
Cancel
Save