demo project

This commit is contained in:
Sebastian Frank 2023-02-21 12:36:06 +00:00
parent 751b6e753c
commit 57bfba5b8d
39 changed files with 4667 additions and 76 deletions

1
.basic-auth-code Normal file
View File

@ -0,0 +1 @@
code:$apr1$AeePIAei$E9E6E6jtFFtwmtGhIEG.Y/

2
.basic-auth-web Normal file
View File

@ -0,0 +1,2 @@
code:$apr1$AeePIAei$E9E6E6jtFFtwmtGhIEG.Y/
web:$apr1$/zc/TBtD$ZGr3RqPiULYMD0kJUup5E0

View File

@ -11,15 +11,21 @@ steps:
commands:
- yarn install
- name: build
##############################
# Build and deploy docs
##############################
- name: build docs
image: node:18
pull: if-not-exists
environment:
FORCE_COLOR: "true"
commands:
- yarn build
- yarn docpress:build
when:
branch: [master]
event: [push]
- name: deploy
- name: deploy docs
image: instrumentisto/rsync-ssh
pull: if-not-exists
environment:
@ -39,3 +45,102 @@ steps:
branch: [master]
event: [push]
##############################
# Demo project
##############################
- name: modify config
image: alpine/git
commands:
- sed -i 's#\(sentryEnvironment.*\)".*"#\1"${DRONE_BRANCH}"#g' frontend/src/config.ts
- sed -i 's#//\( sentry\\.init.*\)#\1#g' frontend/src/config.ts
- export $(cat .env | xargs)
- echo "PROJECT_RELEASE=$${RELEASE_PROJECT_SLUG}.r`git rev-list HEAD --count`-`git describe --all --long | sed 's+/+-+'`" >> .env
- export $(cat .env | xargs)
- cat .env
- sed -i 's#\(const release = \).*#\1"'$${PROJECT_RELEASE}'"#g' api/hooks/config-client.js
- name: build
image: node:18
commands:
- yarn build
- name: build ssr
image: node:18
commands:
- yarn build:server
- name: build legacy
image: node:18
commands:
- yarn build:legacy
- name: modify html
image: bash
commands:
- bash scripts/preload-meta.sh frontend/spa.html
- bash scripts/preload-meta.sh frontend/spa.html > frontend/_spa.html
- cp frontend/_spa.html frontend/spa.html
- export stamp=`date +%s`
- echo $$stamp
- sed -i s/__TIMESTAMP__/$$stamp/g frontend/spa.html
- sed -i s/__TIMESTAMP__/$$stamp/g frontend/serviceworker.js
- cat frontend/serviceworker.js
- cp frontend/spa.html api/templates/spa.html
- cat frontend/spa.html
# staging
- name: copy api config to staging
image: instrumentisto/rsync-ssh
volumes:
- name: data
path: /data
commands:
- rsync -av api /data/
- mkdir -p /data/frontend/dist
- rsync -av frontend/dist/ /data/frontend/dist/
when:
branch: [dev]
event: [push]
- name: review in staging
image: docker/compose:1.22.0
commands:
- docker-compose -p ${DRONE_BRANCH}-${DRONE_REPO_NAME}-${DRONE_REPO_OWNER} up -d --build --remove-orphans
volumes:
- name: docker
path: /var/run/docker.sock
when:
branch: [dev]
event: [push]
# live
- name: deploy master
image: instrumentisto/rsync-ssh
environment:
RSYNC_USER: ""
RSYNC_PASS:
from_secret: rsync_master
commands:
- apk add --no-cache sshpass curl
- scripts/deploy.sh ftp1.webmakers.de $${RSYNC_USER} $${RSYNC_PASS}
# - curl -X POST "https://www....de/api/ssr?token=TowendQhi&clear=1"
when:
branch: [master]
event: [push]
# - name: upload sourcemaps for glitchtip
# image: node
# environment:
# GLITCHTIP_TOKEN:
# from_secret: glitchtip_token
# commands:
# - yarn upload:sourcemaps
########
volumes:
- name: data
host:
path: /data/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}/${DRONE_BRANCH}
- name: docker
host:
path: /var/run/docker.sock

7
.env Normal file
View File

@ -0,0 +1,7 @@
PROJECT_NAME=tibi-docs
TIBI_PREFIX=tibi
TIBI_NAMESPACE=tibi-docs
UID=100
GID=101
RELEASE_ORG_SLUG=webmakers-gmbh
RELEASE_PROJECT_SLUG=tibi-docs

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
_docpress
node_modules
./media
media
tmp
frontend/dist

15
.prettierrc Normal file
View File

@ -0,0 +1,15 @@
{
"printWidth": 120,
"tabWidth": 4,
"singleQuote": false,
"trailingComma": "es5",
"semi": false,
"newline-before-return": true,
"no-duplicate-variable": [true, "check-parameters"],
"no-var-keyword": true,
"svelteSortOrder": "scripts-markup-styles",
"svelteStrictMode": true,
"svelteBracketNewLine": true,
"svelteAllowShorthand": true,
"svelteIndentScriptAndStyle": true
}

16
.vscode/settings.json vendored
View File

@ -1,6 +1,9 @@
{
"editor.tabCompletion": "on",
"diffEditor.codeLens": true,
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"yaml.schemas": {
"./../../cms/tibi-types/schemas/api-config/config.json": "api/config.y*ml",
"./../../cms/tibi-types/schemas/api-config/collection.json": "api/collections/*.y*ml",
@ -9,5 +12,16 @@
"./../../cms/tibi-types/schemas/api-config/job.json": "api/jobs/*.y*ml",
"./../../cms/tibi-types/schemas/api-config/assets.json": "api/assets/*.y*ml"
},
"yaml.customTags": ["!include scalar"]
"yaml.customTags": ["!include scalar"],
"filewatcher.commands": [
{
"match": "/api/.*(\\.ya?ml|js|env)$",
"isAsync": false,
"cmd": "docker compose -p tibi-docs restart tibiserver",
"event": "onFileChange"
}
],
"i18n-ally.localesPaths": ["frontend/locales"],
"i18n-ally.sourceLanguage": "de",
"i18n-ally.keystyle": "nested"
}

49
Makefile Normal file
View File

@ -0,0 +1,49 @@
DOCKER_COMPOSE=docker compose -f docker-compose-local.yml
DOCKER_ALL_PROFILES=--profile docpress --profile tibi-dev --profile tibi --profile chisel
.DEFAULT_GOAL := help
.PHONY: docker-up docker-up-tibi-dev docker-up-chisel docker-up-docpress docker-start docker-start-tibi-dev docker-down docker-ps docker-logs docker-pull yarn-upgrade fix-permissions
include ./.env
help: ## show this help
@echo MAKE TARGETS
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
docker-up: ## bring docker compose stack up in background
$(DOCKER_COMPOSE) --profile tibi up -d
docker-up-tibi-dev: ## bring docker compose stack up in background with tibi-dev
$(DOCKER_COMPOSE) --profile tibi-dev up -d
docker-up-chisel: ## bring up chisel tunnel
$(DOCKER_COMPOSE) --profile chisel up -d
docker-down: ## take docker compose stack down
$(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) down
docker-start: ## start docker compose stack in foreground and take it down after CTRL-C
$(DOCKER_COMPOSE) --profile tibi up; $(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) down
docker-start-tibi-dev: ## start docker compose stack in foreground and take it down after CTRL-C (with tibi-dev)
$(DOCKER_COMPOSE) --profile tibi-dev up; $(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) down
docker-ps: ## show container state
$(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) ps
docker-logs: ## show docker logs and follow
$(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) logs -f || true
docker-pull: ## pull docker images
$(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) pull
docker-%:
$(DOCKER_COMPOSE) $(DOCKER_ALL_PROFILES) $*
yarn-upgrade: # interactive yarn upgrade
$(DOCKER_COMPOSE) run --rm yarnstart yarn upgrade-interactive
$(DOCKER_COMPOSE) restart yarnstart
fix-permissions: # set files/directories owner to UID:GID from .env
sudo chown -R $(UID):$(GID) ./

View File

@ -0,0 +1,10 @@
const release = "tibi-docs.dirty"
// @ts-ignore
if (release && typeof context !== "undefined") {
context.response.header("X-Release", release)
}
module.exports = {
release,
}

20
babel.config.json Normal file
View File

@ -0,0 +1,20 @@
{
"sourceMaps": "inline",
"inputSourceMap": true,
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": {
"version": "3",
"proposals": true
},
"targets": ">0.5%, IE 11, not dead",
"debug": true,
"forceAllTransforms": true
}
]
],
"plugins": []
}

178
docker-compose-local.yml Normal file
View File

@ -0,0 +1,178 @@
version: "3.8"
name: tibi-docs
services:
docpress:
profiles:
- docpress
image: node:18
volumes:
- ./:/data
- ./tmp:/tmp
- ./tmp/nonexistent:/nonexistent
working_dir: /data
command: sh -c "yarn install && yarn docpress:serve"
expose:
- 3000
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-docpress
user: ${UID}:${GID}
yarnstart:
profiles:
- tibi
- tibi-dev
image: node:18
volumes:
- ./:/data
- ./tmp:/tmp
- ./tmp/nonexistent:/nonexistent
working_dir: /data
command: sh -c "yarn install && API_BASE=http://tibiserver:8080/api/v1/_/${TIBI_NAMESPACE} yarn start"
expose:
- 3000
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}
- traefik.http.routers.${PROJECT_NAME}-yarnstart.middlewares=${PROJECT_NAME}-yarnstart
- traefik.http.middlewares.${PROJECT_NAME}-yarnstart.basicauth.usersfile=${PWD}/.basic-auth-web
user: ${UID}:${GID}
tibiserver:
profiles:
- tibi
image: gitbase.de/cms/tibi-server
volumes:
- ./:/data
environment:
DB_DIAL: mongodb://mongo
DB_PREFIX: ${TIBI_PREFIX}
MAIL_HOST: maildev:25
SECURITY_ALLOWABSOLUTEPATHS: "true"
SECURITY_ALLOWUPPERPATHS: "true"
depends_on:
- mongo
expose:
- 8080
labels:
- traefik.enable=true
- traefik.http.services.${PROJECT_NAME}-tibiserver.loadbalancer.server.port=8080
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiserver
tibiserver-dev:
hostname: tibiserver
build:
context: ./
dockerfile: ./../../cms/tibi-server/Dockerfile.air
profiles:
- tibi-dev
volumes:
- ./:/data
- ./../../cms/tibi-server:/tibi-server
- ./../../../../tmp/go/pkg:/go/pkg
working_dir: /tibi-server
environment:
GOCACHE: /tmp/
DB_DIAL: mongodb://mongo
DB_PREFIX: ${TIBI_PREFIX}
MAIL_HOST: maildev:25
SECURITY_ALLOWABSOLUTEPATHS: "true"
SECURITY_ALLOWUPPERPATHS: "true"
depends_on:
- mongo
user: ${UID}:${GID}
expose:
- 8080
labels:
- traefik.enable=true
- traefik.http.services.${PROJECT_NAME}-tibiserver.loadbalancer.server.port=8080
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiserver
tibiadmin:
profiles:
- tibi
image: gitbase.de/cms/tibi-admin
environment:
INDEX: spa.html
WEBROOT: /data
API: /api:http://tibiserver:8080/api/v1
PORT: 80
depends_on:
- tibiserver
expose:
- 80
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin
- traefik.http.routers.${PROJECT_NAME}-tibiadmin.middlewares=${PROJECT_NAME}-tibiadmin
- traefik.http.middlewares.${PROJECT_NAME}-tibiadmin.basicauth.usersfile=${PWD}/.basic-auth-code
tibiadmin-dev:
profiles:
- tibi-dev
image: node:18
volumes:
- ./../../cms/tibi-admin:/data
working_dir: /data
command: sh -c "yarn install && API_BASE=http://tibiserver:8080/api/v1 yarn start:code-server"
expose:
- 3000
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin-dev
- traefik.http.routers.${PROJECT_NAME}-tibiadmin-dev.middlewares=${PROJECT_NAME}-tibiadmin-dev
- traefik.http.middlewares.${PROJECT_NAME}-tibiadmin-dev.basicauth.usersfile=${PWD}/.basic-auth-code
user: ${UID}:${GID}
mongo:
profiles:
- tibi
- tibi-dev
image: gitbase.de/server/mongo:4.2
volumes:
- ./tmp/mongo-data:/data/db
user: ${UID}:${GID}
adminmongo:
profiles:
- tibi
- tibi-dev
image: gitbase.de/server/adminmongo
environment:
CONN_NAME: mongo
DB_HOST: mongo
PORT: 1234
expose:
- 1234
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-adminmongo
- traefik.http.routers.${PROJECT_NAME}-adminmongo.middlewares=${PROJECT_NAME}-adminmongo
- traefik.http.middlewares.${PROJECT_NAME}-adminmongo.basicauth.usersfile=${PWD}/.basic-auth-code
maildev:
profiles:
- tibi
- tibi-dev
image: maildev/maildev
command: node bin/maildev --web 1080 --smtp 25 -v --hide-extensions=STARTTLS
expose:
- 1080
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-maildev
- traefik.http.services.${PROJECT_NAME}-maildev.loadbalancer.server.port=1080
- traefik.http.routers.${PROJECT_NAME}-maildev.middlewares=${PROJECT_NAME}-maildev
- traefik.http.middlewares.${PROJECT_NAME}-maildev.basicauth.usersfile=${PWD}/.basic-auth-code
chisel:
profiles:
- chisel
image: jpillora/chisel
expose:
- 8080
labels:
- traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-chisel
command: server --port 8080 --auth coder:coder

109
esbuild.config.js Normal file
View File

@ -0,0 +1,109 @@
const resolvePlugin = {
name: "resolvePlugin",
setup(build) {
let path = require("path")
// url in css does not resolve via esbuild-svelte correctly
build.onResolve({ filter: /.*/, namespace: "fakecss" }, (args) => {
// console.log(args)
if (args.path.match(/^\./)) return { path: path.dirname(args.importer) + "/" + args.path }
// return { path: path.join(args.resolveDir, "public", args.path) }
})
},
}
////////////////////////// esbuild-svelte
const sveltePlugin = require("esbuild-svelte")
const frontendDir = "./frontend"
const distDir = frontendDir + "/dist"
// console.log("copy public dir...")
// const copydir = require("copy-dir")
// copydir.sync(__dirname + "/public", __dirname + "/" + distDir)
/*copydir.sync(
__dirname + "/public/index.html",
__dirname + "/" + distDir + "/template.html"
)*/
const svelteConfig = require("./svelte.config")
const esbuildSvelte = sveltePlugin({
compilerOptions: {
css: false,
hydratable: true,
dev: (process.argv?.length > 2 ? process.argv[2] : "build") !== "build",
},
preprocess: svelteConfig.preprocess,
cache: true,
filterWarnings: (warning) => {
// filter out a11y
if (warning.code.match(/^a11y/)) return false
return true
},
})
const options = {
logLevel: "info",
color: true,
entryPoints: ["./frontend/src/index.ts"],
outfile: distDir + "/index.mjs",
metafile: true,
format: "esm",
minify: process.argv[2] == "build",
bundle: true,
splitting: false,
plugins: [esbuildSvelte, resolvePlugin],
loader: {
".woff2": "file",
".woff": "file",
".eot": "file",
".svg": "file",
".ttf": "file",
},
sourcemap: true,
target: ["es2020", "chrome61", "firefox60", "safari11", "edge18"],
}
const bsMiddleware = []
if (process.argv[2] == "start") {
const { createProxyMiddleware } = require("http-proxy-middleware")
const apiBase = process.env.API_BASE || "http://localhost:8080/api/v1/_/" + process.env.NAMESPACE
bsMiddleware.push(
createProxyMiddleware("/api", {
target: apiBase,
pathRewrite: { "^/api": "" },
changeOrigin: true,
logLevel: "debug",
})
)
}
module.exports = {
sveltePlugin: sveltePlugin,
resolvePlugin: resolvePlugin,
options: options,
watch: {
path: [__dirname + "/" + frontendDir + "/src/**/*"],
},
serve: {
onRequest(args) {
console.log(args)
},
},
browserSync: {
server: {
baseDir: frontendDir,
middleware: [
require("morgan")("dev"),
...bsMiddleware,
require("connect-history-api-fallback")({
index: "/spa.html",
// verbose: true,
}),
],
},
open: false,
// logLevel: "debug",
},
}

8
esbuild.config.legacy.js Normal file
View File

@ -0,0 +1,8 @@
const config = require("./esbuild.config.js")
config.options.sourcemap = "inline"
config.options.minify = false
config.options.format = "iife"
config.options.outfile = __dirname + "/_temp/index.js"
module.exports = config

23
esbuild.config.server.js Normal file
View File

@ -0,0 +1,23 @@
const config = require("./esbuild.config.js")
const svelteConfig = require("./svelte.config")
config.options.sourcemap = "inline"
config.options.minify = false
config.options.platform = "node"
config.options.format = "cjs"
config.options.entryPoints = ["./frontend/src/ssr.ts"]
config.options.outfile = __dirname + "/_temp/app.server.js"
config.options.plugins = [
config.sveltePlugin({
compilerOptions: {
generate: "ssr",
css: false,
hydratable: true,
dev: (process.argv?.length > 2 ? process.argv[2] : "build") !== "build",
},
preprocess: svelteConfig.preprocess,
}),
config.resolvePlugin,
]
module.exports = config

16
frontend/.htaccess Normal file
View File

@ -0,0 +1,16 @@
AddType application/javascript .mjs
#DirectoryIndex index.html spa.html
DirectoryIndex noindex
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/?api/(.*)$ http://tibi-server:8080/api/v1/_/demo/$1 [P,QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.*)$ http://tibi-server:8080/api/v1/_/demo/ssr?token=owshwerNwoa&url=/$1 [P,QSA,L]
#RewriteRule (.*) /spa.html [QSA,L]
</ifModule>

View File

23
frontend/spa.html Normal file
View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>TibiCMS</title>
<base href="/" />
<link rel="stylesheet" href="/dist/index.css?t=__TIMESTAMP__" />
<!--HEAD-->
<!--PRELOAD-->
</head>
<body>
<div id="appContainer"><!--HTML--></div>
<script type="module" src="/dist/index.mjs?t=__TIMESTAMP__"></script>
<script nomodule src="/dist/index.es5.js?t=__TIMESTAMP__"></script>
</body>
<!--SSR.ERROR-->
<!--SSR.COMMENT-->
</html>

View File

@ -0,0 +1,22 @@
<script lang="ts">
import { location } from "../store"
export let url = ""
if (url) {
// ssr
let l = url.split("?")
$location = {
path: l[0],
search: l.length > 1 ? l[1] : "",
hash: "",
categoryPath: l[0].replace(/\/[^_\/]+_[^\/]+$/, ""),
push: false,
pop: false,
}
}
if (typeof window !== "undefined") console.log("App initialized")
</script>
<h1>Hello World</h1>

5
frontend/src/config.ts Normal file
View File

@ -0,0 +1,5 @@
import configClient from "../../api/hooks/config-client"
export const apiBaseURL = "/api/"
export const release = configClient.release
console.log("Release: ", release)

86
frontend/src/index.ts Normal file
View File

@ -0,0 +1,86 @@
import App from "./components/App.svelte"
import { location } from "./store"
const publishLocation = (_p?: string) => {
let _s: string
let _h: string
if (_p) {
const parts = _p.split("#")
_p = parts.shift()
_h = parts.join()
if (_h) _h = "#" + _h
const parts2 = _p.split("?")
_p = parts2.shift()
_s = parts2.join()
if (_s) _s = "?" + _s
}
const newLocation = {
path:
_p || (typeof window !== "undefined" && window.location?.pathname),
search: _p
? _s
: typeof window !== "undefined" && window.location?.search,
hash: _p ? _h : typeof window !== "undefined" && window.location?.hash,
push: !!_p,
pop: !_p,
categoryPath: "",
}
newLocation.categoryPath = newLocation.path.replace(/\/[^_\/]+_[^\/]+$/, "")
location.set(newLocation)
}
if (typeof history !== "undefined") {
if (typeof Proxy !== "undefined") {
// modern browser
const historyApply = (target, thisArg, argumentsList) => {
publishLocation(
argumentsList && argumentsList.length >= 2 && argumentsList[2]
)
Reflect.apply(target, thisArg, argumentsList)
}
history.pushState = new Proxy(history.pushState, {
apply: historyApply,
})
history.replaceState = new Proxy(history.replaceState, {
apply: historyApply,
})
} else {
// ie11
const pushStateFn = history.pushState
const replaceStateFn = history.replaceState
history.pushState = function (data: any, title: string, url?: string) {
publishLocation(url)
return pushStateFn.apply(history, arguments)
}
history.replaceState = function (
data: any,
title: string,
url?: string
) {
publishLocation(url)
return replaceStateFn.apply(history, arguments)
}
}
} // else ssr -> no history handling
typeof window !== "undefined" &&
window.addEventListener("popstate", (event) => {
publishLocation()
})
let appContainer = document?.getElementById("appContainer")
const hydrate = true //import.meta?.env?.MODE !== "development"
console.log("Features: ", { hydrate })
const app = new App({
target: appContainer,
props: {},
hydrate,
})
export default app

11
frontend/src/store.ts Normal file
View File

@ -0,0 +1,11 @@
import { writable } from "svelte/store"
const initLoc = {
path: (typeof window !== "undefined" && window.location?.pathname) || "/",
search: (typeof window !== "undefined" && window.location?.search) || "",
hash: (typeof window !== "undefined" && window.location?.hash) || "",
push: false,
pop: false,
categoryPath: "",
}
export const location = writable(initLoc)

View File

@ -6,15 +6,52 @@
"author": "Sebastian Frank <sebastian@webmakers.de>",
"license": "MIT",
"packageManager": "yarn@3.2.4",
"scripts": {
"docpress:serve": "docpress serve",
"docpress:build": "docpress build",
"validate": "svelte-check && tsc --noEmit",
"dev": "node scripts/esbuild-wrapper.js watch",
"start": "NAMESPACE=renz_shop node scripts/esbuild-wrapper.js start",
"build": "node scripts/esbuild-wrapper.js build",
"build:legacy": "node scripts/esbuild-wrapper.js build esbuild.config.legacy.js && babel _temp/index.js -o _temp/index.babeled.js && esbuild _temp/index.babeled.js --outfile=frontend/dist/index.es5.js --target=es5 --bundle --minify --sourcemap",
"build:server": "node scripts/esbuild-wrapper.js build esbuild.config.server.js && babel _temp/app.server.js -o _temp/app.server.babeled.js && esbuild _temp/app.server.babeled.js --outfile=api/hooks/lib/app.server.js --target=es5 --bundle --sourcemap --platform=node",
"build:test": "node scripts/esbuild-wrapper.js build esbuild.config.test.js && babel --config-file ./babel.config.test.json _temp/hook.test.js -o _temp/hook.test.babeled.js && esbuild _temp/hook.test.babeled.js --outfile=api/hooks/lib/hook.test.js --target=es5 --bundle --sourcemap --platform=node",
"upload:sourcemaps": "scripts/upload-sourcemaps.sh"
},
"devDependencies": {
"@babel/cli": "^7.20.7",
"@babel/core": "^7.20.12",
"@babel/preset-env": "^7.20.2",
"@tsconfig/svelte": "^3.0.0",
"@types/lodash": "^4.14.191",
"browser-sync": "^2.27.11",
"chokidar": "^3.5.3",
"connect-history-api-fallback": "^2.0.0",
"docpress": "^0.8.2",
"tibi-types": "https://gitbase.de/cms/tibi-types.git#commit=c795339d1c7c91266cafd8b5914a57972565939a"
"esbuild": "^0.17.4",
"esbuild-svelte": "^0.7.3",
"http-proxy-middleware": "^2.0.6",
"less": "^4.1.3",
"morgan": "^1.10.0",
"node-fetch": "^3.3.0",
"postcss": "^8.4.21",
"prettier": "^2.8.3",
"prettier-plugin-svelte": "^2.9.0",
"sass": "^1.57.1",
"svelte": "^3.55.1",
"svelte-check": "^3.0.2",
"svelte-hmr": "^0.15.1",
"svelte-preprocess": "^5.0.1",
"svelte-preprocess-esbuild": "^3.0.1",
"svelte-routing": "^1.6.0",
"tslib": "^2.4.1",
"typescript": "^4.9.4"
},
"dependencies": {
"@sentry/browser": "^7.31.1",
"@sentry/cli": "^2.11.0",
"@sentry/tracing": "^7.31.1",
"core-js": "3.27.2",
"markdown-it-code-include": "./markdown-it-code-include"
},
"scripts": {
"serve": "docpress serve",
"build": "docpress build"
}
}

42
scripts/deploy.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/sh
# if RSYNC_USER or RSYNC_PASS is not set, exit
if [ -z "${RSYNC_USER}" ] || [ -z "${RSYNC_PASS}" ]; then
echo "RSYNC_USER or RSYNC_PASS not set, exiting"
exit 1
fi
excludes=""
if [ "${DRONE_BRANCH}" == "master" ]; then
excludes='--exclude=src --exclude=*.map'
echo "master deploy, excluding $excludes"
fi
# sync frontend
rsync -rlcgD --perms -i -u -v --stats --progress \
--delete \
-e "sshpass -p ${RSYNC_PASS} ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22222" \
$excludes \
frontend/ \
${RSYNC_USER}@ftp1.webmakers.de:./frontend/ \
# sync images getter
rsync -rlcgD --perms -i -u -v --stats --progress \
-e "sshpass -p ${RSYNC_PASS} ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22222" \
images/ \
${RSYNC_USER}@ftp1.webmakers.de:./images/
# sync api config
rsync -rlcgD --perms -i -u -v --stats --progress \
--delete \
-e "sshpass -p ${RSYNC_PASS} ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22222" \
api/ \
${RSYNC_USER}@ftp1.webmakers.de:./api/
# create media directory
mkdir media
chmod 770 media
rsync -rlcgD --perms -i -u -v --stats --progress \
-e "sshpass -p ${RSYNC_PASS} ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 22222" \
media \
${RSYNC_USER}@ftp1.webmakers.de:./

View File

@ -0,0 +1,78 @@
const esbuild = require("esbuild")
const fs = require("fs")
const path = require("path")
const config = require(process.cwd() + (process.argv?.length > 3 ? "/" + process.argv[3] : "/esbuild.config.js"))
const { watch } = require("chokidar")
function log(str, clear) {
if (clear && process.stdout.cursorTo && process.stdout.clearScreenDown) {
process.stdout.cursorTo(0, 0)
process.stdout.clearScreenDown()
}
console.log("\x1b[36m%s\x1b[0m", str)
}
let buildResults
let ctx
async function build(catchError) {
if (!ctx) ctx = await esbuild.context(config.options)
log((buildResults ? "re" : "") + "building...")
const timerStart = Date.now()
try {
buildResults = await ctx.rebuild()
if (config.options.metafile) {
fs.writeFileSync(
(config.options.outfile ? path.dirname(config.options.outfile) : config.options.outdir) + "/meta.json",
JSON.stringify(buildResults.metafile, null, 4)
)
}
} catch (e) {
console.log(e)
if (!catchError) throw e
}
const timerEnd = Date.now()
log(`built in ${timerEnd - timerStart}ms.`)
}
let bs
switch (process.argv?.length > 2 ? process.argv[2] : "build") {
case "serve":
console.log("\x1b[36m%s\x1b[0mserving...")
esbuild.context(config.options).then(function (_ctx) {
_ctx.serve(config.serve).catch((err) => {
console.error(err)
process.exit(1)
})
})
break
case "start":
bs = require("browser-sync")
bs.init(config.browserSync)
case "watch":
// config.options.incremental = true
build(true)
const watcher = watch(config.watch.path)
log("watching files...")
watcher.on("change", function (path) {
log(`${path} changed`, true)
build(true).then(() => {
if (bs) {
bs.reload()
}
})
})
break
default:
esbuild.build(config.options).then(function (buildResults) {
if (config.options.metafile) {
fs.writeFileSync(
(config.options.outfile ? path.dirname(config.options.outfile) : config.options.outdir) +
"/meta.json",
JSON.stringify(buildResults.metafile, null, 4)
)
}
})
}

16
scripts/preload-meta.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
if [ "$1" == "" ]; then
echo template filename required
exit 1
fi
preload=$(for f in frontend/dist/*.woff2; do
echo "<link rel=\"preload\" href=\"/dist/`basename $f`\" as=\"font\" type=\"font/woff2\" crossorigin />"
done)
template="`cat $1 | sed -e 's#<!--PRELOAD-->#\$preload#'`"
eval "cat <<EOF
$template
EOF"

10
scripts/upload-sourcemaps.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
BASEDIR=$(dirname $0)
. $BASEDIR/../.env
echo deleting old release ${RELEASE_ORG_SLUG} ${RELEASE_VERSION:-$RELEASE_PROJECT_SLUG.dirty}
sentry-cli --url https://glitchtip.basehosts.de/ --auth-token ${GLITCHTIP_TOKEN} releases --org ${RELEASE_ORG_SLUG} --project ${RELEASE_PROJECT_SLUG} delete ${RELEASE_VERSION:-$RELEASE_PROJECT_SLUG.dirty}
echo creating release ${RELEASE_ORG_SLUG} ${RELEASE_VERSION:-$RELEASE_PROJECT_SLUG.dirty} and uploading sourcemaps
sentry-cli --url https://glitchtip.basehosts.de/ --auth-token ${GLITCHTIP_TOKEN} releases --org ${RELEASE_ORG_SLUG} --project ${RELEASE_PROJECT_SLUG} files ${RELEASE_VERSION:-$RELEASE_PROJECT_SLUG.dirty} upload-sourcemaps --url-prefix='~/' --ext js --ext mjs --ext svelte --ext map frontend

16
svelte.config.js Normal file
View File

@ -0,0 +1,16 @@
const { typescript } = require("svelte-preprocess-esbuild")
const sveltePreprocess = require("svelte-preprocess")
module.exports = {
preprocess: [
typescript({
sourcemap: true,
}),
sveltePreprocess({
sourceMap: true,
typescript: false,
scss: {
includePaths: ["frontend/src/theme"],
},
}),
],
}

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

24
tsconfig.json Normal file
View File

@ -0,0 +1,24 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["frontend/src/**/*", "types/**/*", "./../../cms/tibi-types", "api/**/*"],
"compilerOptions": {
"module": "esnext",
"typeRoots": ["./node_modules/@types", "./types"],
"target": "esnext",
"moduleResolution": "node",
"jsx": "preserve",
"noEmit": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"useDefineForClassFields": true,
"allowSyntheticDefaultImports": true,
"importsNotUsedAsValues": "error",
"preserveValueImports": true,
"allowJs": true,
"checkJs": true
}
}

3756
yarn.lock

File diff suppressed because it is too large Load Diff