Merge branch 'vue-3'
This commit is contained in:
commit
acb115bb0c
25 changed files with 3039 additions and 3 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
dist/
|
||||
7
.editorconfig
Normal file
7
.editorconfig
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = false
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
15
.eslintrc.yml
Normal file
15
.eslintrc.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
vue/setup-compiler-macros: true
|
||||
extends:
|
||||
- 'plugin:vue/vue3-recommended'
|
||||
- standard
|
||||
parserOptions:
|
||||
ecmaVersion: 13
|
||||
parser: '@typescript-eslint/parser'
|
||||
sourceType: module
|
||||
plugins:
|
||||
- vue
|
||||
- '@typescript-eslint'
|
||||
rules: {}
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
25
Dockerfile
25
Dockerfile
|
|
@ -1,3 +1,26 @@
|
|||
# ======Building the project=====
|
||||
FROM node:17.2.0 AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install Node dependencies
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install
|
||||
|
||||
# Copy over source code & build project
|
||||
COPY vite.config.ts tsconfig.json index.html ./
|
||||
COPY src/ ./src
|
||||
COPY public/ ./public
|
||||
RUN yarn run build
|
||||
|
||||
|
||||
# =====Packaging inside an Nginx container=====
|
||||
FROM nginx:1.21.4-alpine
|
||||
|
||||
COPY default.conf.template /etc/nginx/templates/default.conf.template
|
||||
# Copy over the Nginx config files
|
||||
COPY nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY nginx/*.conf.template /etc/nginx/templates/
|
||||
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Copy over build artifacts
|
||||
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -1,3 +1,11 @@
|
|||
# web
|
||||
# Vue 3 + Typescript + Vite
|
||||
|
||||
Frontend microservice for the Rusty Bever blogging software.
|
||||
This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
|
||||
|
||||
## 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 enable Volar's `.vue` type support plugin by running `Volar: Switch TS Plugin on/off` from VSCode command palette.
|
||||
|
|
|
|||
13
index.html
Normal file
13
index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
20
nginx/default.conf
Normal file
20
nginx/default.conf
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# vim: ft=nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
|
||||
# =====FRONTEND HOSTING=====
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
13
nginx/gateway.conf.template
Normal file
13
nginx/gateway.conf.template
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# vim: ft=nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
location /api/v1/posts/ {
|
||||
proxy_pass http://${RB_BLOG}/v1/posts/;
|
||||
}
|
||||
|
||||
location /api/v1/sections/ {
|
||||
proxy_pass http://${RB_BLOG}/v1/sections/;
|
||||
}
|
||||
}
|
||||
55
nginx/matrix.conf.template
Normal file
55
nginx/matrix.conf.template
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# vim: ft=nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
|
||||
# =====MATRIX WELL-KNOWN FILES=====
|
||||
# Used for server federation
|
||||
location = /.well-known/matrix/server {
|
||||
charset utf-8;
|
||||
default_type application/json;
|
||||
|
||||
if ($request_method = 'GET') {
|
||||
add_header Access-Control-Allow-Origin '*';
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type, Authorization';
|
||||
|
||||
return 200 '{"m.server":"${MATRIX_SERVER}"}';
|
||||
}
|
||||
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header Access-Control-Allow-Origin '*';
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type, Authorization';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
return 405;
|
||||
}
|
||||
|
||||
location = /.well-known/matrix/client {
|
||||
charset utf-8;
|
||||
default_type application/json;
|
||||
|
||||
if ($request_method = 'GET') {
|
||||
add_header Access-Control-Allow-Origin '*';
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type, Authorization';
|
||||
|
||||
return 200 '{"m.homeserver":{"base_url":"${MATRIX_CLIENT_SERVER}"}}';
|
||||
}
|
||||
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header Access-Control-Allow-Origin '*';
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type, Authorization';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
return 405;
|
||||
}
|
||||
|
||||
}
|
||||
33
nginx/nginx.conf
Normal file
33
nginx/nginx.conf
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
gzip on;
|
||||
|
||||
# This order is important, as the Matrix matches should be evaluated first
|
||||
include /etc/nginx/conf.d/matrix.conf;
|
||||
include /etc/nginx/conf.d/gateway.conf;
|
||||
include /etc/nginx/conf.d/default.conf;
|
||||
}
|
||||
31
package.json
Normal file
31
package.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "rb-web",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview",
|
||||
"image": "docker build -t chewingbever/rb-blog .",
|
||||
"lint": "eslint --ext .js,.vue,.ts src",
|
||||
"format": "yarn run lint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.2.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.8.1",
|
||||
"@typescript-eslint/parser": "^5.8.1",
|
||||
"@vitejs/plugin-vue": "^2.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.2.0",
|
||||
"eslint-plugin-vue": "^8.2.0",
|
||||
"miragejs": "^0.1.43",
|
||||
"null-loader": "^4.0.1",
|
||||
"typescript": "^4.4.4",
|
||||
"vite": "^2.7.2",
|
||||
"vue-tsc": "^0.29.8"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
26
src/App.vue
Normal file
26
src/App.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
// This starter template is using Vue 3 <script setup> SFCs
|
||||
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<img
|
||||
alt="Vue logo"
|
||||
src="./assets/logo.png"
|
||||
>
|
||||
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
</style>
|
||||
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
71
src/components/HelloWorld.vue
Normal file
71
src/components/HelloWorld.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps<{ msg: string }>()
|
||||
|
||||
const count = ref(0)
|
||||
|
||||
fetch('/api/v1/sections').then(res => res.json()).then(res => console.log(res))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<p>
|
||||
Recommended IDE setup:
|
||||
<a
|
||||
href="https://code.visualstudio.com/"
|
||||
target="_blank"
|
||||
>VSCode</a>
|
||||
+
|
||||
<a
|
||||
href="https://github.com/johnsoncodehk/volar"
|
||||
target="_blank"
|
||||
>Volar</a>
|
||||
</p>
|
||||
|
||||
<p>See <code>README.md</code> for more information.</p>
|
||||
|
||||
<p>
|
||||
<a
|
||||
href="https://vitejs.dev/guide/features.html"
|
||||
target="_blank"
|
||||
>
|
||||
Vite Docs
|
||||
</a>
|
||||
|
|
||||
<a
|
||||
href="https://v3.vuejs.org/"
|
||||
target="_blank"
|
||||
>Vue 3 Docs</a>
|
||||
</p>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@click="count++"
|
||||
>
|
||||
count is: {{ count }}
|
||||
</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test hot module replacement.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
label {
|
||||
margin: 0 0.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #eee;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
color: #304455;
|
||||
}
|
||||
</style>
|
||||
8
src/env.d.ts
vendored
Normal file
8
src/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
10
src/main.ts
Normal file
10
src/main.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
// @ts-ignore
|
||||
import { makeServer } from './mirage/v1'
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
makeServer()
|
||||
}
|
||||
|
||||
createApp(App).mount('#app')
|
||||
52
src/mirage/models.js
Normal file
52
src/mirage/models.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
export const sections = [
|
||||
{
|
||||
id: '837ba6a5-47ed-4682-bff5-90bc5c5f9646',
|
||||
title: 'Section One',
|
||||
shortname: 'one',
|
||||
description: 'The first section.',
|
||||
is_default: true,
|
||||
has_titles: true,
|
||||
is_private: false,
|
||||
is_archived: false
|
||||
},
|
||||
{
|
||||
id: '5e661b3f-61e6-4aed-a93b-8cae0896f656',
|
||||
title: 'Section Two',
|
||||
shortname: 'two',
|
||||
description: 'The second section.',
|
||||
is_default: true,
|
||||
has_titles: false,
|
||||
is_private: false,
|
||||
is_archived: false
|
||||
},
|
||||
{
|
||||
id: '5fcbeaca-1496-438e-ace2-18e99e11f384',
|
||||
title: 'Section Three',
|
||||
shortname: 'three',
|
||||
description: 'The third section.',
|
||||
is_default: false,
|
||||
has_titles: true,
|
||||
is_private: false,
|
||||
is_archived: false
|
||||
}
|
||||
];
|
||||
|
||||
export const posts = [
|
||||
{
|
||||
id: 'af08bbcd-f6eb-446e-b355-13e0a0ef008e',
|
||||
section_id: sections[0]['id'],
|
||||
is_private: false,
|
||||
is_archived: false
|
||||
}
|
||||
];
|
||||
|
||||
export const versions = [
|
||||
{
|
||||
id: '8c5bc2f9-e52f-4e19-bd76-119cc42ff863',
|
||||
post_id: posts[0]['id'],
|
||||
title: 'This Is A Title',
|
||||
publish_date: '2021-12-28',
|
||||
content: 'Hello. This is some content!',
|
||||
is_draft: false
|
||||
}
|
||||
]
|
||||
37
src/mirage/v1.js
Normal file
37
src/mirage/v1.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { createServer, Model } from 'miragejs';
|
||||
import { sections, posts, versions } from './models';
|
||||
|
||||
export function makeServer ({ environment = 'development' } = {}) {
|
||||
const server = createServer({
|
||||
environment,
|
||||
|
||||
models: {
|
||||
section: Model,
|
||||
Post: Model,
|
||||
version: Model
|
||||
},
|
||||
|
||||
seeds (server) {
|
||||
sections.forEach(s => server.create('section', s));
|
||||
posts.forEach(s => server.create('post', s));
|
||||
versions.forEach(s => server.create('version', s));
|
||||
|
||||
},
|
||||
|
||||
routes () {
|
||||
this.namespace = 'api/v1';
|
||||
|
||||
this.get('/sections', (schema) => {
|
||||
return schema.sections.all();
|
||||
})
|
||||
this.get('/posts', (schema) => {
|
||||
return schema.posts.all();
|
||||
})
|
||||
this.get('/versions', (schema) => {
|
||||
return schema.versions.all();
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
27
src/server.js
Normal file
27
src/server.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// src/server.js
|
||||
import { createServer, Model } from 'miragejs'
|
||||
|
||||
export function makeServer ({ environment = 'development' } = {}) {
|
||||
const server = createServer({
|
||||
environment,
|
||||
|
||||
models: {
|
||||
user: Model
|
||||
},
|
||||
|
||||
seeds (server) {
|
||||
server.create('user', { name: 'Bob' })
|
||||
server.create('user', { name: 'Alice' })
|
||||
},
|
||||
|
||||
routes () {
|
||||
this.namespace = 'api'
|
||||
|
||||
this.get('/users', (schema) => {
|
||||
return schema.users.all()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return server
|
||||
}
|
||||
15
tsconfig.json
Normal file
15
tsconfig.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext", "dom"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
||||
7
vite.config.ts
Normal file
7
vite.config.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()]
|
||||
})
|
||||
14
vue.config.js
Normal file
14
vue.config.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = {
|
||||
chainWebpack: (config) => {
|
||||
if (
|
||||
process.env.NODE_ENV === "production" &&
|
||||
process.env.MIRAGE_ENABLED !== "true"
|
||||
) {
|
||||
config.module
|
||||
.rule("exclude-mirage")
|
||||
.test(/node_modules\/miragejs\//)
|
||||
.use("null-loader")
|
||||
.loader("null-loader")
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in a new issue