Compare commits
No commits in common. "f3f36938df4095c4885fbddac51c632f23b2e181" and "8ec3e6ff5520750ee5261abc9ff585bebb2cdfad" have entirely different histories.
f3f36938df
...
8ec3e6ff55
|
@ -1,6 +0,0 @@
|
|||
.git
|
||||
.editorconfig
|
||||
docker-minecraft.png
|
||||
LICENSE
|
||||
Makefile
|
||||
README.md
|
|
@ -1,16 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_size = 4
|
||||
indent_style = tab
|
|
@ -1,3 +0,0 @@
|
|||
github: PHLAK
|
||||
patreon: PHLAK
|
||||
custom: https://paypal.me/ChrisKankiewicz
|
|
@ -1,8 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: docker
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
timezone: US/Arizona
|
||||
open-pull-requests-limit: 10
|
|
@ -1,40 +0,0 @@
|
|||
name: Publish Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['master']
|
||||
tags: ['*']
|
||||
|
||||
env:
|
||||
DOCKER_HUB_USER: phlak
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
name: Build & Push
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ env.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
- name: Extract Metadata
|
||||
id: extract-metadata
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: ${{ env.DOCKER_HUB_USER }}/minecraft
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build & Push Image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.extract-metadata.outputs.tags }}
|
||||
labels: ${{ steps.extract-metadata.outputs.labels }}
|
|
@ -1,15 +0,0 @@
|
|||
name: Tests
|
||||
|
||||
on: [pull_request_target]
|
||||
|
||||
jobs:
|
||||
build-image:
|
||||
name: Build Image
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build Image
|
||||
run: make build
|
|
@ -1,3 +1 @@
|
|||
data/
|
||||
db/
|
||||
files/server.jar
|
||||
node_modules/
|
49
Dockerfile
49
Dockerfile
|
@ -1,49 +0,0 @@
|
|||
FROM alpine:3.16.0
|
||||
LABEL maintainer='Andriy Cherniy <qugalet@m0e.space>'
|
||||
|
||||
# Minecraft version
|
||||
ARG MC_VERSION=bta
|
||||
ARG MC_JAR_SHA1=8399e1211e95faa421c1507b322dbeae86d604df
|
||||
|
||||
# Set default JVM options
|
||||
ENV _JAVA_OPTIONS '-Xms256M -Xmx4G'
|
||||
ARG JAVA_VERSION=19
|
||||
|
||||
# Create Minecraft directories
|
||||
RUN mkdir -pv /opt/minecraft /etc/minecraft
|
||||
|
||||
# Create non-root user
|
||||
RUN adduser -DHs /sbin/nologin minecraft
|
||||
|
||||
# Add the EULA file
|
||||
COPY files/eula.txt /etc/minecraft/eula.txt
|
||||
|
||||
# Add the ops script
|
||||
COPY files/ops /usr/local/bin/ops
|
||||
RUN chmod +x /usr/local/bin/ops
|
||||
|
||||
# Install dependencies, fetch Minecraft server jar file and chown files
|
||||
#ARG JAR_URL=https://launcher.mojang.com/v1/objects/${MC_JAR_SHA1}/server.jar
|
||||
RUN apk add --update ca-certificates nss tzdata wget \
|
||||
&& apk add openjdk19-jre \
|
||||
#&& wget -O /opt/minecraft/minecraft_server.jar ${JAR_URL} \
|
||||
#&& apk del --purge wget && rm -rf /var/cache/apk/* \
|
||||
&& rm -rf /var/cache/apk/* \
|
||||
&& chown -R minecraft:minecraft /etc/minecraft /opt/minecraft
|
||||
|
||||
COPY files/server.jar /opt/minecraft/minecraft_server.jar
|
||||
|
||||
# Define volumes
|
||||
VOLUME /etc/minecraft
|
||||
|
||||
# Expose port
|
||||
EXPOSE 25565
|
||||
|
||||
# Set running user
|
||||
USER minecraft
|
||||
|
||||
# Set the working dir
|
||||
WORKDIR /etc/minecraft
|
||||
|
||||
# Default run command
|
||||
CMD ["java", "-jar", "/opt/minecraft/minecraft_server.jar", "nogui"]
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Chris Kankiewicz <Chris@ChrisKankiewicz.com>
|
||||
|
||||
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.
|
8
Makefile
8
Makefile
|
@ -1,8 +0,0 @@
|
|||
IMAGE_NAME="phlak/minecraft"
|
||||
IMAGE_TAG="$$(grep 'ARG MC_VERSION' Dockerfile | awk -F = '{print $$2}')"
|
||||
|
||||
build:
|
||||
@docker build --force-rm --pull --tag $(IMAGE_NAME):$(IMAGE_TAG) .
|
||||
|
||||
purge:
|
||||
@docker image rm --force $(IMAGE_NAME):$(IMAGE_TAG)
|
123
README.md.old
123
README.md.old
|
@ -1,123 +0,0 @@
|
|||
docker-minecraft
|
||||
================
|
||||
|
||||
<p align="center">
|
||||
<img src="docker-minecraft.png" alt="Docker Minecraft" width="500">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/PHLAK/docker-minecraft/discussions"><img src="https://img.shields.io/badge/Join_the-Community-7b16ff.svg?style=for-the-badge" alt="Join the Community"></a>
|
||||
<a href="https://github.com/users/PHLAK/sponsorship"><img src="https://img.shields.io/badge/Become_a-Sponsor-cc4195.svg?style=for-the-badge" alt="Become a Sponsor"></a>
|
||||
<a href="https://paypal.me/ChrisKankiewicz"><img src="https://img.shields.io/badge/Make_a-Donation-006bb6.svg?style=for-the-badge" alt="One-time Donation"></a>
|
||||
<br>
|
||||
<a href="https://hub.docker.com/repository/docker/phlak/minecraft/tags"><img alt="Docker Image Version" src="https://img.shields.io/docker/v/phlak/minecraft?style=flat-square&sort=semver"></a>
|
||||
<a href="https://hub.docker.com/repository/docker/phlak/minecraft"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/phlak/minecraft?style=flat-square"></a>
|
||||
<a href="https://github.com/PHLAK/docker-minecraft/blob/master/LICENSE"><img src="https://img.shields.io/github/license/PHLAK/docker-minecraft?style=flat-square" alt="License"></a>
|
||||
<a href="https://hub.docker.com/r/phlak/minecraft/builds"><img alt="Docker Cloud Build Status" src="https://img.shields.io/docker/cloud/build/phlak/minecraft"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Docker image for <a href="https://minecraft.net/">Minecraft</a> server.
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Running the Container
|
||||
---------------------
|
||||
|
||||
First create a named data volume to hold the persistent world and config data:
|
||||
|
||||
docker volume create --name minecraft-data
|
||||
|
||||
Then run the Minecraft server:
|
||||
|
||||
docker run -it -d -p 25565:25565 -v minecraft-data:/etc/minecraft --name minecraft-server phlak/minecraft
|
||||
|
||||
#### Optional 'docker run' Arguments
|
||||
|
||||
<dl>
|
||||
<dt><code>-e _JAVA_OPTIONS='-Xms256M -Xmx2048M'</code></dt>
|
||||
<dd>Set JVM arguments for minimum/maximum memory consumption (default: '-Xms256M -Xmx2048M')</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt><code>-e TZ=America/Phoenix</code></dt>
|
||||
<dd>Set the timezone for your server. You can find your timezone in this <a href="https://goo.gl/uy1J6q">list of timezones</a>. Use the (case sensitive) value from the <code>TZ</code> column. If left unset, timezone will be UTC.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt><code>--restart unless-stopped</code></dt>
|
||||
<dd>Always restart the container regardless of the exit status, but do not start it on daemon startup if the container has been put to a stopped state before. See the Docker <a href="https://goo.gl/Y0dlDH">restart policies</a> for additional details.</dd>
|
||||
</dl>
|
||||
|
||||
**NOTE:** See the [Minecraft Wiki](http://minecraft.gamepedia.com/Server/Requirements) for more info
|
||||
on memory requirements.
|
||||
|
||||
Editing the Server Config
|
||||
-------------------------
|
||||
|
||||
Once you have a running container, you can edit the Minecraft [server config](https://minecraft.gamepedia.com/Server.properties) with:
|
||||
|
||||
docker exec -it minecraft-server vi /etc/minecraft/server.properties
|
||||
|
||||
After saving changes, restart your container with `docker restart minecraft-server`
|
||||
|
||||
Adding OPs
|
||||
----------
|
||||
|
||||
Once you have a running server container you can add OPs by running:
|
||||
|
||||
docker exec minecraft-server ops [PLAYER_NAMES]
|
||||
|
||||
**NOTE:** Replace `[PLAYER_NAMES]` with the name of one or more players you wish to give OP
|
||||
privileges separated by a space. If a players name contains spaces wrap it in quotation marks.
|
||||
|
||||
Here's an example granting OP to three players with name's `Marty`, `Jennifer` and `Doc Brown`:
|
||||
|
||||
docker exec minecraft-server ops Marty Jennifer "Doc Brown"
|
||||
|
||||
Running Server Commands
|
||||
-----------------------
|
||||
|
||||
You can run [commands](https://minecraft.gamepedia.com/Commands) on the server
|
||||
(e.g. `kick`, `ban`, `say`, etc.) by attaching to the running container and
|
||||
running the commands. Attach to the server by running:
|
||||
|
||||
docker attach minecraft-server
|
||||
|
||||
Once attached you can run your commands like normal.
|
||||
|
||||
say Hello world!
|
||||
[10:11:56] [Server thread/INFO]: [Server] Hello world!
|
||||
list
|
||||
[10:12:08] [Server thread/INFO]: There are 3 of a max 10 players online: Marty, Jennifer, Doc Brown
|
||||
seed
|
||||
[10:12:19] [Server thread/INFO]: Seed: [-5234790158571010769]
|
||||
|
||||
**NOTE:** In order to detach from the container and leave it running use the
|
||||
`Ctrl + P` then `Ctrl + Q` key sequence.
|
||||
|
||||
Upgrading the Server
|
||||
--------------------
|
||||
|
||||
First pull down the latest image:
|
||||
|
||||
docker pull phlak/minecraft
|
||||
|
||||
Remove your running server container:
|
||||
|
||||
docker rm -f minecraft-server
|
||||
|
||||
And run a new one with the same command/arguments as before.
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
For general help and support join our [GitHub Discussions](https://github.com/PHLAK/docker-minecraft/discussions) or reach out on [Twitter](https://twitter.com/PHLAK).
|
||||
|
||||
Please report bugs to the [GitHub Issue Tracker](https://github.com/PHLAK/docker-minecraft/issues).
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
This project is licensed under the [MIT License](https://github.com/PHLAK/docker-minecraft/blob/master/LICENSE).
|
12
README.org
12
README.org
|
@ -1,12 +0,0 @@
|
|||
* Minecraft Docker
|
||||
Dockerfile and docker-compose for your own server jar
|
||||
|
||||
** Usage
|
||||
Change your JAVA_VERSION in [[./Dockerfile][Dockerfile]] and build:
|
||||
#+BEGIN_SRC shell
|
||||
docker compose build
|
||||
#+END_SRC
|
||||
Place server.jar to ~files/~ folder, change your [[./docker-compose.yml][Docker Compose]] file and run:
|
||||
#+BEGIN_SRC shell
|
||||
docker compose up -d
|
||||
#+END_SRC
|
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
|
@ -0,0 +1,25 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'prettier'],
|
||||
rules: {
|
||||
yoda: 'error',
|
||||
eqeqeq: 'error',
|
||||
complexity: 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-template': 'error',
|
||||
'object-shorthand': 'warn',
|
||||
'prettier/prettier': 'warn',
|
||||
'prefer-destructuring': 'warn',
|
||||
'prefer-arrow-callback': 'error',
|
||||
'@typescript-eslint/no-namespace': 'off'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
dist/
|
||||
.env
|
||||
README.md
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": true,
|
||||
"semi": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./package.json ./
|
||||
|
||||
RUN npm i
|
||||
|
||||
COPY ./.env ./
|
||||
|
||||
COPY ./prisma/schema.prisma ./
|
||||
|
||||
RUN npm run migrate
|
||||
|
||||
RUN npm run generate
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["node", "dist"]
|
|
@ -0,0 +1,9 @@
|
|||
version: '2'
|
||||
services:
|
||||
backend:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '9030:8080'
|
||||
env_file:
|
||||
- ./.env
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "rpz_auth",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"generate": "prisma generate",
|
||||
"migrate": "prisma migrate deploy",
|
||||
"build": "rm -rf dist/** && tsc",
|
||||
"dev": "tsc -w",
|
||||
"start": "node ./dist"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node18": "^1.0.1",
|
||||
"@types/jsonwebtoken": "^8.5.9",
|
||||
"@types/minio": "^7.0.15",
|
||||
"@types/node": "^18.11.17",
|
||||
"@types/passport-local": "^1.0.34",
|
||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
||||
"@typescript-eslint/parser": "^5.47.0",
|
||||
"eslint": "^8.30.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"prettier": "^2.8.1",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.236.0",
|
||||
"@fastify/autoload": "^5.6.0",
|
||||
"@fastify/cookie": "^8.3.0",
|
||||
"@fastify/passport": "^2.2.0",
|
||||
"@fastify/secure-session": "^5.3.0",
|
||||
"@prisma/client": "^4.8.0",
|
||||
"axios": "^0.27.2",
|
||||
"discord-api-types": "^0.37.24",
|
||||
"fastify": "^4.10.2",
|
||||
"json-schema-to-ts": "^2.6.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"minio": "^7.0.32",
|
||||
"nanoid": "^3.3.4",
|
||||
"passport-local": "^1.0.0",
|
||||
"prisma": "^4.8.0",
|
||||
"redis": "^4.5.1",
|
||||
"simple-oauth2": "^4.3.0"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nickname" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Session" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userNickname" TEXT NOT NULL,
|
||||
"ip" TEXT NOT NULL,
|
||||
"expiredAfter" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_nickname_key" ON "User"("nickname");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Session" ADD CONSTRAINT "Session_userNickname_fkey" FOREIGN KEY ("userNickname") REFERENCES "User"("nickname") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,5 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Session" ADD COLUMN "verified" BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ALTER COLUMN "nickname" DROP NOT NULL;
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `userNickname` on the `Session` table. All the data in the column will be lost.
|
||||
- Added the required column `nickname` to the `Session` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Session" DROP CONSTRAINT "Session_userNickname_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Session" DROP COLUMN "userNickname",
|
||||
ADD COLUMN "nickname" TEXT NOT NULL;
|
|
@ -0,0 +1,14 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Link" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"link" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Link_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Link_sessionId_key" ON "Link"("sessionId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Link" ADD CONSTRAINT "Link_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "Session"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "hasPass" BOOLEAN NOT NULL DEFAULT false;
|
|
@ -0,0 +1,28 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Season" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"starts" TIMESTAMP(3),
|
||||
"ends" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "Season_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Account" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"creationDate" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isBanned" BOOLEAN NOT NULL DEFAULT false,
|
||||
"bannedDate" TIMESTAMP(3),
|
||||
"bannedReason" TEXT,
|
||||
"seasonId" TEXT,
|
||||
|
||||
CONSTRAINT "Account_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Account" ADD CONSTRAINT "Account_seasonId_fkey" FOREIGN KEY ("seasonId") REFERENCES "Season"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `hasPass` on the `User` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Season" ADD COLUMN "current" BOOLEAN NOT NULL DEFAULT true;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" DROP COLUMN "hasPass";
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[discordId]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "discordId" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_discordId_key" ON "User"("discordId");
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "tokenVersion" INTEGER NOT NULL DEFAULT 0;
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `form` to the `User` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "form" JSONB NOT NULL;
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `form` on the `User` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" DROP COLUMN "form";
|
|
@ -0,0 +1,22 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Account" ADD COLUMN "guildId" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Guild" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"discordRole" TEXT NOT NULL,
|
||||
"leaderId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Guild_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Guild_leaderId_key" ON "Guild"("leaderId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Account" ADD CONSTRAINT "Account_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Guild" ADD CONSTRAINT "Guild_leaderId_fkey" FOREIGN KEY ("leaderId") REFERENCES "Account"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `Link` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `Session` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Link" DROP CONSTRAINT "Link_sessionId_fkey";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Link";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Session";
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "password" TEXT;
|
|
@ -0,0 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
|
@ -0,0 +1,67 @@
|
|||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Season {
|
||||
id String @id
|
||||
name String
|
||||
starts DateTime?
|
||||
ends DateTime?
|
||||
accounts Account[]
|
||||
current Boolean @default(true)
|
||||
}
|
||||
|
||||
model Account {
|
||||
id String @id @default(uuid())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
creationDate DateTime @default(now())
|
||||
isBanned Boolean @default(false)
|
||||
bannedDate DateTime?
|
||||
bannedReason String?
|
||||
season Season? @relation(fields: [seasonId], references: [id])
|
||||
seasonId String?
|
||||
guild Guild? @relation(fields: [guildId], references: [id])
|
||||
guildId String?
|
||||
leaderOf Guild? @relation(name: "guildLeader")
|
||||
}
|
||||
|
||||
model Guild {
|
||||
id String @id
|
||||
name String
|
||||
description String
|
||||
discordRole String
|
||||
leader Account @relation(name: "guildLeader", fields: [leaderId], references: [id])
|
||||
leaderId String @unique
|
||||
members Account[]
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
nickname String? @unique
|
||||
discordId String? @unique
|
||||
accounts Account[]
|
||||
tokenVersion Int @default(0)
|
||||
password String?
|
||||
}
|
||||
|
||||
// model Session {
|
||||
// id String @id @default(uuid())
|
||||
// nickname String
|
||||
// ip String
|
||||
// verified Boolean @default(false)
|
||||
// expiredAfter DateTime
|
||||
// link Link?
|
||||
// }
|
||||
|
||||
// model Link {
|
||||
// id String @id
|
||||
// session Session @relation(fields: [sessionId], references: [id])
|
||||
// sessionId String @unique
|
||||
// link String
|
||||
// }
|
|
@ -0,0 +1,108 @@
|
|||
import fastify from 'fastify';
|
||||
import fastifyAutoload from '@fastify/autoload';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
// import { Client as MinioClient } from 'minio';
|
||||
import { S3Client } from '@aws-sdk/client-s3';
|
||||
import fastifyCookie from '@fastify/cookie';
|
||||
// import { readFile } from 'fs/promises';
|
||||
// import { createClient, RedisClientType } from 'redis';
|
||||
// import fastifySchedule from '@fastify/schedule';
|
||||
// import fastifyCors from '@fastify/cors';
|
||||
|
||||
import path from 'path';
|
||||
import { env } from 'process';
|
||||
// import { FromSchema } from 'json-schema-to-ts';
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
db: PrismaClient;
|
||||
storage: S3Client;
|
||||
// redis: RedisClientType;
|
||||
}
|
||||
interface FastifyReply {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
sendError: (error: any, code?: number, explanation?: string) => void;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
NODE_ENV: 'development' | 'production';
|
||||
PORT: number;
|
||||
JWT_REFRESH_SECRET: string;
|
||||
JWT_ACCESS_SECRET: string;
|
||||
AUTH_CLIENT_ID: string;
|
||||
AUTH_CLIENT_SECRET: string;
|
||||
REDIS_URL: string;
|
||||
URL_TOKEN: string;
|
||||
S3_ENDPOINT: string;
|
||||
S3_ID: string;
|
||||
S3_KEY: string;
|
||||
AUTH_SECRET: string;
|
||||
AUTH_SALT: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify({
|
||||
logger: true,
|
||||
ajv: { customOptions: { allErrors: true } }
|
||||
})
|
||||
.decorate('db', new PrismaClient())
|
||||
.decorate(
|
||||
'storage',
|
||||
new S3Client({
|
||||
endpoint: process.env.S3_ENDPOINT,
|
||||
region: 'us-east',
|
||||
credentials: {
|
||||
accessKeyId: process.env.S3_ID,
|
||||
secretAccessKey: process.env.S3_KEY
|
||||
}
|
||||
})
|
||||
)
|
||||
.register(fastifyCookie)
|
||||
// .decorate('redis', async () => {
|
||||
// const client = createClient({
|
||||
// url: process.env.REDIS_URL
|
||||
// });
|
||||
|
||||
// client.on('error', err => console.log('Redis Client Error', err));
|
||||
|
||||
// await client.connect();
|
||||
// return client;
|
||||
// })
|
||||
.addHook('onRoute', route => console.log(route.url))
|
||||
// .register(fastifyCors, {
|
||||
// origin: ['http://127.0.0.1:3000'],
|
||||
// credentials: true
|
||||
// })
|
||||
.decorateReply(
|
||||
'sendError',
|
||||
function (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: any,
|
||||
code = 500,
|
||||
explanation = 'Unexpected error occured. Issue will be reported to staff.'
|
||||
) {
|
||||
this.log.error(error);
|
||||
this.code(code).send(new Error(explanation));
|
||||
}
|
||||
)
|
||||
.register(fastifyAutoload, {
|
||||
dir: path.join(__dirname, 'routes'),
|
||||
routeParams: true,
|
||||
autoHooks: true,
|
||||
options: { prefix: '/api' }
|
||||
})
|
||||
// .register(fastifyAutoload, {
|
||||
// dir: path.join(__dirname, 'link'),
|
||||
// routeParams: true,
|
||||
// autoHooks: true,
|
||||
// options: { prefix: '/a' }
|
||||
// })
|
||||
.listen({ port: process.env.PORT || 8080, host: '0.0.0.0' })
|
||||
// eslint-disable-next-line no-console
|
||||
.then(() => console.log('Server Started'))
|
||||
// eslint-disable-next-line no-console
|
||||
.catch(console.error);
|
|
@ -0,0 +1,51 @@
|
|||
import { FastifyInstance, FastifyReply } from 'fastify';
|
||||
import { CookieSerializeOptions } from '@fastify/cookie';
|
||||
import { User } from '@prisma/client';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
const cookieSettings: CookieSerializeOptions = {
|
||||
httpOnly: true,
|
||||
path: '/api/auth/refresh_token',
|
||||
sameSite: 'strict',
|
||||
maxAge: 2629800, //1 month
|
||||
secure: process.env.NODE_ENV === 'production'
|
||||
};
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyReply {
|
||||
sendTokens: (user: User) => FastifyReply;
|
||||
clearTokens: () => FastifyReply;
|
||||
}
|
||||
}
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server
|
||||
.decorateReply(
|
||||
'sendTokens',
|
||||
function (this: FastifyReply, { id, nickname, tokenVersion }: User) {
|
||||
return this.setCookie(
|
||||
'uwu',
|
||||
jwt.sign({ tokenVersion, id }, process.env.JWT_REFRESH_SECRET, {
|
||||
expiresIn: '30d'
|
||||
}),
|
||||
cookieSettings
|
||||
).send({
|
||||
user: {
|
||||
id,
|
||||
nickname
|
||||
},
|
||||
token: jwt.sign(
|
||||
{
|
||||
id
|
||||
},
|
||||
process.env.JWT_ACCESS_SECRET,
|
||||
{
|
||||
expiresIn: '15m'
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
)
|
||||
.decorateReply('clearTokens', function (this: FastifyReply) {
|
||||
return this.clearCookie('uwu', cookieSettings);
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { stringify } from 'querystring';
|
||||
import axios from 'axios';
|
||||
import { pbkdf2 } from 'node:crypto';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['username', 'password'],
|
||||
properties: {
|
||||
username: { type: 'string' },
|
||||
password: { type: 'string' }
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post<{ Body: FromSchema<typeof schema.body> }>(
|
||||
'/login',
|
||||
{ schema },
|
||||
async (req, reply) => {
|
||||
const pbkdf2Promise = promisify(pbkdf2);
|
||||
const hash = await pbkdf2Promise(
|
||||
req.body.password,
|
||||
process.env.AUTH_SALT,
|
||||
100000,
|
||||
64,
|
||||
'sha512'
|
||||
);
|
||||
await server.db.user
|
||||
.findFirst({
|
||||
where: {
|
||||
nickname: req.body.username,
|
||||
password: hash.toString('hex')
|
||||
}
|
||||
})
|
||||
.then(user => {
|
||||
if (!user) return reply.code(403).send(new Error('Invalid username or password'));
|
||||
reply.sendTokens(user);
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post('/logout', async (_req, reply) => reply.clearTokens().send());
|
|
@ -0,0 +1,20 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
import { verify } from 'jsonwebtoken';
|
||||
import { User } from '@prisma/client';
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post('/refresh_token', async (req, reply) => {
|
||||
const refreshToken = req.cookies.uwu ?? null;
|
||||
if (!refreshToken) return reply.send({ error: 'uwu cookie is lost' });
|
||||
try {
|
||||
const { id, tokenVersion } = verify(refreshToken, process.env.JWT_REFRESH_SECRET) as User,
|
||||
user = await server.db.user.findUnique({
|
||||
where: { id }
|
||||
});
|
||||
if (!user || tokenVersion !== user.tokenVersion)
|
||||
return reply.code(400).clearTokens().send(new Error('Please login again'));
|
||||
return reply.sendTokens(user);
|
||||
} catch (e) {
|
||||
return reply.clearTokens().sendError(e, 400, 'Cannot validate your auth, please login again');
|
||||
}
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { pbkdf2 } from 'node:crypto';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['username', 'password', 'key'],
|
||||
properties: {
|
||||
username: { type: 'string' },
|
||||
password: { type: 'string' },
|
||||
key: { type: 'string' }
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post<{ Body: FromSchema<typeof schema.body> }>(
|
||||
'/register',
|
||||
{ schema },
|
||||
async (req, reply) => {
|
||||
if (req.body.key !== process.env.AUTH_SECRET)
|
||||
return reply.code(403).send('Invalid register key');
|
||||
const currentSeason = (
|
||||
await server.db.season.findFirst({ where: { current: true }, select: { id: true } })
|
||||
)?.id;
|
||||
const pbkdf2Promise = promisify(pbkdf2);
|
||||
const hash = await pbkdf2Promise(
|
||||
req.body.password,
|
||||
process.env.AUTH_SALT,
|
||||
100000,
|
||||
64,
|
||||
'sha512'
|
||||
);
|
||||
server.log.info(reply.sent);
|
||||
|
||||
await server.db.user
|
||||
.create({
|
||||
data: {
|
||||
nickname: req.body.username,
|
||||
password: hash.toString('hex'),
|
||||
accounts: {
|
||||
create: {
|
||||
season: {
|
||||
connect: {
|
||||
id: currentSeason
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(user => reply.sendTokens(user))
|
||||
.catch(err => {
|
||||
if (err.code === 'P2002') reply.code(400).send('User is already exists');
|
||||
reply.sendError(err);
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,45 @@
|
|||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { stringify } from 'querystring';
|
||||
import axios from 'axios';
|
||||
import { pbkdf2 } from 'node:crypto';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['username', 'password'],
|
||||
properties: {
|
||||
username: { type: 'string' },
|
||||
password: { type: 'string' }
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post<{ Body: FromSchema<typeof schema.body> }>(
|
||||
'/verify',
|
||||
{ schema },
|
||||
async (req, reply) => {
|
||||
const pbkdf2Promise = promisify(pbkdf2);
|
||||
const hash = await pbkdf2Promise(
|
||||
req.body.password,
|
||||
process.env.AUTH_SALT,
|
||||
100000,
|
||||
64,
|
||||
'sha512'
|
||||
);
|
||||
|
||||
await server.db.user
|
||||
.findFirst({
|
||||
where: {
|
||||
nickname: req.body.username,
|
||||
password: hash.toString('hex')
|
||||
}
|
||||
})
|
||||
.then(user => {
|
||||
if (!user) return reply.code(403).send(new Error('Invalid username or password'));
|
||||
reply.send('ok');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,11 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.get('/health', (req, reply) => {
|
||||
try {
|
||||
server.db.$queryRaw`SELECT 1`;
|
||||
reply.send('ok');
|
||||
} catch {
|
||||
reply.send('bad');
|
||||
}
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
import axios from 'axios';
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { HeadObjectCommand } from '@aws-sdk/client-s3';
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.get<{ Params: { nickname: string } }>('/:nickname', async (req, reply) => {
|
||||
const existingUser = await server.db.account.findFirst({
|
||||
where: {
|
||||
user: {
|
||||
nickname: req.params.nickname
|
||||
},
|
||||
season: {
|
||||
current: true
|
||||
}
|
||||
},
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
nickname: true
|
||||
}
|
||||
},
|
||||
guild: {
|
||||
select: {
|
||||
id: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const existingSkin = await server.storage
|
||||
.send(new HeadObjectCommand({ Bucket: 'rpz', Key: `skins/${req.params.nickname}.png` }))
|
||||
.then(head => head)
|
||||
.catch(() => null);
|
||||
console.log(req.params.nickname);
|
||||
|
||||
if (existingUser && existingSkin) {
|
||||
reply.send({
|
||||
SKIN: {
|
||||
url: `${process.env.S3_ENDPOINT}/rpz/skins/${existingUser.user.nickname}.png`
|
||||
},
|
||||
CAPE: existingUser.guild
|
||||
? {
|
||||
url: `${process.env.S3_ENDPOINT}/rpz/capes/${existingUser.guild.id}.png`
|
||||
}
|
||||
: undefined
|
||||
});
|
||||
} else {
|
||||
const {
|
||||
data: { id: uuid }
|
||||
} = await axios.get(`https://api.mojang.com/users/profiles/minecraft/${req.params.nickname}`);
|
||||
const { data: skinResponseRaw } = await axios.get(
|
||||
`https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`
|
||||
);
|
||||
const skinResponse = JSON.parse(
|
||||
Buffer.from(skinResponseRaw.properties[0].value, 'base64').toString('utf-8')
|
||||
);
|
||||
// console.log(skinResponse);
|
||||
reply.send(skinResponse.textures);
|
||||
}
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { nanoid } from 'nanoid/async';
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['session', 'key'],
|
||||
properties: {
|
||||
session: { type: 'string' },
|
||||
key: { type: 'string' }
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.post<{ Body: FromSchema<typeof schema.body> }>(
|
||||
'/create',
|
||||
{ schema },
|
||||
async (req, reply) => {}
|
||||
);
|
|
@ -0,0 +1,11 @@
|
|||
import { FastifyInstance } from 'fastify';
|
||||
|
||||
export default async (server: FastifyInstance) =>
|
||||
server.get<{ Params: { id: string } }>('/:id', (req, reply) =>
|
||||
server.db.user
|
||||
.findFirstOrThrow({ where: { id: req.params.id }, select: {} })
|
||||
.then(user => reply.send(user))
|
||||
.catch(() => server.db.user.findFirstOrThrow({ where: { nickname: req.params.id } }))
|
||||
.then(user => reply.send(user))
|
||||
.catch(() => reply.code(404).send('User not found'))
|
||||
);
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "@tsconfig/node18/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true
|
||||
// "module": "esnext"
|
||||
},
|
||||
"esModuleInterop": true
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
services:
|
||||
db:
|
||||
image: postgres
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=rpz_auth
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
|
||||
auth:
|
||||
build: ./auth
|
||||
depends_on:
|
||||
- db
|
||||
restart: unless-stopped
|
||||
|
||||
minecraft:
|
||||
build: .
|
||||
stdin_open: true # docker run -i
|
||||
tty: true # docker run -t
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./data:/etc/minecraft
|
||||
ports:
|
||||
- 25565:25565
|
||||
depends_on:
|
||||
- db
|
||||
- auth
|
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
|
@ -1 +0,0 @@
|
|||
eula=true
|
13
files/ops
13
files/ops
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -o errexit
|
||||
|
||||
OPS_FILE="/etc/minecraft/ops.txt"
|
||||
[ ! -e "${OPS_FILE}" ] && touch ${OPS_FILE}
|
||||
|
||||
for OP in "$@"; do
|
||||
if grep -qx "${OP}" ${OPS_FILE}; then
|
||||
echo "NOTICE: '${OP}' already present in OPs file"; continue
|
||||
fi
|
||||
|
||||
echo "${OP}" >> ${OPS_FILE} && echo "SUCCESS: '${OP}' added to OPs file"
|
||||
done
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
|
@ -0,0 +1,20 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['svelte3', '@typescript-eslint'],
|
||||
ignorePatterns: ['*.cjs'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
}
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
|
@ -0,0 +1 @@
|
|||
engine-strict=true
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
||||
"@typescript-eslint/parser": "^5.27.0",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"prettier": "^2.6.2",
|
||||
"prettier-plugin-svelte": "^2.7.0",
|
||||
"svelte": "^3.44.0",
|
||||
"svelte-check": "^2.7.1",
|
||||
"svelte-preprocess": "^4.10.6",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"vite": "^3.1.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Error {}
|
||||
// interface Platform {}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,15 @@
|
|||
import adapter from '@sveltejs/adapter-auto';
|
||||
import preprocess from 'svelte-preprocess';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: preprocess(),
|
||||
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import type { UserConfig } from 'vite';
|
||||
|
||||
const config: UserConfig = {
|
||||
plugins: [sveltekit()]
|
||||
};
|
||||
|
||||
export default config;
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
packages:
|
||||
- 'backend'
|
||||
- 'frontend'
|
Loading…
Reference in New Issue