FEAT: switch to vite vue stack
7
.eslintrc.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ["plugin:vue/vue3-essential", "prettier"],
|
||||
rules: {
|
||||
// override/add rules settings here, such as:
|
||||
"vue/no-unused-vars": "error",
|
||||
},
|
||||
};
|
11
.prettierrc.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
semi: false,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
printWidth: 80,
|
||||
endOfLine: "auto",
|
||||
singleQuote: true,
|
||||
trailingComma: "es5",
|
||||
bracketSpacing: true,
|
||||
arrowParens: "always",
|
||||
};
|
4
.vscode/extensions.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
.vscode/launch.json
vendored
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
3
.vscode/settings.json
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"svg.preview.background": "transparent"
|
||||
}
|
@@ -2,12 +2,12 @@ FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json /app/
|
||||
RUN ls
|
||||
COPY package.json /app/
|
||||
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE ${PORT_EXPOSED}
|
||||
CMD ["node", "dist/server/entry.mjs"]
|
||||
CMD vite preview --port ${PORT_EXPOSED}
|
||||
|
21
License
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Shamim Hossain
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
105
README.md
@@ -1,54 +1,83 @@
|
||||
# Welcome to [Astro](https://astro.build)
|
||||
# vue-3-stackter
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
|
||||
[](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/basics)
|
||||

|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
A Vue3 starter project setup with these following components,
|
||||
|
||||

|
||||
- [Vite](https://vitejs.dev/)
|
||||
- vue-meta-3.0.0-alpha.8
|
||||
- Router
|
||||
- [Pinia](https://pinia.vuejs.org/) (Vue 3 default)
|
||||
- Eslint
|
||||
- Prettier
|
||||
- [Tailwind CSS](https://tailwindcss.com/)
|
||||
- File based routing with [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages). (Like [Nuxt file system routing](https://nuxtjs.org/docs/2.x/features/file-system-routing))
|
||||
- Layout system with [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts). (Like [Nuxt layouts](https://nuxtjs.org/docs/2.x/directory-structure/layouts))
|
||||
- Components auto importing with [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components)
|
||||
- `~/` alias for `/src`. So we don't have to write something like `../../../SomeModule` to import modules.
|
||||
- and some custom setups.
|
||||
|
||||
[Check out Typescript version here](https://github.com/shamscorner/vitesse-stackter-clean-architect)
|
||||
|
||||
# Deploy :
|
||||
|
||||
node ./dist/server/entry.mjs
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
### Run this project:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ └── Card.astro
|
||||
│ ├── layouts/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
### Change site name
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
In `App.vue` change the following,
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
```Javascript
|
||||
const siteName = 'Vite App' // add your site name here
|
||||
```
|
||||
|
||||
## 🧞 Commands
|
||||
### Layouts
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
You can add layouts in your project if you want. You will find `default.vue` and `404.vue` layout examples in this project. For more details, check out [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts). (Like [Nuxt layouts](https://nuxtjs.org/docs/2.x/directory-structure/layouts) system).
|
||||
|
||||
| Command | Action |
|
||||
| :--------------------- | :------------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro preview` |
|
||||
| `npm run astro --help` | Get help using the Astro CLI |
|
||||
### Pages
|
||||
|
||||
## 👀 Want to learn more?
|
||||
You can add pages to your project. You will find some example pages in the `pages` directory (`index.vue`, `about/[name].vue`, and `[...all].vue`). For more details, check out [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages). (Like [Nuxt file system routing](https://nuxtjs.org/docs/2.x/features/file-system-routing)).
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
### Meta info
|
||||
|
||||
You can add meta information in your pages. Here is an example,
|
||||
|
||||
```Javascript
|
||||
<script setup>
|
||||
import { useMeta } from 'vue-meta'
|
||||
|
||||
useMeta({
|
||||
title: 'Homepage',
|
||||
})
|
||||
...
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur). Make sure to enable `vetur.experimental.templateInterpolationService` in settings!
|
||||
|
||||
### If Using `<script setup>`
|
||||
|
||||
[`<script setup>`](https://github.com/vuejs/rfcs/pull/227) is a feature that is currently in RFC stage. To get proper IDE support for the syntax, use [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) instead of Vetur (and disable Vetur).
|
||||
|
||||
## Type Support For `.vue` Imports in TS
|
||||
|
||||
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can use the following:
|
||||
|
||||
### If Using Volar
|
||||
|
||||
Run `Volar: Switch TS Plugin on/off` from VSCode command palette.
|
||||
|
||||
### If Using Vetur
|
||||
|
||||
1. Install and add `@vuedx/typescript-plugin-vue` to the [plugins section](https://www.typescriptlang.org/tsconfig#plugins) in `tsconfig.json`
|
||||
2. Delete `src/shims-vue.d.ts` as it is no longer needed to provide module info to Typescript
|
||||
3. Open `src/main.ts` in VSCode
|
||||
4. Open the VSCode command palette
|
||||
5. Search and run "Select TypeScript version" -> "Use workspace version"
|
||||
|
@@ -1,19 +0,0 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
import vue from "@astrojs/vue";
|
||||
|
||||
// https://astro.build/config
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
|
||||
// https://astro.build/config
|
||||
import node from "@astrojs/node";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [vue(), tailwind()],
|
||||
output: "server",
|
||||
adapter: node({
|
||||
mode: 'standalone'
|
||||
}),
|
||||
});
|
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
export DOMAIN="pegazio.domain.com"
|
||||
export PORT="7755"
|
||||
export PORT_EXPOSED="3000"
|
||||
export PORT_EXPOSED="80"
|
||||
export REDIRECTIONS=""
|
||||
|
@@ -1,41 +1,21 @@
|
||||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="https://raw.githubusercontent.com/valerebron/pegaz/master/docs/pegaz.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content="pegaz, deploy stack on the go with docker-compose">
|
||||
<link rel="canonical" href="https://pegaz.io">
|
||||
<meta property="og:title" content="pegaz, deploy stack on the go">
|
||||
<meta property="og:image" content="https://raw.githubusercontent.com/valerebron/pegaz/master/docs/pegaz.svg">
|
||||
<meta property="og:site_name" content="pegaz">
|
||||
<script defer data-domain="pegaz.io" src="https://plausible.erudi.fr/js/plausible.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>pegaz.io</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<style is:global>
|
||||
:root {
|
||||
--accent: 124, 58, 237;
|
||||
--accent-gradient: linear-gradient(45deg, rgb(var(--accent)), #da62c4 30%, white 60%);
|
||||
}
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
</style>
|
11918
package-lock.json
generated
39
package.json
@@ -1,22 +1,29 @@
|
||||
{
|
||||
"name": "@example/basics",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"version": "3.0.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"docker": "docker build . -t pegazio && docker run --network host -p 3000:3000 -d pegazio"
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^3.0.0",
|
||||
"@astrojs/tailwind": "^2.1.2",
|
||||
"@astrojs/vue": "^1.2.1",
|
||||
"astro": "^1.6.7",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"vue": "^3.2.45"
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-vue": "^9.2.0",
|
||||
"pinia": "^2.0.16",
|
||||
"prettier": "^2.7.1",
|
||||
"vue": "^3.2.41",
|
||||
"vue-meta": "3.0.0-alpha.10",
|
||||
"vue-router": "4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vue/compiler-sfc": "^3.2.37",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"postcss": "^8.4.14",
|
||||
"tailwindcss": "^3.1.6",
|
||||
"unplugin-vue-components": "^0.21.1",
|
||||
"vite": "^3.2.3",
|
||||
"vite-plugin-pages": "^0.27.1",
|
||||
"vite-plugin-vue-layouts": "^0.7.0"
|
||||
}
|
||||
}
|
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
@@ -1,652 +0,0 @@
|
||||
#!/bin/bash
|
||||
source /opt/pegaz/env.sh
|
||||
|
||||
SERVICES=$(find $PATH_PEGAZ_SERVICES -mindepth 1 -maxdepth 1 -not -name '.*' -type d -printf ' %f\n' | sort | sed '/^$/d')
|
||||
SERVICES_FLAT=$(echo $SERVICES | tr '\n' ' ')
|
||||
IS_PEGAZDEV="false" && [[ $0 == "cli.pegaz.sh" ]] && IS_PEGAZDEV="true"
|
||||
PATH_COMPAT="$(dirname $0)" # pegazdev compatibility (used for create/drop services)
|
||||
|
||||
# HELPERS
|
||||
|
||||
EXECUTE() {
|
||||
TEST_CONFIG
|
||||
SETUP_NETWORK
|
||||
if [[ -d $PATH_PEGAZ_SERVICES/$2 ]]
|
||||
then
|
||||
cd $PATH_PEGAZ_SERVICES/$2
|
||||
[[ -f "$PATH_PEGAZ/config.sh" ]] && source "$PATH_PEGAZ/config.sh"
|
||||
[[ -f "config.sh" ]] && source "config.sh"
|
||||
[[ -f ".env" ]] && source ".env"
|
||||
docker-compose $1 2>&1 | grep -v "error while removing network"
|
||||
else
|
||||
echo "[x] $2 folder doesn't exist"
|
||||
fi
|
||||
# echo $1 $2
|
||||
local ACT=("stop","down","pause","unpause")
|
||||
[[ "${ACT[*]}" =~ "${1}" ]] && UPDATE_DASHBOARD $2
|
||||
}
|
||||
|
||||
# CHECK_DEPS() {
|
||||
# sed >= 4.7
|
||||
# }
|
||||
|
||||
REMOVE_LINE() {
|
||||
sed -i "/.*$1.*/d" $2 &> /dev/null
|
||||
}
|
||||
|
||||
INSERT_LINE_AFTER() {
|
||||
sed -i "0,/${1//\//\\/}/s//${1//\//\\/}\n${2//\//\\/}/" $3
|
||||
}
|
||||
|
||||
SERVICE_INFOS() {
|
||||
if [[ -f $PATH_PEGAZ_SERVICES/$1/config.sh ]]
|
||||
then
|
||||
if [[ $1 == "proxy" ]]
|
||||
then
|
||||
echo -e "[√] $1 is up"
|
||||
else
|
||||
SOURCE_SERVICE $1
|
||||
echo -e "[√] $1 is up (use pegaz logs $1 to know when the service is ready) \nhttp://$DOMAIN"
|
||||
if [[ $IS_PEGAZDEV == "true" ]]
|
||||
then
|
||||
echo "http://127.0.0.1:$PORT"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
SETUP_NETWORK() {
|
||||
if ! echo $(docker network ls) | grep -q pegaz
|
||||
then
|
||||
echo "[*] create NETWORK"
|
||||
docker network create pegaz
|
||||
fi
|
||||
}
|
||||
|
||||
SETUP_REDIRECTIONS() {
|
||||
unset REDIRECTIONS
|
||||
SOURCE_SERVICE $1
|
||||
if [[ $REDIRECTIONS != "" ]]
|
||||
then
|
||||
PATH_FILE_REDIRECTION="$PATH_PEGAZ_SERVICES/proxy/$FILENAME_REDIRECTION"
|
||||
touch "$PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX" $PATH_FILE_REDIRECTION
|
||||
REMOVE_LINE $AUTO_GENERATED_STAMP "$PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX"
|
||||
REMOVE_LINE $AUTO_GENERATED_STAMP $PATH_FILE_REDIRECTION
|
||||
for REDIRECTION in $REDIRECTIONS
|
||||
do
|
||||
local FROM=${REDIRECTION%->*}
|
||||
local TO=${REDIRECTION#*->}
|
||||
if [[ $FROM == /* ]]; then # same domain
|
||||
echo "rewrite ^$FROM$ http://$DOMAIN$TO permanent; $AUTO_GENERATED_STAMP" >> "$PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX"
|
||||
elif [[ $TO != "" ]] # sub-domain
|
||||
then
|
||||
echo "server {" >> $PATH_FILE_REDIRECTION
|
||||
echo " server_name $FROM.$MAIN_DOMAIN;" >> $PATH_FILE_REDIRECTION
|
||||
echo " return 301 http://$DOMAIN$TO;" >> $PATH_FILE_REDIRECTION
|
||||
echo "}" >> $PATH_FILE_REDIRECTION
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
SETUP_NGINX() {
|
||||
if [[ $DOMAIN != *localhost:* ]]
|
||||
then
|
||||
if [[ -f "$PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX" ]]
|
||||
then
|
||||
if [[ -s "$PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX" ]]
|
||||
then
|
||||
local NEW_LINE=" - $PATH_PEGAZ_SERVICES/$1/$FILENAME_NGINX:/etc/nginx/vhost.d/${DOMAIN}_location"
|
||||
INSERT_LINE_AFTER "docker.sock:ro" "$NEW_LINE" "$PATH_PROXY_COMPOSE"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
SETUP_PROXY() {
|
||||
[[ -f "$PATH_PEGAZ/$FILENAME_CONFIG" ]] && source "$PATH_PEGAZ/$FILENAME_CONFIG" || echo "[x] no pegaz main config file"
|
||||
PATH_PROXY_COMPOSE="$PATH_PEGAZ_SERVICES/proxy/docker-compose.yml"
|
||||
|
||||
rm -rf "$PATH_PEGAZ_SERVICES/proxy/$FILENAME_REDIRECTION" # delete old redirections
|
||||
sed -i "\|$PATH_PEGAZ_SERVICES|d" "$PATH_PROXY_COMPOSE" # delete old vhosts
|
||||
for PATH_SERVICE in $PATH_PEGAZ_SERVICES/*
|
||||
do
|
||||
local NAME_SERVICE=$(basename $PATH_SERVICE)
|
||||
NAME_SERVICE=$(echo $NAME_SERVICE | sed "s%/%%g")
|
||||
[[ -f "$PATH_SERVICE/$FILENAME_CONFIG" ]] && source "$PATH_SERVICE/$FILENAME_CONFIG"
|
||||
SETUP_REDIRECTIONS $NAME_SERVICE
|
||||
SETUP_NGINX $NAME_SERVICE
|
||||
done
|
||||
|
||||
local NEW_LINE=" - $PATH_PEGAZ_SERVICES/proxy/$FILENAME_REDIRECTION:/etc/nginx/conf.d/$FILENAME_REDIRECTION"
|
||||
INSERT_LINE_AFTER "docker.sock:ro" "$NEW_LINE" "$PATH_PROXY_COMPOSE"
|
||||
|
||||
EXECUTE "up -d" "proxy"
|
||||
}
|
||||
|
||||
SOURCE_SERVICE() {
|
||||
[[ -f "$PATH_PEGAZ_SERVICES/$1/$FILENAME_CONFIG" ]] && source "$PATH_PEGAZ_SERVICES/$1/$FILENAME_CONFIG"
|
||||
[[ -f "$PATH_PEGAZ_SERVICES/$1/$FILENAME_ENV" ]] && source "$PATH_PEGAZ_SERVICES/$1/$FILENAME_ENV"
|
||||
}
|
||||
|
||||
PRE_INSTALL() {
|
||||
SOURCE_SERVICE $1
|
||||
local PATH_SCRIPT="$PATH_PEGAZ_SERVICES/$1/$FILENAME_PREINSTALL"
|
||||
if [[ -f $PATH_SCRIPT ]]
|
||||
then
|
||||
echo "[*] pre-install"
|
||||
bash $PATH_SCRIPT $1 $IS_PEGAZDEV
|
||||
fi
|
||||
}
|
||||
|
||||
POST_INSTALL() {
|
||||
local POST_INSTALL_TEST_CMD=""
|
||||
SOURCE_SERVICE $1
|
||||
local PATH_SCRIPT="$PATH_PEGAZ_SERVICES/$1/$FILENAME_POSTINSTALL"
|
||||
if [[ -f $PATH_SCRIPT ]]
|
||||
then
|
||||
echo "[*] post-install: wait for $1 up"
|
||||
if [[ -n $POST_INSTALL_TEST_CMD ]]
|
||||
then
|
||||
while :
|
||||
do
|
||||
$POST_INSTALL_TEST_CMD >> /dev/null
|
||||
if [[ $? -eq 0 ]]
|
||||
then
|
||||
echo "[*] $POST_INSTALL_TEST_CMD is enable, launch post-install.sh"
|
||||
bash $PATH_SCRIPT $1
|
||||
break
|
||||
else
|
||||
continue
|
||||
fi
|
||||
done
|
||||
else
|
||||
while :
|
||||
do
|
||||
HTTP_CODE=$(curl -ILs $DOMAIN | head -n 1 | cut -d$' ' -f2)
|
||||
if [[ $HTTP_CODE < "400" ]]
|
||||
then
|
||||
echo "[*] $DOMAIN http status code is $HTTP_CODE, launch post-install.sh"
|
||||
bash $PATH_SCRIPT $1 &&\
|
||||
break
|
||||
else
|
||||
continue
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ADD_TO_HOSTS() {
|
||||
if [[ $IS_PEGAZDEV == "true" ]]
|
||||
then
|
||||
local PATH_HOSTFILE="/etc/hosts"
|
||||
SOURCE_SERVICE $1
|
||||
if [[ $DOMAIN == *$MAIN_DOMAIN* && -f $PATH_HOSTFILE ]]
|
||||
then
|
||||
if ! grep -q "$DOMAIN" $PATH_HOSTFILE
|
||||
then
|
||||
echo "127.0.0.1 $DOMAIN" | sudo tee -a $PATH_HOSTFILE >> /dev/null
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
SET_ALIAS() {
|
||||
if [[ $1 == "-h" ]] || [[ $1 == "--help" ]]
|
||||
then
|
||||
HELP
|
||||
elif [[ $1 == "-v" ]] || [[ $1 == "--version" ]]
|
||||
then
|
||||
VERSION
|
||||
elif [[ $1 == "ps" ]]
|
||||
then
|
||||
PS
|
||||
fi
|
||||
}
|
||||
|
||||
MANAGE_BACKUP() {
|
||||
mkdir -p $PATH_PEGAZ_BACKUP
|
||||
case $2 in
|
||||
backup) EXECUTE "pause" $1;;
|
||||
restore) EXECUTE "stop" $1;;
|
||||
esac
|
||||
echo "[*] $1 $2"
|
||||
for VOLUME in $(EXECUTE "config --volumes" $1)
|
||||
do
|
||||
local VOLUME=($(docker volume inspect --format "{{.Name}} {{.Mountpoint}}" "$1_$VOLUME" 2> /dev/null))
|
||||
local NAME_VOLUME=${VOLUME[0]}
|
||||
local PATH_VOLUME=${VOLUME[1]}
|
||||
if [[ -n $NAME_VOLUME ]]
|
||||
then
|
||||
local PATH_TARBALL="$PATH_PEGAZ_BACKUP/$NAME_VOLUME.tar.gz"
|
||||
case $2 in
|
||||
backup)
|
||||
docker run --rm -v $NAME_VOLUME:/$NAME_VOLUME -v $PATH_PEGAZ_BACKUP:/backup busybox tar czvf /backup/$NAME_VOLUME.tar.gz /$NAME_VOLUME;;
|
||||
restore)
|
||||
docker run --rm -v $NAME_VOLUME:/$NAME_VOLUME -v $PATH_PEGAZ_BACKUP:/backup busybox sh -c "cd /$NAME_VOLUME && tar xvf /backup/$NAME_VOLUME.tar.gz --strip 1";;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
case $2 in
|
||||
backup) EXECUTE "unpause" $1;;
|
||||
restore) EXECUTE "start" $1;;
|
||||
esac
|
||||
echo "[√] $1 $2 done"
|
||||
}
|
||||
|
||||
STORJ() {
|
||||
if ! command -v "unzip" 1>/dev/null
|
||||
then
|
||||
sudo apt install unzip
|
||||
fi
|
||||
if ! command -v "uplink" 1>/dev/null
|
||||
then
|
||||
echo "[*] install uplink"
|
||||
curl -L https://github.com/storj/storj/releases/latest/download/uplink_linux_amd64.zip -o uplink_linux_amd64.zip
|
||||
unzip -o uplink_linux_amd64.zip
|
||||
sudo install uplink /usr/local/bin/uplink
|
||||
rm uplink_linux_amd64.zip
|
||||
uplink setup
|
||||
fi
|
||||
echo "what's your bucket name ?"
|
||||
read BUCKET_NAME
|
||||
if [[ -z $1 ]] || [[ $1 == "backup" ]]
|
||||
then
|
||||
uplink cp -r --progress /opt/pegaz/backup sj://$BUCKET_NAME
|
||||
elif [[ $1 == "restore" ]]
|
||||
then
|
||||
mkdir -p $PATH_PEGAZ_BACKUP
|
||||
uplink cp -r --progress sj://$BUCKET_NAME /opt/pegaz/backup
|
||||
fi
|
||||
}
|
||||
|
||||
GET_LAST_PORT() {
|
||||
local THE_LAST_PORT="0"
|
||||
for PATH_SERVICE in $PATH_PEGAZ_SERVICES/*
|
||||
do
|
||||
[[ $PATH_SERVICE == "$PATH_PEGAZ_SERVICES/deluge" ]] && continue
|
||||
if [[ -f "$PATH_SERVICE/$FILENAME_CONFIG" || -f "$PATH_SERVICE/$FILENAME_ENV" ]]
|
||||
then
|
||||
if [[ -f "$PATH_SERVICE/$FILENAME_CONFIG" ]]
|
||||
then
|
||||
SED_PREFIX="export PORT" && FILENAME=$FILENAME_CONFIG
|
||||
else
|
||||
SED_PREFIX="PORT" && FILENAME=$FILENAME_ENV
|
||||
fi
|
||||
local CURRENT_PORT=`sed -n "s/^$SED_PREFIX\(.*\)/\1/p" < "$PATH_SERVICE/$FILENAME"`
|
||||
CURRENT_PORT=$(echo $CURRENT_PORT | tr ' ' '\n' | grep -v '_EXPOSED=' | grep -o -E '[0-9]+' | sort -nr | head -n1)
|
||||
fi
|
||||
if [[ $CURRENT_PORT ]]
|
||||
then
|
||||
CURRENT_PORT=`sed -e 's/^"//' -e 's/"$//' <<<"$CURRENT_PORT"`
|
||||
if [ "${CURRENT_PORT}" -gt "${THE_LAST_PORT}" ]
|
||||
then
|
||||
THE_LAST_PORT=$CURRENT_PORT
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo $THE_LAST_PORT
|
||||
}
|
||||
|
||||
GET_STATE() {
|
||||
local RESTARTING="$(docker ps -a --format "{{.Names}} {{.State}}" | grep "$1" | grep "restarting")"
|
||||
if [[ -n $RESTARTING ]]
|
||||
then
|
||||
echo "restarting"
|
||||
else
|
||||
local STARTING="$(docker ps -a --format "{{.Names}} {{.Status}}" | grep "$1" | grep "starting")"
|
||||
if [[ -n $STARTING ]]
|
||||
then
|
||||
echo "starting"
|
||||
else
|
||||
local STATE="$(docker ps -a --format "{{.Names}} {{.State}}" | grep "$1 ")"
|
||||
if [[ -n $STATE ]]
|
||||
then
|
||||
STATE=${STATE/$1 /}
|
||||
STATE=${STATE/running/up}
|
||||
STATE=${STATE/exited/stopped}
|
||||
if [[ $STATE == "up" ]]
|
||||
then
|
||||
SOURCE_SERVICE $1
|
||||
if [[ -n $DOMAIN ]]
|
||||
then
|
||||
STATE="http://$DOMAIN"
|
||||
fi
|
||||
fi
|
||||
echo $STATE
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
UPDATE_DASHBOARD() {
|
||||
[[ $1 != "dashboard" && -n $(GET_STATE "dashboard") ]] && bash "$PATH_PEGAZ_SERVICES/dashboard/$FILENAME_POSTINSTALL" "dashboard"
|
||||
}
|
||||
|
||||
TEST_CONFIG() {
|
||||
source $PATH_PEGAZ/config.sh
|
||||
[[ -z $MAIN_DOMAIN || -z $USERNAME || -z $PASSWORD ]] && echo "[!] config pegaz first" && CONFIG
|
||||
[[ $MAIN_DOMAIN == "domain.com" && $IS_PEGAZDEV == "false" ]] && echo "[!] please configure pegaz first" && CONFIG
|
||||
}
|
||||
|
||||
# CORE COMMANDS
|
||||
|
||||
CONFIG() {
|
||||
source $PATH_COMPAT/config.sh
|
||||
[[ -n $MAIN_DOMAIN ]] && echo "[?] Domain [$MAIN_DOMAIN]:" || echo "[?] Domain:"
|
||||
read NEW_MAIN_DOMAIN
|
||||
[[ -n $NEW_MAIN_DOMAIN ]] && sed -i "s|MAIN_DOMAIN=.*|MAIN_DOMAIN=\"$NEW_MAIN_DOMAIN\"|g" $PATH_COMPAT/config.sh;
|
||||
|
||||
[[ -n $USERNAME ]] && echo "[?] Username [$USERNAME]:" || echo "[?] Username:"
|
||||
read NEW_USERNAME
|
||||
[[ -n $NEW_USERNAME ]] && sed -i "s|USERNAME=.*|USERNAME=\"$NEW_USERNAME\"|g" $PATH_COMPAT/config.sh
|
||||
|
||||
echo "[?] Password:"
|
||||
read -s PASSWORD
|
||||
[[ -n $PASSWORD ]] && sed -i "s|PASSWORD=.*|PASSWORD=\"$PASSWORD\"|g" $PATH_COMPAT/config.sh
|
||||
|
||||
[[ $EMAIL == "user@domain.com" && -n $NEW_USERNAME && -n $NEW_MAIN_DOMAIN ]] && EMAIL="$NEW_USERNAME@$NEW_MAIN_DOMAIN"
|
||||
[[ -n $EMAIL ]] && echo "[?] Email [$EMAIL]:" || echo "[?] Email:"
|
||||
read NEW_EMAIL
|
||||
if [[ -n $NEW_EMAIL ]]
|
||||
then
|
||||
sed -i "s|EMAIL=.*|EMAIL=\"$NEW_EMAIL\"|g" $PATH_COMPAT/config.sh
|
||||
else
|
||||
sed -i "s|EMAIL=.*|EMAIL=\"$EMAIL\"|g" $PATH_COMPAT/config.sh
|
||||
fi
|
||||
|
||||
echo -e "[?] Media Path [$MEDIA_DIR]:"
|
||||
read MEDIA_DIR
|
||||
[[ -n $MEDIA_DIR ]] && {
|
||||
[[ -d $MEDIA_DIR ]] && sed -i "s|MEDIA_DIR=.*|MEDIA_DIR=\"$MEDIA_DIR\"|g" $PATH_COMPAT/config.sh || echo "[x] $MEDIA_DIR doesn't exist"
|
||||
}
|
||||
|
||||
echo "[?] ZeroSSL API key:"
|
||||
read ZEROSSL_API_KEY
|
||||
[[ -n $ZEROSSL_API_KEY ]] && sed -i "s|ZEROSSL_API_KEY=.*|ZEROSSL_API_KEY=\"$ZEROSSL_API_KEY\"|g" $PATH_COMPAT/config.sh
|
||||
|
||||
[[ $IS_PEGAZDEV == "true" ]] && cp $PATH_COMPAT/config.sh $PATH_PEGAZ
|
||||
}
|
||||
|
||||
|
||||
UPGRADE() {
|
||||
echo "[i] All custom configurations in default pegaz services will be overwritten"
|
||||
echo "[?] Are you sure to upgrade pegaz (Y/n)"
|
||||
read ANSWER
|
||||
if [[ $ANSWER == "Y" || $ANSWER == "y" ]]
|
||||
then
|
||||
rm -rf /tmp/pegaz
|
||||
git clone $GITHUB_PEGAZ /tmp/pegaz
|
||||
chmod -R 750 /tmp/pegaz
|
||||
rm $PATH_PEGAZ/env.sh $PATH_PEGAZ/completion.sh $PATH_PEGAZ/cli.pegaz.sh
|
||||
|
||||
mv /tmp/pegaz/env.sh $PATH_PEGAZ
|
||||
mv /tmp/pegaz/completion.sh $PATH_PEGAZ
|
||||
mv /tmp/pegaz/cli.pegaz.sh $PATH_PEGAZ
|
||||
|
||||
rsync -av --exclude "$PATH_PEGAZ_SERVICES/dashboard/web/index.html" --exclude "*config.sh" /tmp/pegaz/services/* $PATH_PEGAZ_SERVICES
|
||||
|
||||
source $PATH_PEGAZ/env.sh
|
||||
echo "[√] pegaz is now upgraded (v$PEGAZ_VERSION)"
|
||||
fi
|
||||
}
|
||||
|
||||
UNINSTALL() {
|
||||
echo "[?] Are you sure to uninstall pegaz (Y/n)"
|
||||
read ANSWER
|
||||
if [[ $ANSWER == "Y" || $ANSWER == "y" ]]
|
||||
then
|
||||
sudo sed -i "\|$PATH_PEGAZ|d" $PATH_BASHRC
|
||||
if [[ -n $SUDO_USER ]]
|
||||
then
|
||||
sudo sed -i "\|$PATH_PEGAZ|d" "/home/$SUDO_USER/.bashrc"
|
||||
elif [[ -f "/home/$USER/.bashrc" ]]
|
||||
then
|
||||
sudo sed -i "\|$PATH_PEGAZ|d" "/home/$USER/.bashrc"
|
||||
fi
|
||||
sudo rm -rf $PATH_PEGAZ/services $PATH_PEGAZ/docs
|
||||
sudo rm $PATH_PEGAZ/* 2> /dev/null # no -rf to delete only file & keep backup & media folder is exist
|
||||
echo "[√] pegaz successfully uninstalled"
|
||||
fi
|
||||
}
|
||||
|
||||
HELP() {
|
||||
echo "Core Commands:
|
||||
usage: pegaz <command>
|
||||
|
||||
help -h Print help
|
||||
version -v Print version
|
||||
upgrade Upgrade pegaz
|
||||
uninstall Uninstall pegaz
|
||||
config Assistant to edit configurations stored in $FILENAME_CONFIG (main configurations or specific configurations if service named is passed)
|
||||
|
||||
Service Commands:
|
||||
usage: pegaz <command> <service>
|
||||
|
||||
up launch or update a web service with configuration set in $FILENAME_CONFIG and proxy settings set in $FILENAME_NGINX then execute $FILENAME_POSTINSTALL
|
||||
create create a service based on service/example (pegaz create <service_name> <dockerhub_image_name>)
|
||||
drop down a service and remove its config folder
|
||||
backup archive volume(s) mounted on the service in $PATH_PEGAZ_BACKUP
|
||||
restore replace volume(s) mounted on the service by backed up archive in $PATH_PEGAZ_BACKUP
|
||||
storj copy backup to a distant bucket with storj (vice-versa if 'pegaz storj restore')
|
||||
reset down a service and prune containers, images and volumes not linked to up & running containers (useful for dev & test)
|
||||
* down restart stop rm logs pull, any docker-compose commands are compatible
|
||||
|
||||
Services:
|
||||
|
||||
$SERVICES"
|
||||
}
|
||||
|
||||
VERSION() {
|
||||
echo $PEGAZ_VERSION
|
||||
}
|
||||
|
||||
PS() {
|
||||
docker ps
|
||||
}
|
||||
|
||||
PORT() {
|
||||
echo "the last port used is $(GET_LAST_PORT)"
|
||||
}
|
||||
|
||||
# SERVICE COMMANDS
|
||||
|
||||
STATE() {
|
||||
local STATE_SERVICE=$(GET_STATE $1)
|
||||
if [[ -n $STATE_SERVICE ]]
|
||||
then
|
||||
printf "%-20s %-20s\n" $1 $STATE_SERVICE
|
||||
fi
|
||||
}
|
||||
|
||||
CREATE() {
|
||||
if test $2
|
||||
then
|
||||
local NAME=$1
|
||||
local IMAGE=$2
|
||||
elif test $1
|
||||
then
|
||||
local NAME=$1
|
||||
local IMAGE=$(docker search $1 --limit 1 --format "{{.Name}}")
|
||||
else
|
||||
while [[ !" ${SERVICES_FLAT} " =~ " $NAME " || ! $NAME ]]
|
||||
do
|
||||
echo "[?] Name"
|
||||
read NAME
|
||||
done
|
||||
local DELIMITER=") "
|
||||
local MAX_RESULT=7
|
||||
local LINE=0
|
||||
local RESULTS=$(docker search $NAME --limit $MAX_RESULT --format "{{.Name}}" | nl -w2 -s "$DELIMITER")
|
||||
while [[ $LINE -lt 1 || $LINE -gt $MAX_RESULT ]]
|
||||
do
|
||||
printf "$RESULTS\n"
|
||||
read LINE
|
||||
done
|
||||
IMAGE=$(sed -n ${LINE}p <<< "$RESULTS" 2> /dev/null)
|
||||
IMAGE=${IMAGE/ $LINE$DELIMITER/}
|
||||
fi
|
||||
|
||||
[[ " ${SERVICES_FLAT} " =~ " $NAME " ]] && echo "[x] service $NAME already exist" && exit 1
|
||||
|
||||
#ports setup
|
||||
local PORT=$(GET_LAST_PORT)
|
||||
PORT=$(($PORT + 5))
|
||||
docker pull $IMAGE
|
||||
[[ $? != 0 ]] && echo "[x] cant pull $IMAGE" && exit 1
|
||||
local PORT_EXPOSED=$(docker inspect --format='{{.Config.ExposedPorts}}' $IMAGE | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//')
|
||||
|
||||
if [[ $PORT_EXPOSED == "" ]]
|
||||
then
|
||||
PORT_EXPOSED="80"
|
||||
fi
|
||||
|
||||
#clean name
|
||||
NAME=${NAME//[^a-zA-Z0-9_]/}
|
||||
NAME=${NAME,,}
|
||||
|
||||
echo $NAME
|
||||
|
||||
#compose setup
|
||||
mkdir -p "$PATH_COMPAT/services/$NAME"
|
||||
cp "$PATH_COMPAT/docs/pegaz.svg" "$PATH_COMPAT/services/$NAME/logo.svg"
|
||||
cp "$PATH_COMPAT/services/example/config.sh" "$PATH_COMPAT/services/example/docker-compose.yml" "$PATH_COMPAT/services/$NAME/"
|
||||
sed -i "s/example/$NAME/" "$PATH_COMPAT/services/$NAME/docker-compose.yml"
|
||||
sed -i "s|image:.*|image: $IMAGE|g" "$PATH_COMPAT/services/$NAME/docker-compose.yml"
|
||||
sed -i "s|DOMAIN=.*|DOMAIN=\"$NAME.$MAIN_DOMAIN\"|g" "$PATH_COMPAT/services/$NAME/config.sh"
|
||||
sed -i "s|PORT=.*|PORT=\"$PORT\"|g" "$PATH_COMPAT/services/$NAME/config.sh"
|
||||
sed -i "s|PORT_EXPOSED=.*|PORT_EXPOSED=\"$PORT_EXPOSED\"|g" "$PATH_COMPAT/services/$NAME/config.sh"
|
||||
sed -i "s|REDIRECTIONS=.*|REDIRECTIONS=\"\"|g" "$PATH_COMPAT/services/$NAME/config.sh"
|
||||
if [[ $IS_PEGAZDEV == "true" ]]
|
||||
then
|
||||
cp -R "$PATH_COMPAT/services/$NAME" $PATH_PEGAZ_SERVICES
|
||||
fi
|
||||
SERVICES=$(find $PATH_PEGAZ_SERVICES -mindepth 1 -maxdepth 1 -not -name '.*' -type d -printf ' %f\n' | sort | sed '/^$/d') # update services list
|
||||
UP $NAME
|
||||
[[ $? != 0 ]] && echo "[x] create fail" && exit 1
|
||||
}
|
||||
|
||||
BACKUP() {
|
||||
[[ -n $(GET_STATE $1) ]] && MANAGE_BACKUP $1 "backup" || echo "$1 is not initialized"
|
||||
}
|
||||
|
||||
RESTORE() {
|
||||
[[ -n $(GET_STATE $1) ]] && MANAGE_BACKUP $1 "restore" || echo "$1 is not initialized"
|
||||
}
|
||||
|
||||
DROP() {
|
||||
echo "[?] Are you sure to drop $1 (Y/n)"
|
||||
read ANSWER
|
||||
if [[ $ANSWER == "Y" || $ANSWER == "y" ]]
|
||||
then
|
||||
EXECUTE "down" $1
|
||||
rm -rf "$PATH_COMPAT/services/$1" "$PATH_PEGAZ_SERVICES/$1"
|
||||
fi
|
||||
}
|
||||
|
||||
UP() {
|
||||
ADD_TO_HOSTS $1
|
||||
PRE_INSTALL $1
|
||||
EXECUTE "pull" $1
|
||||
EXECUTE "build" $1
|
||||
EXECUTE "up -d" $1
|
||||
POST_INSTALL $1
|
||||
SETUP_PROXY
|
||||
UPDATE_DASHBOARD $1
|
||||
SERVICE_INFOS $1
|
||||
}
|
||||
|
||||
START() {
|
||||
[[ -z $(GET_STATE $1) ]] && UP $1 || EXECUTE "start" $1
|
||||
}
|
||||
|
||||
UPDATE() {
|
||||
EXECUTE "build --pull" $1
|
||||
EXECUTE "up -d" $1
|
||||
SETUP_PROXY
|
||||
UPDATE_DASHBOARD $1
|
||||
SERVICE_INFOS $1
|
||||
}
|
||||
|
||||
RESET() {
|
||||
EXECUTE "stop" $1
|
||||
EXECUTE "rm -f" $1
|
||||
}
|
||||
|
||||
LOGS() {
|
||||
[[ -n $(GET_STATE $1) ]] && EXECUTE "logs -f" $1 || echo "$1 is not initialized"
|
||||
}
|
||||
|
||||
# MAIN SCRIPT
|
||||
|
||||
source $PATH_PEGAZ/config.sh
|
||||
|
||||
# DEFAULT command
|
||||
if ! test $1
|
||||
then
|
||||
HELP
|
||||
# ALIAS commands
|
||||
elif [[ $1 = -* ]] || [[ $1 == "ps" ]]
|
||||
then
|
||||
if ! test $2
|
||||
then
|
||||
SET_ALIAS $1
|
||||
elif [[ $1 == "ps" ]]
|
||||
then
|
||||
EXECUTE $1 $2
|
||||
else
|
||||
echo "[x] $1 command doesn't need param, try to run 'pegaz $1'"
|
||||
fi
|
||||
elif [[ " ${COMMANDS[*]} " =~ " $1 " ]]
|
||||
then
|
||||
# CORE commands
|
||||
if [[ " ${COMMANDS_CORE[*]} " =~ " $1 " ]]
|
||||
then
|
||||
if ! test $2
|
||||
then
|
||||
${1^^}
|
||||
elif [[ $1 == "create" || $1 == "storj" ]]
|
||||
then
|
||||
${1^^} $2 $3
|
||||
else
|
||||
echo "[x] $1 command doesn't need param, try to run 'pegaz $1'"
|
||||
fi
|
||||
# SERVICE commands
|
||||
elif [[ " ${COMMANDS_SERVICE[*]} " =~ " $1 " ]]
|
||||
then
|
||||
if test $2
|
||||
then
|
||||
if [[ " ${SERVICES_FLAT[*]} " =~ " $2 " ]]
|
||||
then
|
||||
${1^^} $2
|
||||
elif [[ $1 == "backup" && $2 == "ls" ]]
|
||||
then
|
||||
echo -e "$(ls -lt $PATH_PEGAZ_BACKUP)"
|
||||
else
|
||||
echo "[x] $2 is not on the list, $1 a service listed below :
|
||||
$SERVICES"
|
||||
fi
|
||||
else
|
||||
for SERVICE in $SERVICES
|
||||
do
|
||||
${1^^} $SERVICE
|
||||
done
|
||||
fi
|
||||
# DOCKER-COMPOSE commands
|
||||
else
|
||||
if test $2
|
||||
then
|
||||
EXECUTE $1 $2
|
||||
else
|
||||
for SERVICE in $SERVICES
|
||||
do
|
||||
EXECUTE $1 $SERVICE
|
||||
done
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "[x] No such command: $1"
|
||||
HELP
|
||||
fi
|
||||
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
25
src/App.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<metainfo>
|
||||
<template v-slot:title="{ content }">
|
||||
{{ content ? `${content} | ${siteName}` : siteName }}
|
||||
</template>
|
||||
</metainfo>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useMeta } from 'vue-meta'
|
||||
|
||||
const siteName = 'Pegaz.io'
|
||||
|
||||
useMeta({
|
||||
title: '',
|
||||
htmlAttrs: { lang: 'en', amp: true },
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="postcss">
|
||||
html {
|
||||
@apply bg-slate-100
|
||||
}
|
||||
</style>
|
BIN
src/assets/logo.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
7
src/components/VButton.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<button
|
||||
class="px-4 py-2 ml-2 text-white transition duration-200 bg-blue-500 rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2"
|
||||
>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
@@ -1,61 +1,57 @@
|
||||
<script is:inline>
|
||||
import Nextcloud from '../svg/apps/nextcloud.vue'
|
||||
<script>
|
||||
import { onBeforeUnmount } from 'vue'
|
||||
import Nextcloud from '~/components/svg/apps/nextcloud.vue'
|
||||
|
||||
export default {
|
||||
components: { Nextcloud },
|
||||
data: () => ({
|
||||
terminalContent: '',
|
||||
subDomain: '',
|
||||
isLaunched: false,
|
||||
stories: [
|
||||
{
|
||||
terminal: ['pegaz up nextcloud', '[*] pre-install', 'Creating nextcloud ... done', '[*] post-install', '[√] https://cloud.domain.com'],
|
||||
terminal: ['pegaz up nextcloud', 'Creating nextcloud ... done', '[√] https://cloud.domain.com'],
|
||||
navigator: ['show', 'nextcloud', 'click', 'nextcloud', 'goto', 'cloud'],
|
||||
},
|
||||
{
|
||||
terminal: ['pegaz up jellyfin', '[*] pre-install', 'Creating jellyfin ... done', '[*] post-install', '[√] https://jellyfin.domain.com'],
|
||||
terminal: ['pegaz up jellyfin', 'Creating jellyfin ... done', '[√] https://jellyfin.domain.com'],
|
||||
navigator: ['show', 'jellyfin', 'click', 'jellyfin', 'goto', 'jellyfin'],
|
||||
},
|
||||
{
|
||||
terminal: ['pegaz down nextcloud', 'Stopping test ... done', 'Removing test ... done'],
|
||||
terminal: ['pegaz down nextcloud', 'Stopping nextcloud ... done', 'Removing nextcloud ... done'],
|
||||
navigator: ['goto', 'home', 'hide', 'jellyfin'],
|
||||
},
|
||||
],
|
||||
}),
|
||||
methods: {
|
||||
delay(milliseconds) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, milliseconds)
|
||||
})
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.stories.map(story => {
|
||||
story.terminal.map(async cmd => {
|
||||
this.terminalContent += 'n'
|
||||
await this.delay(1000)
|
||||
this.terminalContent = 'NEW'
|
||||
console.log('each second')
|
||||
}
|
||||
)
|
||||
})
|
||||
},
|
||||
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
|
||||
let i = 0
|
||||
this.timer = await setInterval(() => {
|
||||
this.terminalContent += this.stories[0].terminal[i]+'\n'
|
||||
i += 1
|
||||
if (i == this.stories[0].terminal.length) {
|
||||
clearInterval(this.timer)
|
||||
this.isLaunched = true
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="flex flex-col md:flex-row items-center justify-center mb-28">
|
||||
<div class="bg-slate-900 flex-row rounded-xl w-4/5 md:w-96 h-56 md:z-10 -mb-8 md:-mb-0 max-w-full">
|
||||
<code class="bg-slate-900 flex-row rounded-xl w-4/5 md:w-96 h-56 md:z-10 -mb-8 md:-mb-0 max-w-full md:min-w-max">
|
||||
<div class="p-3 flex justify-between w-20">
|
||||
<div class="bg-green-400 h-4 w-4 r-1 rounded-full"></div>
|
||||
<div class="bg-yellow-300 h-4 w-4 r-1 rounded-full"></div>
|
||||
<div class="bg-red-600 h-4 w-4 r-1 rounded-full"></div>
|
||||
</div>
|
||||
<div class="flex h-4/5">
|
||||
<code class="text-white font-mono p-4 pt-0 mr-0 overflow-scroll">
|
||||
<code class="w-full text-white font-mono p-4 pt-0 mr-0 overflow-scroll whitespace-pre">
|
||||
{{ terminalContent }}<span class="w-2 h-4 bg-white inline-block animate-blink relative" style="margin-bottom: -2px;" ref="terminal" />
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
</code>
|
||||
<div class="bg-slate-400 flex flex-col items-center rounded-2xl w-full md:w-2/4 md:min-w-fit h-80 md:-ml-8 md:z-0">
|
||||
<div class="bg-white inline-block rounded-2xl px-4 py-1 m-4 w-4/6">
|
||||
<span class="text-gray-400">
|
||||
@@ -66,7 +62,7 @@
|
||||
</span>domain.com
|
||||
</div>
|
||||
<div class="bg-white w-full h-full flex justify-center items-center group">
|
||||
<Nextcloud class="w-20 bg-black bg-opacity-10 inline-block rounded-xl p-4 cursor-pointer scale-0 group-hover:scale-100 transition-transform" />
|
||||
<Nextcloud class="w-20 bg-black bg-opacity-10 inline-block rounded-xl p-4 cursor-pointer scale-0 transition-transform" :class="isLaunched ? 'scale-100' : ''" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import ClipBoard from '../svg/clipboard.vue'
|
||||
import ClipBoard from '~/components/svg/clipboard.vue'
|
||||
export default {
|
||||
components: { ClipBoard },
|
||||
data: () => {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import Logo from '../svg/logo.vue'
|
||||
import Logo from '~/components/svg/logo.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
Before Width: | Height: | Size: 890 B After Width: | Height: | Size: 890 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 659 B |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 769 B |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
1
src/env.d.ts
vendored
@@ -1 +0,0 @@
|
||||
/// <reference types="astro/client" />
|
3
src/index.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
19
src/layouts/404.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<main class="max-w-5xl p-5 mx-auto my-10 text-center">
|
||||
<router-view />
|
||||
<div>
|
||||
<v-button @click="router.back()"> Go Back </v-button>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useMeta } from 'vue-meta'
|
||||
|
||||
useMeta({
|
||||
title: '404 - Not found!',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
3
src/layouts/default.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
20
src/main.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createMetaManager } from 'vue-meta'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { createPinia } from 'pinia'
|
||||
import { setupLayouts } from 'virtual:generated-layouts'
|
||||
import generatedRoutes from 'virtual:generated-pages'
|
||||
import App from './App.vue'
|
||||
import './index.css'
|
||||
|
||||
const routes = setupLayouts(generatedRoutes)
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
const app = createApp(App).use(router).use(createPinia()).use(createMetaManager())
|
||||
|
||||
await router.isReady()
|
||||
app.mount('#app')
|
8
src/pages/[...all].vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div class="py-4 text-2xl text-center">Page Not found!</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: 404
|
||||
</route>
|
26
src/pages/about/[name].vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold">About {{ usersStore.name }}</h1>
|
||||
|
||||
<p class="my-8">
|
||||
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque
|
||||
voluptatem consequuntur molestiae cumque recusandae eos non,
|
||||
consectetur, repellat architecto illo nobis, voluptatum dolor!
|
||||
Reprehenderit, nam veniam quibusdam ab nulla rem.
|
||||
</p>
|
||||
<router-link to="/">
|
||||
<v-button>Back to home</v-button>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useMeta } from 'vue-meta'
|
||||
import { useUsersStore } from '~/stores/useUsersStore'
|
||||
|
||||
useMeta({
|
||||
title: 'About Page',
|
||||
})
|
||||
|
||||
const usersStore = useUsersStore()
|
||||
</script>
|
@@ -1,28 +0,0 @@
|
||||
---
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import Github from "../svg/github.vue";
|
||||
import HeroTitle from "../components/hero-title.vue";
|
||||
import HeroButtons from "../components/hero-buttons.vue";
|
||||
import Demo from "../components/demo.vue";
|
||||
---
|
||||
|
||||
<Layout title="Welcome to Pegaz.io.">
|
||||
<div class="mx-6">
|
||||
<header class="h-screen flex flex-col justify-center">
|
||||
<nav class="fixed right-0 top-0 p-2">
|
||||
<a
|
||||
title="Go to Pegaz GitHub repo"
|
||||
href="https://github.com/valerebron/pegaz"
|
||||
target="_blank"
|
||||
>
|
||||
<Github class="bg-white rounded-full hover:scale-105" />
|
||||
</a>
|
||||
</nav>
|
||||
<HeroTitle client:visible />
|
||||
<HeroButtons client:visible />
|
||||
</header>
|
||||
<main class="-mt-20">
|
||||
<Demo />
|
||||
</main>
|
||||
</div>
|
||||
</Layout>
|
52
src/pages/index.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="mx-6">
|
||||
<header class="h-screen flex flex-col justify-center">
|
||||
<nav class="fixed right-0 top-0 p-2">
|
||||
<a
|
||||
title="Go to Pegaz GitHub repo"
|
||||
href="https://github.com/valerebron/pegaz"
|
||||
target="_blank"
|
||||
>
|
||||
<Github class="bg-white rounded-full hover:scale-105" />
|
||||
</a>
|
||||
</nav>
|
||||
<HeroTitle client:visible />
|
||||
<HeroButtons client:visible />
|
||||
</header>
|
||||
<main class="-mt-20">
|
||||
<Demo />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useMeta } from 'vue-meta'
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUsersStore } from '~/stores/useUsersStore'
|
||||
|
||||
import Github from "~/components/svg/github.vue";
|
||||
import HeroTitle from "~/components/hero-title.vue";
|
||||
import HeroButtons from "~/components/hero-buttons.vue";
|
||||
import Demo from "~/components/demo.vue";
|
||||
|
||||
useMeta({
|
||||
title: 'Deploy stack',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const usersStore = useUsersStore()
|
||||
|
||||
const newName = ref('')
|
||||
|
||||
function saveName() {
|
||||
if (newName.value === '') {
|
||||
return
|
||||
}
|
||||
|
||||
usersStore.saveName(newName.value)
|
||||
router.push(`/about/${newName.value}`)
|
||||
newName.value = ''
|
||||
}
|
||||
</script>
|
24
src/stores/useUsersStore.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||
|
||||
export const useUsersStore = defineStore('users', {
|
||||
state: () => {
|
||||
return {
|
||||
name: 'John Doe'
|
||||
}
|
||||
},
|
||||
|
||||
getters: {
|
||||
nameUppercased: (state) => state.name.toUpperCase()
|
||||
},
|
||||
|
||||
actions: {
|
||||
saveName(name) {
|
||||
this.name = name
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useUsersStore, import.meta.hot))
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {
|
||||
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {
|
||||
keyframes: {
|
||||
blink: {
|
||||
'0%': { opacity: '0' },
|
||||
@@ -26,7 +26,10 @@ module.exports = {
|
||||
slide: 'slide .3s',
|
||||
fadeout: 'fadeout .8s',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve"
|
||||
}
|
||||
}
|
19
vite.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import path from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import Pages from 'vite-plugin-pages'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import Layouts from 'vite-plugin-vue-layouts'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'~/': `${path.resolve(__dirname, 'src')}/`,
|
||||
},
|
||||
},
|
||||
plugins: [vue(), Pages(), Layouts(), Components()],
|
||||
build: {
|
||||
target: 'esnext'
|
||||
}
|
||||
})
|