cleanup for the docker setup
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
parent
ecaa6fb68f
commit
fa2f3acb35
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,7 @@
|
|||||||
|
data.db
|
||||||
*.yaml
|
*.yaml
|
||||||
|
*.yml
|
||||||
*.env
|
*.env
|
||||||
|
|
||||||
|
# don't ignore example deployment stuff
|
||||||
|
!deploy/*
|
||||||
|
@ -2,9 +2,16 @@ FROM golang:1.23.4
|
|||||||
|
|
||||||
WORKDIR /api
|
WORKDIR /api
|
||||||
|
|
||||||
COPY *.go ./
|
RUN useradd runner -r -u 1001 -d /api
|
||||||
|
RUN chown -R runner:runner /api
|
||||||
|
USER runner
|
||||||
|
|
||||||
COPY *.mod ./
|
COPY *.mod ./
|
||||||
COPY *.sum ./
|
COPY *.sum ./
|
||||||
|
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY *.go ./
|
||||||
COPY Makefile ./
|
COPY Makefile ./
|
||||||
COPY config ./config
|
COPY config ./config
|
||||||
COPY database ./database
|
COPY database ./database
|
||||||
@ -14,7 +21,6 @@ COPY status ./status
|
|||||||
COPY util ./util
|
COPY util ./util
|
||||||
COPY views ./views
|
COPY views ./views
|
||||||
|
|
||||||
EXPOSE 7001
|
|
||||||
RUN make
|
RUN make
|
||||||
|
|
||||||
ENTRYPOINT ["/api/api.elf"]
|
ENTRYPOINT ["/api/api.elf"]
|
||||||
|
@ -6,7 +6,7 @@ api.elf: $(GOSRCS)
|
|||||||
go build -o $@
|
go build -o $@
|
||||||
|
|
||||||
run:
|
run:
|
||||||
API_DEBUG=true API_APP_URL=http://localhost:7002 API_PASSWORD=test ./api.elf
|
WEBSITE_DEBUG=true WEBSITE_PASSWORD=test ./api.elf
|
||||||
|
|
||||||
format:
|
format:
|
||||||
gofmt -s -w .
|
gofmt -s -w .
|
||||||
|
@ -39,12 +39,11 @@ func (c *Type) Load() (err error) {
|
|||||||
c.Options = []Option{
|
c.Options = []Option{
|
||||||
{Name: "debug", Value: "false", Type: OPTION_TYPE_BOOL, Required: true}, // should display debug messgaes?
|
{Name: "debug", Value: "false", Type: OPTION_TYPE_BOOL, Required: true}, // should display debug messgaes?
|
||||||
|
|
||||||
{Name: "url", Value: "http://localhost:7001/", Type: OPTION_TYPE_URL, Required: true}, // API URL for the website
|
{Name: "app_url", Value: "http://localhost:7001/", Type: OPTION_TYPE_URL, Required: true}, // frontend application URL for the website
|
||||||
{Name: "app_url", Value: "http://localhost:7002/", Type: OPTION_TYPE_URL, Required: true}, // frontend application URL for the website
|
{Name: "api_url", Value: "http://localhost:7002/", Type: OPTION_TYPE_URL, Required: true}, // API URL for the website
|
||||||
{Name: "doc_url", Value: "http://localhost:7003/", Type: OPTION_TYPE_URL, Required: true}, // documentation URL for the website
|
|
||||||
|
|
||||||
{Name: "password", Value: "", Type: OPTION_TYPE_STR, Required: true}, // admin password
|
{Name: "password", Value: "", Type: OPTION_TYPE_STR, Required: true}, // admin password
|
||||||
{Name: "host", Value: "0.0.0.0:7001", Type: OPTION_TYPE_STR, Required: true}, // host the server should listen on
|
{Name: "host", Value: "0.0.0.0:7002", Type: OPTION_TYPE_STR, Required: true}, // host the server should listen on
|
||||||
{Name: "ip_header", Value: "X-Real-IP", Type: OPTION_TYPE_STR, Required: false}, // header that should be checked for obtaining the client IP
|
{Name: "ip_header", Value: "X-Real-IP", Type: OPTION_TYPE_STR, Required: false}, // header that should be checked for obtaining the client IP
|
||||||
{Name: "interval", Value: "1h", Type: OPTION_TYPE_STR, Required: false}, // service status check interval
|
{Name: "interval", Value: "1h", Type: OPTION_TYPE_STR, Required: false}, // service status check interval
|
||||||
{Name: "timeout", Value: "15s", Type: OPTION_TYPE_STR, Required: false}, // timeout for the service status check
|
{Name: "timeout", Value: "15s", Type: OPTION_TYPE_STR, Required: false}, // timeout for the service status check
|
||||||
|
@ -25,7 +25,7 @@ type Option struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Option) Env() string {
|
func (o *Option) Env() string {
|
||||||
return strings.ToUpper(fmt.Sprintf("API_%s", o.Name))
|
return strings.ToUpper(fmt.Sprintf("WEBSITE_%s", o.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Option) Load() (err error) {
|
func (o *Option) Load() (err error) {
|
||||||
|
@ -7,7 +7,8 @@ import (
|
|||||||
|
|
||||||
func GET_Index(c *fiber.Ctx) error {
|
func GET_Index(c *fiber.Ctx) error {
|
||||||
conf := c.Locals("config").(*config.Type)
|
conf := c.Locals("config").(*config.Type)
|
||||||
doc := conf.GetURL("doc_url")
|
app := conf.GetURL("app_url")
|
||||||
|
|
||||||
return c.Redirect(doc.JoinPath("/api").String())
|
// redirect to the API documentation
|
||||||
|
return c.Redirect(app.JoinPath("/doc/api").String())
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.svelte-kit
|
.svelte-kit
|
||||||
build
|
|
||||||
public
|
public
|
||||||
|
build
|
||||||
|
@ -1,22 +1,39 @@
|
|||||||
FROM node:23.5.0 as build
|
# build the application with node
|
||||||
|
FROM node:23.5.0 AS build
|
||||||
|
|
||||||
|
ARG WEBSITE_REPORT_URL
|
||||||
|
ARG WEBSITE_SOURCE_URL
|
||||||
|
ARG WEBSITE_APP_URL
|
||||||
|
ARG WEBSITE_API_URL
|
||||||
|
ARG WEBSITE_DOC_URL
|
||||||
|
|
||||||
|
ENV WEBSITE_REPORT_URL=$WEBSITE_REPORT_URL
|
||||||
|
ENV WEBSITE_SOURCE_URL=$WEBSITE_SOURCE_URL
|
||||||
|
ENV WEBSITE_APP_URL=$WEBSITE_APP_URL
|
||||||
|
ENV WEBSITE_API_URL=$WEBSITE_API_URL
|
||||||
|
ENV WEBSITE_DOC_URL=$WEBSITE_DOC_URL
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|
||||||
ARG API_URL
|
|
||||||
ENV VITE_API_URL_DEV $API_URL
|
|
||||||
|
|
||||||
RUN npm install && npm run build
|
RUN npm install && npm run build
|
||||||
|
|
||||||
FROM oven/bun:1.1.20 as main
|
# run it with bun (a lot faster)
|
||||||
|
FROM oven/bun:latest AS main
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=build /app/build ./build
|
COPY --from=build /app/build ./build
|
||||||
COPY --from=build /app/package.json ./package.json
|
COPY --from=build /app/package.json ./package.json
|
||||||
COPY --from=build /app/package-lock.json ./package-lock.json
|
COPY --from=build /app/package-lock.json ./package-lock.json
|
||||||
|
|
||||||
EXPOSE 7001
|
RUN useradd runner -r -u 1001 -d /app
|
||||||
|
RUN chown -R runner:runner /app
|
||||||
|
|
||||||
|
USER runner
|
||||||
RUN bun install
|
RUN bun install
|
||||||
|
|
||||||
|
EXPOSE 7001
|
||||||
|
|
||||||
|
ENV PORT=7001
|
||||||
CMD ["bun", "build/index.js"]
|
CMD ["bun", "build/index.js"]
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
"version": "6.0",
|
"version": "6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port 7002 dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview --host",
|
"preview": "vite preview",
|
||||||
"lint": "prettier --check .",
|
"lint": "prettier --check .",
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
@ -21,7 +21,6 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/dompurify": "^3.2.0",
|
|
||||||
"dompurify": "^3.2.3",
|
"dompurify": "^3.2.3",
|
||||||
"marked": "^15.0.6",
|
"marked": "^15.0.6",
|
||||||
"svelte-i18n": "^4.0.1"
|
"svelte-i18n": "^4.0.1"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { urljoin } from "$lib/util.js";
|
import { urljoin } from "$lib/util.js";
|
||||||
|
|
||||||
const api_version = "v1";
|
const api_version = "v1";
|
||||||
const api_url = urljoin(import.meta.env.APP_API_URL, api_version);
|
const api_url = urljoin(import.meta.env.WEBSITE_API_URL, api_version);
|
||||||
|
|
||||||
function api_urljoin(path = null, query = {}) {
|
function api_urljoin(path = null, query = {}) {
|
||||||
return urljoin(api_url, path, query);
|
return urljoin(api_url, path, query);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { urljoin } from "$lib/util.js";
|
import { urljoin } from "$lib/util.js";
|
||||||
|
|
||||||
function doc_urljoin(path = null, query = {}) {
|
function doc_urljoin(path = null, query = {}) {
|
||||||
return urljoin(import.meta.env.APP_DOC_URL, path, query);
|
return urljoin(import.meta.env.WEBSITE_DOC_URL, path, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doc_check_err(json) {
|
function doc_check_err(json) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
{error}
|
{error}
|
||||||
{/if}
|
{/if}
|
||||||
</code>
|
</code>
|
||||||
<Link link={import.meta.env.APP_REPORT_URL}>
|
<Link link={import.meta.env.WEBSITE_REPORT_URL}>
|
||||||
{$_("error.report")}
|
{$_("error.report")}
|
||||||
</Link>
|
</Link>
|
||||||
<img src="/profile/sad.png" alt="" />
|
<img src="/profile/sad.png" alt="" />
|
||||||
|
@ -17,17 +17,17 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<span>
|
<span>
|
||||||
<Link link={import.meta.env.APP_SOURCE_URL} bold={true}>{$_("footer.source")}</Link>
|
<Link link={import.meta.env.WEBSITE_SOURCE_URL} bold={true}>{$_("footer.source")}</Link>
|
||||||
</span>
|
</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span>
|
<span>
|
||||||
<Link link={urljoin(import.meta.env.APP_URL, "doc/license")} bold={true}
|
<Link link={urljoin(import.meta.env.WEBSITE_APP_URL, "doc/license")} bold={true}
|
||||||
>{$_("footer.license")}</Link
|
>{$_("footer.license")}</Link
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span>
|
<span>
|
||||||
<Link link={urljoin(import.meta.env.APP_URL, "doc/privacy")} bold={true}
|
<Link link={urljoin(import.meta.env.WEBSITE_APP_URL, "doc/privacy")} bold={true}
|
||||||
>{$_("footer.privacy")}</Link
|
>{$_("footer.privacy")}</Link
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { frontend_url } from "$lib/util.js";
|
|
||||||
import { api_urljoin } from "$lib/api.js";
|
import { api_urljoin } from "$lib/api.js";
|
||||||
|
import { app_url } from "$lib/util.js";
|
||||||
|
|
||||||
export let desc, title;
|
export let desc, title;
|
||||||
</script>
|
</script>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<meta content="[ngn.tf] | {title}" property="og:title" />
|
<meta content="[ngn.tf] | {title}" property="og:title" />
|
||||||
<meta content={desc} property="og:description" />
|
<meta content={desc} property="og:description" />
|
||||||
<meta content={frontend_url()} property="og:url" />
|
<meta content={app_url()} property="og:url" />
|
||||||
<meta content="#000000" data-react-helmet="true" name="theme-color" />
|
<meta content="#000000" data-react-helmet="true" name="theme-color" />
|
||||||
|
|
||||||
<link
|
<link
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export default [
|
|
||||||
{ code: "en", name: "English", icon: "🇬🇧", path: "../locales/en.json" },
|
|
||||||
{ code: "tr", name: "Turkish", icon: "🇹🇷", path: "../locales/tr.json" },
|
|
||||||
];
|
|
@ -21,11 +21,11 @@
|
|||||||
<Icon {icon} />
|
<Icon {icon} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if highlight}
|
{#if highlight}
|
||||||
<a {style} href={link}>
|
<a data-sveltekit-preload-data {style} href={link}>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<a {style} class="no-highlight" href={link}>
|
<a data-sveltekit-preload-data {style} class="no-highlight" href={link}>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
66
app/src/lib/locale.js
Normal file
66
app/src/lib/locale.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { init, locale, register, waitLocale } from "svelte-i18n";
|
||||||
|
import { browser } from "$app/environment";
|
||||||
|
import { get, writable } from "svelte/store";
|
||||||
|
|
||||||
|
const locale_default = "en";
|
||||||
|
let locale_index = writable(0);
|
||||||
|
let locale_list = [];
|
||||||
|
|
||||||
|
function locale_setup() {
|
||||||
|
// english
|
||||||
|
register("en", () => import("../locales/en.json"));
|
||||||
|
locale_list.push({ code: "en", name: "English", icon: "🇬🇧" });
|
||||||
|
|
||||||
|
// turkish
|
||||||
|
register("tr", () => import("../locales/tr.json"));
|
||||||
|
locale_list.push({ code: "tr", name: "Turkish", icon: "🇹🇷" });
|
||||||
|
|
||||||
|
init({
|
||||||
|
fallbackLocale: locale_default,
|
||||||
|
initialLocale: get(locale),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function locale_from_browser() {
|
||||||
|
if (browser) return window.navigator.language.slice(0, 2).toLowerCase();
|
||||||
|
else return locale_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
function locale_select(l = null) {
|
||||||
|
if (l === null) {
|
||||||
|
if (browser && null !== (l = localStorage.getItem("locale"))) locale_select(l);
|
||||||
|
else locale_select(locale_from_browser());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = l.slice(0, 2);
|
||||||
|
|
||||||
|
for (let i = 0; i < locale_list.length; i++) {
|
||||||
|
if (l !== locale_list[i].code) continue;
|
||||||
|
|
||||||
|
if (browser) localStorage.setItem("locale", l);
|
||||||
|
|
||||||
|
locale.set(l);
|
||||||
|
locale_index.set(i);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
locale.set(locale_default);
|
||||||
|
locale_index.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function locale_wait() {
|
||||||
|
await waitLocale();
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
locale,
|
||||||
|
locale_list,
|
||||||
|
locale_index,
|
||||||
|
locale_default,
|
||||||
|
locale_setup,
|
||||||
|
locale_wait,
|
||||||
|
locale_select,
|
||||||
|
locale_from_browser,
|
||||||
|
};
|
@ -1,38 +1,24 @@
|
|||||||
<script>
|
<script>
|
||||||
import { language, set_lang } from "$lib/util.js";
|
import { locale_list, locale_select, locale_index } from "$lib/locale.js";
|
||||||
import languages from "$lib/lang.js";
|
|
||||||
|
|
||||||
let icon = null,
|
let len = locale_list.length;
|
||||||
indx = 0,
|
|
||||||
len = languages.length;
|
|
||||||
|
|
||||||
function next_indx() {
|
function get_next(indx) {
|
||||||
if (indx + 1 >= len) return 0;
|
let new_indx = 0;
|
||||||
return indx + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function next_lang(inc) {
|
if (indx + 1 >= len) indx = 0;
|
||||||
let new_indx = next_indx();
|
else new_indx = indx + 1;
|
||||||
if (inc) indx = new_indx;
|
|
||||||
return languages[new_indx];
|
return locale_list[new_indx];
|
||||||
}
|
}
|
||||||
|
|
||||||
function next() {
|
function next() {
|
||||||
set_lang(next_lang(true).code);
|
locale_select(get_next($locale_index).code);
|
||||||
icon = next_lang(false).icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (indx = 0; indx < len; indx++) {
|
|
||||||
if (languages[indx].code == $language) {
|
|
||||||
set_lang(languages[indx].code);
|
|
||||||
icon = next_lang(false).icon;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button on:click={next}>
|
<button on:click={next}>
|
||||||
{icon}
|
{get_next($locale_index).icon}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import Icon from "$lib/icon.svelte";
|
import Icon from "$lib/icon.svelte";
|
||||||
import Link from "$lib/link.svelte";
|
import Link from "$lib/link.svelte";
|
||||||
|
|
||||||
import { color, time_from_ts, language } from "$lib/util.js";
|
import { color, time_from_ts } from "$lib/util.js";
|
||||||
import { _ } from "svelte-i18n";
|
import { locale, _ } from "svelte-i18n";
|
||||||
|
|
||||||
export let service = {};
|
export let service = {};
|
||||||
</script>
|
</script>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<h1>{service.name}</h1>
|
<h1>{service.name}</h1>
|
||||||
<p>{service.desc[$language]}</p>
|
<p>{service.desc[$locale]}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<Link highlight={false} link={service.clear}><Icon icon="nf-oct-link" /></Link>
|
<Link highlight={false} link={service.clear}><Icon icon="nf-oct-link" /></Link>
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
import { browser } from "$app/environment";
|
import { locale_from_browser } from "$lib/locale.js";
|
||||||
import { locale } from "svelte-i18n";
|
|
||||||
import languages from "$lib/lang.js";
|
|
||||||
import { writable, get } from "svelte/store";
|
|
||||||
|
|
||||||
const default_language = languages[0].code;
|
|
||||||
const colors = [
|
const colors = [
|
||||||
"yellow",
|
"yellow",
|
||||||
"cyan",
|
"cyan",
|
||||||
@ -13,54 +9,8 @@ const colors = [
|
|||||||
// "blue" (looks kinda ass)
|
// "blue" (looks kinda ass)
|
||||||
];
|
];
|
||||||
|
|
||||||
let language = writable(default_language);
|
|
||||||
let colors_pos = -1;
|
let colors_pos = -1;
|
||||||
|
|
||||||
function browser_lang() {
|
|
||||||
if (browser) return window.navigator.language.slice(0, 2).toLowerCase();
|
|
||||||
else return get(language);
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_lang(lang) {
|
|
||||||
language.set(default_language);
|
|
||||||
locale.set(default_language);
|
|
||||||
|
|
||||||
if (lang === null || lang === undefined) {
|
|
||||||
if (browser && null !== (lang = localStorage.getItem("language"))) set_lang(lang);
|
|
||||||
else if (browser) set_lang(browser_lang());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lang = lang.slice(0, 2);
|
|
||||||
|
|
||||||
for (let i = 0; i < languages.length; i++) {
|
|
||||||
if (lang !== languages[i].code) continue;
|
|
||||||
|
|
||||||
language.set(lang);
|
|
||||||
locale.set(lang);
|
|
||||||
|
|
||||||
if (browser) localStorage.setItem("language", lang);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function urljoin(url, path = null, query = {}) {
|
|
||||||
let url_len = url.length;
|
|
||||||
|
|
||||||
if (url[url_len - 1] != "/") url += "/";
|
|
||||||
|
|
||||||
if (null === path || "" === path) url = new URL(url);
|
|
||||||
else if (path[0] === "/") url = new URL(path.slice(1), url);
|
|
||||||
else url = new URL(path, url);
|
|
||||||
|
|
||||||
for (let k in query) url.searchParams.append(k, query[k]);
|
|
||||||
|
|
||||||
return url.href;
|
|
||||||
}
|
|
||||||
|
|
||||||
function frontend_url(path = null, query = {}) {
|
|
||||||
return urljoin(import.meta.env.APP_URL, path, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
function color() {
|
function color() {
|
||||||
if (colors_pos < 0) colors_pos = Math.floor(Math.random() * colors.length);
|
if (colors_pos < 0) colors_pos = Math.floor(Math.random() * colors.length);
|
||||||
else if (colors_pos >= colors.length) colors_pos = 0;
|
else if (colors_pos >= colors.length) colors_pos = 0;
|
||||||
@ -73,6 +23,26 @@ function click() {
|
|||||||
audio.play();
|
audio.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function urljoin(url, path = null, query = {}) {
|
||||||
|
if (undefined === url || null === url) return;
|
||||||
|
|
||||||
|
let url_len = url.length;
|
||||||
|
|
||||||
|
if (url[url_len - 1] != "/") url += "/";
|
||||||
|
|
||||||
|
if (null === path || "" === path) url = new URL(url);
|
||||||
|
else if (path[0] === "/") url = new URL(path.slice(1), url);
|
||||||
|
else url = new URL(path, url);
|
||||||
|
|
||||||
|
for (let k in query) url.searchParams.append(k, query[k]);
|
||||||
|
|
||||||
|
return url.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
function app_url(path = null, query = {}) {
|
||||||
|
return urljoin(import.meta.env.WEBSITE_APP_URL, path, query);
|
||||||
|
}
|
||||||
|
|
||||||
function time_from_ts(ts) {
|
function time_from_ts(ts) {
|
||||||
if (ts === 0 || ts === undefined) return;
|
if (ts === 0 || ts === undefined) return;
|
||||||
|
|
||||||
@ -80,7 +50,7 @@ function time_from_ts(ts) {
|
|||||||
let ts_zone = ts_date.toString().match(/([A-Z]+[\+-][0-9]+)/)[1];
|
let ts_zone = ts_date.toString().match(/([A-Z]+[\+-][0-9]+)/)[1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
new Intl.DateTimeFormat(browser_lang(), {
|
new Intl.DateTimeFormat(locale_from_browser(), {
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
@ -91,22 +61,11 @@ function time_from_ts(ts) {
|
|||||||
function date_from_ts(ts) {
|
function date_from_ts(ts) {
|
||||||
if (ts === 0 || ts === undefined) return;
|
if (ts === 0 || ts === undefined) return;
|
||||||
|
|
||||||
return new Intl.DateTimeFormat(browser_lang(), {
|
return new Intl.DateTimeFormat(locale_from_browser(), {
|
||||||
month: "2-digit",
|
month: "2-digit",
|
||||||
year: "2-digit",
|
year: "2-digit",
|
||||||
day: "2-digit",
|
day: "2-digit",
|
||||||
}).format(new Date(ts * 1000));
|
}).format(new Date(ts * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { color, click, urljoin, app_url, time_from_ts, date_from_ts };
|
||||||
default_language,
|
|
||||||
browser_lang,
|
|
||||||
language,
|
|
||||||
set_lang,
|
|
||||||
urljoin,
|
|
||||||
frontend_url,
|
|
||||||
click,
|
|
||||||
color,
|
|
||||||
time_from_ts,
|
|
||||||
date_from_ts,
|
|
||||||
};
|
|
||||||
|
@ -1,37 +1,6 @@
|
|||||||
import { default_language, language, set_lang } from "$lib/util.js";
|
import { locale_setup, locale_wait } from "$lib/locale.js";
|
||||||
import { api_get_services, api_get_projects } from "$lib/api.js";
|
|
||||||
import { doc_get_list } from "$lib/doc.js";
|
|
||||||
import languages from "$lib/lang.js";
|
|
||||||
|
|
||||||
import { init, register, waitLocale } from "svelte-i18n";
|
export async function load() {
|
||||||
import { get } from "svelte/store";
|
locale_setup();
|
||||||
|
await locale_wait();
|
||||||
// setup the locale
|
|
||||||
for (let i = 0; i < languages.length; i++)
|
|
||||||
register(languages[i].code, () => import(/* @vite-ignore */ languages[i].path));
|
|
||||||
|
|
||||||
// set the language
|
|
||||||
set_lang();
|
|
||||||
|
|
||||||
init({
|
|
||||||
fallbackLocale: default_language,
|
|
||||||
initialLocale: get(language),
|
|
||||||
});
|
|
||||||
|
|
||||||
// load locales & load data from the API
|
|
||||||
export async function load({ fetch }) {
|
|
||||||
await waitLocale();
|
|
||||||
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
services: await api_get_services(fetch),
|
|
||||||
projects: await api_get_projects(fetch),
|
|
||||||
docs: await doc_get_list(fetch),
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
error: err.toString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
<script>
|
<script>
|
||||||
import Navbar from "$lib/navbar.svelte";
|
import Navbar from "$lib/navbar.svelte";
|
||||||
import Footer from "$lib/footer.svelte";
|
import Footer from "$lib/footer.svelte";
|
||||||
import Error from "$lib/error.svelte";
|
|
||||||
|
|
||||||
let { data, children } = $props();
|
import { locale_select } from "$lib/locale.js";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
let { children } = $props();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
locale_select();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
{#if data.error === null}
|
<Navbar />
|
||||||
<Navbar />
|
<div class="content">
|
||||||
<div class="content">
|
{@render children()}
|
||||||
{@render children()}
|
</div>
|
||||||
</div>
|
<Footer />
|
||||||
<Footer />
|
|
||||||
{:else}
|
|
||||||
<Error error={data.error} />>
|
|
||||||
{/if}
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import "../../static/global.css";
|
@import "/global.css";
|
||||||
|
|
||||||
main {
|
main {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
14
app/src/routes/+page.js
Normal file
14
app/src/routes/+page.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { api_get_projects } from "$lib/api.js";
|
||||||
|
|
||||||
|
export async function load({ fetch }) {
|
||||||
|
try {
|
||||||
|
let projects = await api_get_projects(fetch)
|
||||||
|
return {
|
||||||
|
projects: null === projects ? [] : projects,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
error: err.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,97 +1,106 @@
|
|||||||
<script>
|
<script>
|
||||||
import Header from "$lib/header.svelte";
|
import Header from "$lib/header.svelte";
|
||||||
|
import Error from "$lib/error.svelte";
|
||||||
import Head from "$lib/head.svelte";
|
import Head from "$lib/head.svelte";
|
||||||
import Card from "$lib/card.svelte";
|
import Card from "$lib/card.svelte";
|
||||||
import Link from "$lib/link.svelte";
|
import Link from "$lib/link.svelte";
|
||||||
|
|
||||||
import { color, language } from "$lib/util.js";
|
import { _, locale } from "svelte-i18n";
|
||||||
import { _ } from "svelte-i18n";
|
import { color } from "$lib/util.js";
|
||||||
|
|
||||||
const { data } = $props();
|
let { data } = $props();
|
||||||
let projects = $state(data.projects);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head title="home" desc="home page of my personal website" />
|
<Head title="home" desc="home page of my personal website" />
|
||||||
<Header picture="tired" title={$_("home.title")} />
|
<Header picture="tired" title={$_("home.title")} />
|
||||||
|
|
||||||
<main>
|
{#if data.error !== undefined}
|
||||||
<Card title={$_("home.welcome.title")}>
|
<Error error={data.error} />
|
||||||
<span> 👋 {$_("home.welcome.desc")}</span>
|
{:else}
|
||||||
<ul>
|
<main>
|
||||||
<li>🇹🇷 {$_("home.welcome.whoami")}</li>
|
<Card title={$_("home.welcome.title")}>
|
||||||
<li>🖥️ {$_("home.welcome.interest")}</li>
|
<span> 👋 {$_("home.welcome.desc")}</span>
|
||||||
<li>❤️ {$_("home.welcome.support")}</li>
|
<ul>
|
||||||
</ul>
|
<li>🇹🇷 {$_("home.welcome.whoami")}</li>
|
||||||
</Card>
|
<li>🖥️ {$_("home.welcome.interest")}</li>
|
||||||
<Card title={$_("home.work.title")}>
|
<li>❤️ {$_("home.welcome.support")}</li>
|
||||||
<span>{$_("home.work.desc")}</span>
|
</ul>
|
||||||
<ul>
|
</Card>
|
||||||
<li>⌨️ {$_("home.work.build")}</li>
|
<Card title={$_("home.work.title")}>
|
||||||
<li>🤦 {$_("home.work.fix")}</li>
|
<span>{$_("home.work.desc")}</span>
|
||||||
<li>🚩 {$_("home.work.ctf")}</li>
|
<ul>
|
||||||
<li>👥 {$_("home.work.contribute")}</li>
|
<li>⌨️ {$_("home.work.build")}</li>
|
||||||
<li>📑 {$_("home.work.wiki")}</li>
|
<li>🤦 {$_("home.work.fix")}</li>
|
||||||
</ul>
|
<li>🚩 {$_("home.work.ctf")}</li>
|
||||||
</Card>
|
<li>👥 {$_("home.work.contribute")}</li>
|
||||||
<Card title={$_("home.links.title")}>
|
<li>📑 {$_("home.work.wiki")}</li>
|
||||||
<span>{$_("home.links.desc")}:</span>
|
</ul>
|
||||||
<ul>
|
</Card>
|
||||||
<li>
|
<Card title={$_("home.links.title")}>
|
||||||
<Link icon="nf-fa-key" link="https://keyoxide.org/F9E70878C2FB389AEC2BA34CA3654DF5AD9F641D">
|
<span>{$_("home.links.desc")}:</span>
|
||||||
PGP
|
<ul>
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link icon="nf-md-email" link="mailto:ngn@ngn.tf">Email</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link icon="nf-md-mastodon" link="https://defcon.social/@ngn">Mastodon</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<span>
|
|
||||||
{$_("home.links.prefer")}
|
|
||||||
</span>
|
|
||||||
</Card>
|
|
||||||
<Card title={$_("home.services.title")}>
|
|
||||||
<span>
|
|
||||||
{$_("home.services.desc")}:
|
|
||||||
</span>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<i style="color: var(--{color()});" class="nf nf-md-speedometer_slow"></i>
|
|
||||||
{$_("home.services.speed")}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<i style="color: var(--{color()});" class="nf nf-fa-lock"></i>
|
|
||||||
{$_("home.services.security")}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<i style="color: var(--{color()});" class="nf nf-fa-network_wired"></i>
|
|
||||||
{$_("home.services.privacy")}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<i style="color: var(--{color()});" class="nf nf-md-eye_off"></i>
|
|
||||||
{$_("home.services.bullshit")}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<Link linK="/services">{$_("home.services.link")}</Link>
|
|
||||||
</Card>
|
|
||||||
<Card title={$_("home.projects.title")}>
|
|
||||||
<span>
|
|
||||||
{$_("home.projects.desc")}:
|
|
||||||
</span>
|
|
||||||
<ul>
|
|
||||||
{#each projects.filter((p) => {
|
|
||||||
return p.desc[$language] !== "" && p.desc[$language] !== null && p.desc[$language] !== undefined;
|
|
||||||
}) as project}
|
|
||||||
<li>
|
<li>
|
||||||
<Link active={true} link={project.url}>{project.name}</Link>:
|
<Link
|
||||||
{project.desc[$language]}
|
icon="nf-fa-key"
|
||||||
|
link="https://keyoxide.org/F9E70878C2FB389AEC2BA34CA3654DF5AD9F641D"
|
||||||
|
>
|
||||||
|
PGP
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
<li>
|
||||||
</ul>
|
<Link icon="nf-md-email" link="mailto:ngn@ngn.tf">Email</Link>
|
||||||
</Card>
|
</li>
|
||||||
</main>
|
<li>
|
||||||
|
<Link icon="nf-md-mastodon" link="https://defcon.social/@ngn">Mastodon</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<span>
|
||||||
|
{$_("home.links.prefer")}
|
||||||
|
</span>
|
||||||
|
</Card>
|
||||||
|
<Card title={$_("home.services.title")}>
|
||||||
|
<span>
|
||||||
|
{$_("home.services.desc")}:
|
||||||
|
</span>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<i style="color: var(--{color()});" class="nf nf-md-speedometer_slow"></i>
|
||||||
|
{$_("home.services.speed")}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i style="color: var(--{color()});" class="nf nf-fa-lock"></i>
|
||||||
|
{$_("home.services.security")}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i style="color: var(--{color()});" class="nf nf-fa-network_wired"></i>
|
||||||
|
{$_("home.services.privacy")}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i style="color: var(--{color()});" class="nf nf-md-eye_off"></i>
|
||||||
|
{$_("home.services.bullshit")}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<Link link="/services">{$_("home.services.link")}</Link>
|
||||||
|
</Card>
|
||||||
|
<Card title={$_("home.projects.title")}>
|
||||||
|
<span>
|
||||||
|
{$_("home.projects.desc")}:
|
||||||
|
</span>
|
||||||
|
{#if data.error === undefined}
|
||||||
|
<ul>
|
||||||
|
{#each data.projects.filter((p) => {
|
||||||
|
return p.desc[$locale] !== "" && p.desc[$locale] !== null && p.desc[$locale] !== undefined;
|
||||||
|
}) as project}
|
||||||
|
<li>
|
||||||
|
<Link active={true} link={project.url}>{project.name}</Link>:
|
||||||
|
{project.desc[$locale]}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{/if}
|
||||||
|
</Card>
|
||||||
|
</main>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
main {
|
main {
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { doc_get } from "$lib/doc";
|
import { doc_get_list, doc_get } from "$lib/doc";
|
||||||
|
|
||||||
export async function load({ fetch, params }) {
|
export async function load({ fetch, params }) {
|
||||||
try {
|
try {
|
||||||
return { doc: await doc_get(fetch, params.name) };
|
return {
|
||||||
|
docs: await doc_get_list(fetch),
|
||||||
|
doc: await doc_get(fetch, params.name),
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { error: err.toString() };
|
return { error: err.toString() };
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
<script>
|
<script>
|
||||||
import Header from "$lib/header.svelte";
|
import Header from "$lib/header.svelte";
|
||||||
|
import Error from "$lib/error.svelte";
|
||||||
import Head from "$lib/head.svelte";
|
import Head from "$lib/head.svelte";
|
||||||
|
|
||||||
import { language, color } from "$lib/util.js";
|
import { locale, _ } from "svelte-i18n";
|
||||||
import { goto } from "$app/navigation";
|
import { color } from "$lib/util.js";
|
||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
marked.use({ breaks: true });
|
marked.use({ breaks: true });
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (data.error !== null) return await goto("/");
|
|
||||||
|
|
||||||
for (let key in data.doc)
|
for (let key in data.doc)
|
||||||
data.doc[key]["content"] = DOMPurify.sanitize(data.doc[key]["content"]);
|
data.doc[key]["content"] = DOMPurify.sanitize(data.doc[key]["content"]);
|
||||||
});
|
});
|
||||||
@ -23,28 +21,32 @@
|
|||||||
<Head title="documentation" desc="website and API documentation" />
|
<Head title="documentation" desc="website and API documentation" />
|
||||||
<Header picture="reader" title={$_("doc.title")} />
|
<Header picture="reader" title={$_("doc.title")} />
|
||||||
|
|
||||||
<main>
|
{#if data.error !== undefined}
|
||||||
{#if data.doc !== undefined}
|
<Error error={data.error} />
|
||||||
<div class="markdown-body" style="--link-color: var(--{color()})">
|
{:else}
|
||||||
{@html marked.parse(data.doc[$language].content)}
|
<main>
|
||||||
</div>
|
{#if data.doc !== undefined}
|
||||||
<div class="docs">
|
<div class="markdown-body" style="--link-color: var(--{color()})">
|
||||||
{#each data.docs[$language] as doc}
|
{@html marked.parse(data.doc[$locale].content)}
|
||||||
{#if doc.title == data.doc[$language].title}
|
</div>
|
||||||
<a href="/doc/{doc.name}" style="border-color: var(--{color()})">
|
<div class="docs">
|
||||||
<h1>{doc.title}</h1>
|
{#each data.docs[$locale] as doc}
|
||||||
<h3>{doc.desc}</h3>
|
{#if doc.title == data.doc[$locale].title}
|
||||||
</a>
|
<a href="/doc/{doc.name}" style="border-color: var(--{color()})">
|
||||||
{:else}
|
<h1>{doc.title}</h1>
|
||||||
<a href="/doc/{doc.name}" style="border-color: var(--white-3)">
|
<h3>{doc.desc}</h3>
|
||||||
<h1>{doc.title}</h1>
|
</a>
|
||||||
<h3>{doc.desc}</h3>
|
{:else}
|
||||||
</a>
|
<a href="/doc/{doc.name}" style="border-color: var(--white-3)">
|
||||||
{/if}
|
<h1>{doc.title}</h1>
|
||||||
{/each}
|
<h3>{doc.desc}</h3>
|
||||||
</div>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
</main>
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</main>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import "/markdown.css";
|
@import "/markdown.css";
|
||||||
|
14
app/src/routes/services/+page.js
Normal file
14
app/src/routes/services/+page.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { api_get_services } from "$lib/api.js";
|
||||||
|
|
||||||
|
export async function load({ fetch }) {
|
||||||
|
try {
|
||||||
|
let services = await api_get_services(fetch)
|
||||||
|
return {
|
||||||
|
services: null === services ? [] : services,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
error: err.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import Service from "$lib/service.svelte";
|
import Service from "$lib/service.svelte";
|
||||||
import Header from "$lib/header.svelte";
|
import Header from "$lib/header.svelte";
|
||||||
|
import Error from "$lib/error.svelte";
|
||||||
import Link from "$lib/link.svelte";
|
import Link from "$lib/link.svelte";
|
||||||
import Head from "$lib/head.svelte";
|
import Head from "$lib/head.svelte";
|
||||||
|
|
||||||
import { api_urljoin } from "$lib/api.js";
|
import { api_urljoin } from "$lib/api.js";
|
||||||
import { language } from "$lib/util.js";
|
import { locale, _ } from "svelte-i18n";
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let services = $state(data.services);
|
let services = $state(data.services);
|
||||||
@ -22,15 +22,13 @@
|
|||||||
|
|
||||||
data.services.forEach((s) => {
|
data.services.forEach((s) => {
|
||||||
if (s.name.toLowerCase().includes(value)) services.push(s);
|
if (s.name.toLowerCase().includes(value)) services.push(s);
|
||||||
else if (s.desc[$language].toLowerCase().includes(value)) services.push(s);
|
else if (s.desc[$locale].toLowerCase().includes(value)) services.push(s);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_services() {
|
function get_services() {
|
||||||
return services.filter((s) => {
|
return services.filter((s) => {
|
||||||
return (
|
return s.desc[$locale] !== "" && s.desc[$locale] !== null && s.desc[$locale] !== undefined;
|
||||||
s.desc[$language] !== "" && s.desc[$language] !== null && s.desc[$language] !== undefined
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -38,23 +36,27 @@
|
|||||||
<Head title="services" desc="my self-hosted services and projects" />
|
<Head title="services" desc="my self-hosted services and projects" />
|
||||||
<Header picture="cool" title={$_("services.title")} />
|
<Header picture="cool" title={$_("services.title")} />
|
||||||
|
|
||||||
<main>
|
{#if data.error !== undefined}
|
||||||
<div class="title">
|
<Error error={data.error} />
|
||||||
<input oninput={change} type="text" placeholder={$_("services.search")} />
|
{:else}
|
||||||
<div>
|
<main>
|
||||||
<Link icon="nf-fa-feed" link={api_urljoin("/news/" + $language)}>{$_("services.feed")}</Link>
|
<div class="title">
|
||||||
|
<input oninput={change} type="text" placeholder={$_("services.search")} />
|
||||||
|
<div>
|
||||||
|
<Link icon="nf-fa-feed" link={api_urljoin("/news/" + $locale)}>{$_("services.feed")}</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="services">
|
||||||
<div class="services">
|
{#if get_services().length == 0}
|
||||||
{#if get_services().length == 0}
|
<h3 class="none">{$_("services.none")}</h3>
|
||||||
<h3 class="none">{$_("services.none")}</h3>
|
{:else}
|
||||||
{:else}
|
{#each get_services() as service}
|
||||||
{#each get_services() as service}
|
<Service {service} />
|
||||||
<Service {service} />
|
{/each}
|
||||||
{/each}
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
main {
|
main {
|
||||||
|
@ -6,8 +6,8 @@ import { readFileSync } from "fs";
|
|||||||
const default_env = {
|
const default_env = {
|
||||||
REPORT_URL: "https://github.com/ngn13/website/issues",
|
REPORT_URL: "https://github.com/ngn13/website/issues",
|
||||||
SOURCE_URL: "https://github.com/ngn13/website",
|
SOURCE_URL: "https://github.com/ngn13/website",
|
||||||
API_URL: "http://localhost:7001",
|
APP_URL: "http://localhost:7001",
|
||||||
URL: "http://localhost:7002",
|
API_URL: "http://localhost:7002",
|
||||||
DOC_URL: "http://localhost:7003",
|
DOC_URL: "http://localhost:7003",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,12 +16,20 @@ const json = readFileSync(file, "utf8");
|
|||||||
const pkg = JSON.parse(json);
|
const pkg = JSON.parse(json);
|
||||||
|
|
||||||
for (let env in default_env) {
|
for (let env in default_env) {
|
||||||
if (process.env["APP_" + env] === undefined) process.env["APP_" + env] = default_env[env];
|
if (process.env["WEBSITE_" + env] === undefined) process.env["WEBSITE_" + env] = default_env[env];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [sveltekit()],
|
||||||
envPrefix: "APP",
|
envPrefix: "WEBSITE",
|
||||||
|
preview: {
|
||||||
|
port: 7001,
|
||||||
|
strictPort: true,
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 7001,
|
||||||
|
strictPort: true,
|
||||||
|
},
|
||||||
define: {
|
define: {
|
||||||
pkg: pkg,
|
pkg: pkg,
|
||||||
},
|
},
|
||||||
|
50
deploy/compose.yml
Normal file
50
deploy/compose.yml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: "website_app"
|
||||||
|
image: website_app
|
||||||
|
build:
|
||||||
|
context: ./app
|
||||||
|
args:
|
||||||
|
WEBSITE_SOURCE_URL: http://github.com/ngn13/website
|
||||||
|
WEBSITE_REPORT_URL: http://github.com/ngn13/website/issues
|
||||||
|
WEBSITE_APP_URL: http://localhost:7001
|
||||||
|
WEBSITE_API_URL: http://localhost:7002
|
||||||
|
WEBSITE_DOC_URL: http://doc:7003
|
||||||
|
security_opt:
|
||||||
|
- "no-new-privileges:true"
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:7001:7001"
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- doc
|
||||||
|
|
||||||
|
api:
|
||||||
|
container_name: "website_api"
|
||||||
|
image: website_api
|
||||||
|
build:
|
||||||
|
context: ./api
|
||||||
|
security_opt:
|
||||||
|
- "no-new-privileges:true"
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:7002:7002"
|
||||||
|
volumes:
|
||||||
|
- ./data.db:/api/data.db:rw
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
WEBSITE_PASSWORD: change_me
|
||||||
|
|
||||||
|
doc:
|
||||||
|
container_name: "website_doc"
|
||||||
|
image: website_doc
|
||||||
|
build:
|
||||||
|
context: ./doc
|
||||||
|
security_opt:
|
||||||
|
- ano-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
restart: unless-stopped
|
9
deploy/run.sh
Normal file
9
deploy/run.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ ! -f data.db ]; then
|
||||||
|
touch data.db
|
||||||
|
sudo chmod 1001:1001 data.db
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
@ -7,7 +7,11 @@ COPY docs ./docs
|
|||||||
COPY inc ./inc
|
COPY inc ./inc
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
|
|
||||||
EXPOSE 7003
|
RUN useradd runner -r -u 1001 -d /doc
|
||||||
|
RUN chown -R runner:runner /doc
|
||||||
|
|
||||||
|
USER runner
|
||||||
RUN make
|
RUN make
|
||||||
|
|
||||||
|
EXPOSE 7003
|
||||||
ENTRYPOINT ["/doc/doc.elf"]
|
ENTRYPOINT ["/doc/doc.elf"]
|
||||||
|
@ -18,13 +18,13 @@ option_t options[] = {
|
|||||||
bool config_load(config_t *conf) {
|
bool config_load(config_t *conf) {
|
||||||
bzero(conf, sizeof(*conf));
|
bzero(conf, sizeof(*conf));
|
||||||
|
|
||||||
char name_env[OPT_NAME_MAX + 5], name_copy[OPT_NAME_MAX], *value = NULL;
|
char name_env[OPT_NAME_MAX + 10], name_copy[OPT_NAME_MAX], *value = NULL;
|
||||||
conf->options = options;
|
conf->options = options;
|
||||||
|
|
||||||
for (option_t *opt = conf->options; opt->value != NULL; opt++, conf->count++) {
|
for (option_t *opt = conf->options; opt->value != NULL; opt++, conf->count++) {
|
||||||
strcpy(name_copy, opt->name);
|
strcpy(name_copy, opt->name);
|
||||||
util_toupper(name_copy);
|
util_toupper(name_copy);
|
||||||
snprintf(name_env, sizeof(name_env), "DOC_%s", name_copy);
|
snprintf(name_env, sizeof(name_env), "WEBSITE_%s", name_copy);
|
||||||
|
|
||||||
if ((value = getenv(name_env)) != NULL)
|
if ((value = getenv(name_env)) != NULL)
|
||||||
opt->value = value;
|
opt->value = value;
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# redeployment script for docker-compose
|
|
||||||
docker-compose down
|
|
||||||
docker rmi website_app:latest
|
|
||||||
docker rmi website_api:latest
|
|
||||||
git pull && docker-compose up -d
|
|
Loading…
x
Reference in New Issue
Block a user