Merge pull request #11 from aldy505/client/docs
Updating docs on client web
This commit is contained in:
commit
58605e6af3
|
@ -93,17 +93,17 @@ jobs:
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Installling dependencies
|
- name: Installling dependencies
|
||||||
run: yarn install
|
run: npm install
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: yarn lint
|
run: npm run lint
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: yarn build
|
run: npm run build
|
||||||
env:
|
env:
|
||||||
VITE_SENTRY_DSN: https://examplePublicKey@o0.ingest.sentry.io/0
|
VITE_SENTRY_DSN: https://examplePublicKey@o0.ingest.sentry.io/0
|
||||||
VITE_NODE_ENV: development
|
VITE_NODE_ENV: development
|
||||||
VITE_API_ENDPOINT: https://jokesbapak2.herokuapp.com/v1
|
VITE_API_ENDPOINT: https://jokesbapak2.reinaldyrafli.com/api/v1
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v1
|
||||||
|
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Installling dependencies
|
- name: Installling dependencies
|
||||||
run: yarn install
|
run: npm install
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npx eslint --ext .svelte,.js,.ts --ignore-path .gitignore .
|
run: npx eslint --ext .svelte,.js,.ts --ignore-path .gitignore .
|
||||||
|
@ -28,11 +28,11 @@ jobs:
|
||||||
run: npx prettier --check --ignore-path .gitignore --plugin-search-dir=. "./**/*.(ts|json|js|svelte)"
|
run: npx prettier --check --ignore-path .gitignore --plugin-search-dir=. "./**/*.(ts|json|js|svelte)"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: yarn build
|
run: npm run build
|
||||||
env:
|
env:
|
||||||
VITE_SENTRY_DSN: https://examplePublicKey@o0.ingest.sentry.io/0
|
VITE_SENTRY_DSN: https://examplePublicKey@o0.ingest.sentry.io/0
|
||||||
VITE_NODE_ENV: development
|
VITE_NODE_ENV: development
|
||||||
VITE_API_ENDPOINT: https://jokesbapak2.herokuapp.com/v1
|
VITE_API_ENDPOINT: https://jokesbapak2.reinaldyrafli.com/api/v1
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v1
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,goland,webstorm,datagrip
|
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,goland,webstorm
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,goland,webstorm,datagrip
|
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,goland,webstorm
|
||||||
|
|
||||||
### GoLand ###
|
### GoLand ###
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
@ -214,6 +214,10 @@ fabric.properties
|
||||||
# Azure Toolkit for IntelliJ plugin
|
# Azure Toolkit for IntelliJ plugin
|
||||||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,goland,webstorm,datagrip
|
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,goland,webstorm
|
||||||
|
|
||||||
data
|
docker-compose.override.yml
|
||||||
|
data/
|
||||||
|
.env.*
|
||||||
|
.env
|
||||||
|
!.env.example
|
|
@ -7,9 +7,9 @@
|
||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
👋 Hey there! Still a work in progress, if you'd like to contribute this while this repo is still growing, that would be so great!
|
👋 Hey there! Always a work in progress, if you'd like to contribute this while this repo is still growing, that would be so great!
|
||||||
|
|
||||||
It's on alpha phase now. You can access the front facing web on [jokesbapak2.pages.dev](http://jokesbapak2.pages.dev/).
|
ou can access the front facing web on [jokesbapak2.reinaldyrafli.com](http://jokesbapak2.reinaldyrafli.com/).
|
||||||
|
|
||||||
## Brief explanation of what is this
|
## Brief explanation of what is this
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
ENV=development
|
ENV=development
|
||||||
PORT=5000
|
PORT=5000
|
||||||
|
HOSTNAME=127.0.0.1
|
||||||
|
|
||||||
DATABASE_URL=postgres://postgres:password@localhost:5432/jokesbapak2
|
|
||||||
REDIS_URL=redis://@localhost:6379
|
REDIS_URL=redis://@localhost:6379
|
||||||
|
MINIO_HOST=
|
||||||
|
MINIO_ACCESS_ID=
|
||||||
|
MINIO_SECRET_KEY=
|
||||||
|
MINIO_TOKEN=
|
||||||
|
|
||||||
SENTRY_DSN=
|
SENTRY_DSN=
|
|
@ -10,6 +10,10 @@ FROM debian:bullseye AS runtime
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get upgrade --no-install-recommends -y \
|
||||||
|
&& apt-get install -y --no-install-recommends curl \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=builder /app/main .
|
COPY --from=builder /app/main .
|
||||||
|
|
||||||
ENV PORT=5000
|
ENV PORT=5000
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"url": "https://jokesbapak2.herokuapp.com/v1",
|
"url": "https://jokesbapak2.reinaldyrafli.com/api/v1",
|
||||||
"description": "Production"
|
"description": "Production"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://jokesbapak2.herokuapp.com",
|
"url": "https://jokesbapak2.reinaldyrafli.com/api",
|
||||||
"description": "Production"
|
"description": "Production"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,9 +14,9 @@ info:
|
||||||
name: GNU General Public License v3.0
|
name: GNU General Public License v3.0
|
||||||
url: https://github.com/aldy505/jokes-bapak2/blob/master/LICENSE
|
url: https://github.com/aldy505/jokes-bapak2/blob/master/LICENSE
|
||||||
servers:
|
servers:
|
||||||
- url: "https://jokesbapak2.herokuapp.com/v1"
|
- url: "https://jokesbapak2.reinaldyrafli.com/api/v1"
|
||||||
description: Production
|
description: Production
|
||||||
- url: "https://jokesbapak2.herokuapp.com"
|
- url: "https://jokesbapak2.reinaldyrafli.com/api"
|
||||||
description: Production
|
description: Production
|
||||||
- url: "http://localhost:5000"
|
- url: "http://localhost:5000"
|
||||||
description: Development
|
description: Development
|
||||||
|
@ -31,9 +31,9 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: Image data
|
description: Image data
|
||||||
content:
|
content:
|
||||||
'image/gif': {}
|
"image/gif": {}
|
||||||
'image/png': {}
|
"image/png": {}
|
||||||
'image/jpeg': {}
|
"image/jpeg": {}
|
||||||
put:
|
put:
|
||||||
summary: Add a new joke into database
|
summary: Add a new joke into database
|
||||||
description: asd
|
description: asd
|
||||||
|
@ -46,15 +46,15 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/request.auth'
|
- $ref: "#/components/schemas/request.auth"
|
||||||
- $ref: '#/components/schemas/request.joke'
|
- $ref: "#/components/schemas/request.joke"
|
||||||
responses:
|
responses:
|
||||||
201:
|
201:
|
||||||
description: Image has been added
|
description: Image has been added
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/request.joke'
|
$ref: "#/components/schemas/request.joke"
|
||||||
example:
|
example:
|
||||||
link: https://link.to/image.jpg
|
link: https://link.to/image.jpg
|
||||||
400:
|
400:
|
||||||
|
@ -62,7 +62,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
example:
|
example:
|
||||||
error: URL provided is not a valid image
|
error: URL provided is not a valid image
|
||||||
403:
|
403:
|
||||||
|
@ -70,7 +70,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
/id/{id}:
|
/id/{id}:
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
|
@ -88,17 +88,16 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: Image data
|
description: Image data
|
||||||
content:
|
content:
|
||||||
'image/jpeg': {}
|
"image/jpeg": {}
|
||||||
'image/png': {}
|
"image/png": {}
|
||||||
'image/gif': {}
|
"image/gif": {}
|
||||||
404:
|
404:
|
||||||
description: Provided image ID was not found
|
description: Provided image ID was not found
|
||||||
content:
|
content:
|
||||||
text/plain:
|
text/plain:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example:
|
example: Requested ID was not found.
|
||||||
Requested ID was not found.
|
|
||||||
patch:
|
patch:
|
||||||
summary: Update a Joke with certain image ID
|
summary: Update a Joke with certain image ID
|
||||||
description: Returns consistent image for every call.
|
description: Returns consistent image for every call.
|
||||||
|
@ -111,26 +110,26 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/response.confirmation'
|
- $ref: "#/components/schemas/response.confirmation"
|
||||||
- $ref: '#/components/schemas/request.joke'
|
- $ref: "#/components/schemas/request.joke"
|
||||||
400:
|
400:
|
||||||
description: Link provided is not a valid image
|
description: Link provided is not a valid image
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
403:
|
403:
|
||||||
description: Must be authenticated to submit a joke
|
description: Must be authenticated to submit a joke
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
406:
|
406:
|
||||||
description: If the Joke ID does not exists
|
description: If the Joke ID does not exists
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
delete:
|
delete:
|
||||||
summary: Delete a Joke with certain image ID
|
summary: Delete a Joke with certain image ID
|
||||||
description: hi
|
description: hi
|
||||||
|
@ -142,19 +141,19 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.confirmation'
|
$ref: "#/components/schemas/response.confirmation"
|
||||||
403:
|
403:
|
||||||
description: Must be authenticated to submit a joke
|
description: Must be authenticated to submit a joke
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
406:
|
406:
|
||||||
description: If the Joke ID does not exists
|
description: If the Joke ID does not exists
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
/today:
|
/today:
|
||||||
get:
|
get:
|
||||||
summary: Get the joke of the day
|
summary: Get the joke of the day
|
||||||
|
@ -165,9 +164,9 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: Image data
|
description: Image data
|
||||||
content:
|
content:
|
||||||
'image/jpeg': {}
|
"image/jpeg": {}
|
||||||
'image/png': {}
|
"image/png": {}
|
||||||
'image/gif': {}
|
"image/gif": {}
|
||||||
/total:
|
/total:
|
||||||
get:
|
get:
|
||||||
summary: Get total amount of jokes in database
|
summary: Get total amount of jokes in database
|
||||||
|
@ -179,7 +178,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.confirmation'
|
$ref: "#/components/schemas/response.confirmation"
|
||||||
example:
|
example:
|
||||||
message: "154"
|
message: "154"
|
||||||
/submit:
|
/submit:
|
||||||
|
@ -223,7 +222,7 @@ paths:
|
||||||
jokes:
|
jokes:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/response.submission'
|
$ref: "#/components/schemas/response.submission"
|
||||||
post:
|
post:
|
||||||
summary: Submit a joke
|
summary: Submit a joke
|
||||||
description: >
|
description: >
|
||||||
|
@ -256,17 +255,17 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/response.confirmation'
|
- $ref: "#/components/schemas/response.confirmation"
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/components/schemas/response.submission'
|
$ref: "#/components/schemas/response.submission"
|
||||||
400:
|
400:
|
||||||
description: Invalid data was sent
|
description: Invalid data was sent
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
/health:
|
/health:
|
||||||
get:
|
get:
|
||||||
summary: Health check
|
summary: Health check
|
||||||
|
@ -281,7 +280,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/response.error'
|
$ref: "#/components/schemas/response.error"
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
|
|
|
@ -16,6 +16,7 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi/v5 v5.0.7
|
github.com/go-chi/chi/v5 v5.0.7
|
||||||
github.com/minio/minio-go/v7 v7.0.35
|
github.com/minio/minio-go/v7 v7.0.35
|
||||||
|
github.com/rs/cors v1.8.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
|
@ -238,6 +238,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
|
||||||
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||||
|
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
|
13
api/main.go
13
api/main.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -20,6 +21,7 @@ import (
|
||||||
"github.com/allegro/bigcache/v3"
|
"github.com/allegro/bigcache/v3"
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/rs/cors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -69,7 +71,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup In Memory
|
// Setup In Memory
|
||||||
memory, err := bigcache.NewBigCache(bigcache.DefaultConfig(6 * time.Hour))
|
memory, err := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
@ -127,12 +129,19 @@ func main() {
|
||||||
|
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
|
|
||||||
|
router.Use(cors.New(cors.Options{
|
||||||
|
AllowedMethods: []string{http.MethodGet},
|
||||||
|
AllowCredentials: false,
|
||||||
|
MaxAge: int(60 * 60 * 24 * 365),
|
||||||
|
Debug: false,
|
||||||
|
}).Handler)
|
||||||
|
|
||||||
router.Mount("/health", healthRouter)
|
router.Mount("/health", healthRouter)
|
||||||
router.Mount("/", jokeRouter)
|
router.Mount("/", jokeRouter)
|
||||||
|
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Handler: router,
|
Handler: router,
|
||||||
Addr: hostname + ":" + port,
|
Addr: net.JoinHostPort(hostname, port),
|
||||||
ReadTimeout: time.Minute,
|
ReadTimeout: time.Minute,
|
||||||
WriteTimeout: time.Minute,
|
WriteTimeout: time.Minute,
|
||||||
IdleTimeout: time.Second * 30,
|
IdleTimeout: time.Second * 30,
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "yarn run b:random && yarn run b:today && yarn run b:byid",
|
"start": "yarn run b:random && yarn run b:today && yarn run b:byid",
|
||||||
"b:random": "autocannon --title \"GET /v1/ - Random Jokes\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.herokuapp.com/v1/",
|
"b:random": "autocannon --title \"GET /v1/ - Random Jokes\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.reinaldyrafli.com/api/v1/",
|
||||||
"b:today": "autocannon --title \"GET /v1/today - Today's Jokes\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.herokuapp.com/v1/today",
|
"b:today": "autocannon --title \"GET /v1/today - Today's Jokes\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.reinaldyrafli.com/api/v1/today",
|
||||||
"b:byid": "autocannon --title \"GET /v1/id/5 - Joke by ID\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.herokuapp.com/v1/id/5"
|
"b:byid": "autocannon --title \"GET /v1/id/5 - Joke by ID\" --method GET --amount 100 --bailout 3 --headers user-agent=benchmark https://jokesbapak2.reinaldyrafli.com/api/v1/id/5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autocannon": "^7.4.0"
|
"autocannon": "^7.4.0"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
v14.17.3
|
v16.13
|
|
@ -1,14 +1,15 @@
|
||||||
FROM node:14.17.3-buster
|
FROM node:16.17.0-bullseye
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get upgrade --no-install-recommends -y \
|
||||||
|
&& apt-get install -y --no-install-recommends curl \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm install -g yarn
|
RUN npm ci && npm run build && rm -rf node_modules && npm ci --omit=dev
|
||||||
RUN yarn install
|
|
||||||
RUN yarn build
|
|
||||||
RUN yarn cache clean
|
|
||||||
|
|
||||||
EXPOSE ${PORT}
|
EXPOSE ${PORT}
|
||||||
|
|
||||||
CMD ["yarn", "preview"]
|
CMD ["node", "dist/index.js"]
|
|
@ -1,35 +1,35 @@
|
||||||
# Jokes Bapak2 Client
|
# Jokes Bapak2 Client
|
||||||
|
|
||||||
Still work in progress
|
The frontend.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install modules
|
# Install modules
|
||||||
$ yarn install
|
$ npm install
|
||||||
|
|
||||||
# Run local server
|
# Run local server
|
||||||
$ yarn dev
|
$ npm run dev
|
||||||
|
|
||||||
# build everything
|
# build everything
|
||||||
$ yarn build
|
$ npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
> You can preview the built app with `yarn preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
|
> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
|
||||||
|
|
||||||
## Used packages
|
## Used packages
|
||||||
|
|
||||||
| Name | Version | Type |
|
| Name | Version | Type |
|
||||||
| --- | --- | --- |
|
| -------------------------- | ---------------- | -------------------- |
|
||||||
| @sveltejs/kit | `1.0.0-next.129` | Framework |
|
| @sveltejs/kit | `1.0.0-next.480` | Framework |
|
||||||
| svelte | `3.38.3` | Framework |
|
| svelte | `3.50.1` | Framework |
|
||||||
| typescript | `4.3.5` | Static type language |
|
| typescript | `4.8.3` | Static type language |
|
||||||
| svelte-i18n | `3.3.9` | i18n Library |
|
| svelte-i18n | `3.4.0` | i18n Library |
|
||||||
| svelte-windicss-preprocess | `4.0.12` | CSS Library |
|
| svelte-windicss-preprocess | `4.2.8` | CSS Library |
|
||||||
| @fontsource/fira-mono | `4.5.0` | Webfont |
|
| @fontsource/fira-mono | `4.5.9` | Webfont |
|
||||||
| @fontsource/rubik | `4.5.0` | Webfont |
|
| @fontsource/rubik | `4.5.11` | Webfont |
|
||||||
| dotenv | `10.0.0` | Utils |
|
| dotenv | `16.0.2` | Utils |
|
||||||
| @sentry/browser | `6.9.0` | Logging |
|
| @sentry/browser | `7.12.1` | Logging |
|
||||||
|
|
||||||
## Directory structure
|
## Directory structure
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ $ yarn build
|
||||||
├── static - Static/public directory
|
├── static - Static/public directory
|
||||||
├── svelte.config.js - Svelte configuration file
|
├── svelte.config.js - Svelte configuration file
|
||||||
├── tsconfig.json - Typescript configuration file
|
├── tsconfig.json - Typescript configuration file
|
||||||
├── windi.config.js - WindiCSS configuration file
|
├── windi.config.ts - WindiCSS configuration file
|
||||||
└── yarn.lock - Packages lock file
|
└── package-lock.json - Packages lock file
|
||||||
```
|
```
|
||||||
|
|
||||||
## `.env` configuration
|
## `.env` configuration
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,38 +11,39 @@
|
||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "svelte-kit dev",
|
"dev": "vite dev",
|
||||||
"build": "svelte-kit build",
|
"build": "vite build",
|
||||||
"preview": "svelte-kit preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "eslint --fix --ext .svelte,.js,.ts --ignore-path .gitignore .",
|
"lint": "eslint --fix --ext .svelte,.js,.ts --ignore-path .gitignore .",
|
||||||
"format": "prettier --write --ignore-path .gitignore --plugin-search-dir=. \"./**/*.(ts|json|js|svelte)\""
|
"format": "prettier --write --ignore-path .gitignore --plugin-search-dir=. \"./**/*.(ts|json|js|svelte)\""
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-static": "1.0.0-next.13",
|
"@sveltejs/adapter-node": "^1.0.0-next.89",
|
||||||
"@sveltejs/kit": "1.0.0-next.129",
|
"@sveltejs/kit": "1.0.0-next.480",
|
||||||
"@typescript-eslint/eslint-plugin": "4.28.3",
|
"@typescript-eslint/eslint-plugin": "5.36.2",
|
||||||
"@typescript-eslint/parser": "4.28.3",
|
"@typescript-eslint/parser": "5.36.2",
|
||||||
"cssnano": "5.0.6",
|
"cssnano": "5.1.13",
|
||||||
"eslint": "7.30.0",
|
"eslint": "8.23.0",
|
||||||
"eslint-config-prettier": "8.3.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
"eslint-plugin-svelte3": "3.2.0",
|
"eslint-plugin-svelte3": "4.0.0",
|
||||||
"prettier": "2.3.2",
|
"prettier": "2.7.1",
|
||||||
"prettier-plugin-svelte": "2.3.1",
|
"prettier-plugin-svelte": "2.7.0",
|
||||||
"svelte": "3.38.3",
|
"svelte": "3.50.1",
|
||||||
"svelte-check": "2.2.2",
|
"svelte-check": "2.9.0",
|
||||||
"svelte-preprocess": "4.7.4",
|
"svelte-preprocess": "4.10.7",
|
||||||
"svelte-windicss-preprocess": "4.0.12",
|
"svelte-windicss-preprocess": "4.2.8",
|
||||||
"tslib": "2.3.0",
|
"tslib": "2.4.0",
|
||||||
"typescript": "4.3.5"
|
"typescript": "4.8.3",
|
||||||
|
"vite": "^3.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/fira-mono": "4.5.0",
|
"@fontsource/fira-mono": "4.5.9",
|
||||||
"@fontsource/rubik": "4.5.0",
|
"@fontsource/rubik": "4.5.11",
|
||||||
"@sentry/browser": "6.9.0",
|
"@sentry/browser": "7.12.1",
|
||||||
"dotenv": "10.0.0",
|
"dotenv": "16.0.2",
|
||||||
"ohmyfetch": "^0.2.0",
|
"ohmyfetch": "0.4.18",
|
||||||
"svelte-i18n": "3.3.9"
|
"svelte-i18n": "3.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="%lang%">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="keywords" content="jokesbapak2, jokes, bapak2, indonesian, dad, jokes, api, rest" />
|
<meta name="keywords" content="jokesbapak2, jokes, bapak2, indonesian, dad, jokes, api, rest" />
|
||||||
<meta name="author" content="Reinaldy Rafli" />
|
<meta name="author" content="Reinaldy Rafli" />
|
||||||
<meta name="theme-color" content="#f4a9f5" />
|
<meta name="theme-color" content="#f4a9f5" />
|
||||||
<meta name="publisher" content="https://jokesbapak2.pages.dev/" />
|
<meta name="publisher" content="https://jokesbapak2.reinaldyrafli.com/" />
|
||||||
<meta property="og:image" content="https://jokesbapak2.pages.dev/social.jpg" />
|
<meta property="og:image" content="%sveltekit.assets%/social.jpg" />
|
||||||
<meta property="og:image:alt" content="Jokesbapak2 - Largest collection of Indonesian dad jokes" />
|
<meta property="og:image:alt" content="Jokesbapak2 - Largest collection of Indonesian dad jokes" />
|
||||||
<meta property="og:image:secure_url" content="https://jokesbapak2.pages.dev/social.jpg" />
|
<meta property="og:image:secure_url" content="%sveltekit.assets%/social.jpg" />
|
||||||
<meta property="og:image:width" content="1280" />
|
<meta property="og:image:width" content="1280" />
|
||||||
<meta property="og:image:height" content="640" />
|
<meta property="og:image:height" content="640" />
|
||||||
<meta property="og:locale" content="en_US" />
|
<meta property="og:locale" content="en_US" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta name="twitter:image:src" content="https://jokesbapak2.pages.dev/social.jpg" />
|
<meta name="twitter:image:src" content="%sveltekit.assets%/social.jpg" />
|
||||||
<meta name="twitter:image" content="https://jokesbapak2.pages.dev/social.jpg" />
|
<meta name="twitter:image" content="%sveltekit.assets%/social.jpg" />
|
||||||
<meta name="twitter:creator" content="Reinaldy Rafli" />
|
<meta name="twitter:creator" content="Reinaldy Rafli" />
|
||||||
<link rel="icon" type="image/png" href="/favicon.png">
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
<link rel="icon" type="image/svg" href="/favicon.svg">
|
<link rel="icon" type="image/svg" href="/favicon.svg">
|
||||||
<script async defer data-website-id="82725fd7-2542-4828-b313-349f68d84894" src="https://jokesbapak2-analytics.herokuapp.com/umami.js" data-do-not-track="true" data-domains="jokesbapak2.pages.dev"></script>
|
%sveltekit.head%
|
||||||
%svelte.head%
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="svelte">%svelte.body%</div>
|
<div id="svelte">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const handle: Handle = ({ event, resolve }) => {
|
||||||
|
return resolve(event, {
|
||||||
|
transformPageChunk: ({ html }) => html.replace('%lang%', 'en'),
|
||||||
|
});
|
||||||
|
};
|
|
@ -71,7 +71,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
"limit": "We limit the request to be 30 request/minute.",
|
"limit": "We limit the request to be 120 request/minute.",
|
||||||
"get": {
|
"get": {
|
||||||
"title": "Get Jokes",
|
"title": "Get Jokes",
|
||||||
"random": {
|
"random": {
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
"fetch": {
|
"fetch": {
|
||||||
"1": "Using fetch API",
|
"1": "Using fetch API",
|
||||||
"2": "You can use it, but I personally don't recommend it.",
|
"2": "You can use it, but I personally don't recommend it.",
|
||||||
"3": "data is a base64 string"
|
"3": "Do some error handling if the request fails"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
"limit": "Kami membatasi request menjadi 30 request/menit.",
|
"limit": "Kami membatasi request menjadi 120 request/menit.",
|
||||||
"get": {
|
"get": {
|
||||||
"title": "Dapatkan Jokes",
|
"title": "Dapatkan Jokes",
|
||||||
"random": {
|
"random": {
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
"fetch": {
|
"fetch": {
|
||||||
"1": "Menggunakan fetch API",
|
"1": "Menggunakan fetch API",
|
||||||
"2": "Bapak bisa menggunakannya, tapi saya secara personal tidak merekomendasikannya.",
|
"2": "Bapak bisa menggunakannya, tapi saya secara personal tidak merekomendasikannya.",
|
||||||
"3": "data adalah string dengan isi base64"
|
"3": "Periksa dan jangan abaikan errornya jika request gagal"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,20 +42,14 @@
|
||||||
<p class="text-sm opacity-50 hover:opacity-90 transition duration-300 ease-in-out inline-block">
|
<p class="text-sm opacity-50 hover:opacity-90 transition duration-300 ease-in-out inline-block">
|
||||||
{$_('footer.language')}
|
{$_('footer.language')}
|
||||||
<a href="?lang=en" target="_top" class="hover:underline">{$_('footer.english')}</a>
|
<a href="?lang=en" target="_top" class="hover:underline">{$_('footer.english')}</a>
|
||||||
|
|
|
||||||
<a href="?lang=id" target="_top" class="hover:underline">{$_('footer.indonesian')}</a>.
|
<a href="?lang=id" target="_top" class="hover:underline">{$_('footer.indonesian')}</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-initial pr-3">
|
|
||||||
<p class="text-sm opacity-50 hover:opacity-90 transition duration-300 ease-in-out inline-block">
|
|
||||||
<a href="https://jokesbapak2-analytics.herokuapp.com/share/1xYuVSyl/Jokes%20Bapak2" class="hover:underline"
|
|
||||||
>Analytics</a
|
|
||||||
>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style windi:preflights:global windi:safelist:global>
|
<style windi:global windi:preflights:global windi:safelist:global>
|
||||||
</style>
|
</style>
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { $fetch } from 'ohmyfetch';
|
||||||
|
import env from '../lib/env';
|
||||||
|
|
||||||
|
interface TotalResponse {
|
||||||
|
message: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageServerLoad} */
|
||||||
|
export async function load() {
|
||||||
|
const response = await $fetch<TotalResponse>('total', {
|
||||||
|
method: 'GET',
|
||||||
|
baseURL: env.API_ENDPOINT,
|
||||||
|
parseResponse: JSON.parse,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: response.message,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,25 +1,13 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import { $fetch as omf } from 'ohmyfetch';
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import env from '$lib/env';
|
import env from '$lib/env';
|
||||||
import Codeblock from '../components/codeblock.svelte';
|
import Codeblock from '../components/codeblock.svelte';
|
||||||
|
|
||||||
interface TotalResponse {
|
/** @type {import('./$types').PageData} */
|
||||||
message: string;
|
export let data;
|
||||||
}
|
|
||||||
|
|
||||||
let total;
|
let total = data.total;
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
const totalJokes = async (): Promise<string> => {
|
|
||||||
const response = await omf<TotalResponse>(`${env.API_ENDPOINT}/total`);
|
|
||||||
return response.message;
|
|
||||||
};
|
|
||||||
|
|
||||||
total = await totalJokes();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -27,7 +15,7 @@
|
||||||
<meta name="title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
<meta name="title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
||||||
<meta name="twitter:title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
<meta name="twitter:title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
||||||
<meta property="og:title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
<meta property="og:title" content={$_('meta.title') + '-' + $_('meta.tagline')} />
|
||||||
<link rel="canonical" href="https://jokesbapak2.pages.dev/" />
|
<link rel="canonical" href="https://jokesbapak2.reinaldyrafli.com/" />
|
||||||
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
|
@ -43,17 +31,13 @@
|
||||||
<div class="max-w-xs mx-auto">
|
<div class="max-w-xs mx-auto">
|
||||||
<img src={env.API_ENDPOINT + `/today`} alt="Sample joke" class="py-6 shadow-2xl" />
|
<img src={env.API_ENDPOINT + `/today`} alt="Sample joke" class="py-6 shadow-2xl" />
|
||||||
</div>
|
</div>
|
||||||
<Codeblock>$ curl -XGET 'https://jokesbapak2.herokuapp.com/v1/'</Codeblock>
|
<Codeblock>$ curl -XGET 'https://jokesbapak2.reinaldyrafli.com/api/'</Codeblock>
|
||||||
<p class="text-sm text-center py-4 opacity-70 hover:opacity-100 transition duration-300 ease-in-out">
|
<p class="text-sm text-center py-4 opacity-70 hover:opacity-100 transition duration-300 ease-in-out">
|
||||||
{$_('home.more.1')} <span on:click={() => goto('/guide')}>{$_('navigation.guide')}</span>
|
{$_('home.more.1')}
|
||||||
{$_('home.more.2')} <span on:click={() => goto('/api')}>{$_('navigation.api')}</span>
|
<span class="hover:underline cursor-pointer" on:click={() => goto('/guide')}>{$_('navigation.guide')}</span>
|
||||||
|
{$_('home.more.2')}
|
||||||
|
<span class="hover:underline cursor-pointer" on:click={() => goto('/api')}>{$_('navigation.api')}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
|
||||||
span {
|
|
||||||
@apply 'hover:underline' cursor-pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1 @@
|
||||||
|
export const ssr = true;
|
|
@ -4,8 +4,8 @@
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import env from '$lib/env';
|
import env from '$lib/env';
|
||||||
import { $fetch as omf } from 'ohmyfetch';
|
import { $fetch as omf } from 'ohmyfetch';
|
||||||
import Codeblock from '../components/codeblock.svelte';
|
import Codeblock from '../../components/codeblock.svelte';
|
||||||
import Notice from '../components/notice.svelte';
|
import Notice from '../../components/notice.svelte';
|
||||||
|
|
||||||
interface TotalResponse {
|
interface TotalResponse {
|
||||||
message: string;
|
message: string;
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<meta name="title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
<meta name="title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
||||||
<meta name="twitter:title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
<meta name="twitter:title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
||||||
<meta property="og:title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
<meta property="og:title" content={$_('navigation.api') + '-' + $_('meta.title')} />
|
||||||
<link rel="canonical" href="https://jokesbapak2.pages.dev/api" />
|
<link rel="canonical" href="https://jokesbapak2.reinaldyrafli.com/api" />
|
||||||
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</Notice>
|
</Notice>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section class="api_page">
|
||||||
<h1>{$_('api.get.title')}</h1>
|
<h1>{$_('api.get.title')}</h1>
|
||||||
<h2>{$_('api.get.random.title')}</h2>
|
<h2>{$_('api.get.random.title')}</h2>
|
||||||
<p>{$_('api.get.random.body')}</p>
|
<p>{$_('api.get.random.body')}</p>
|
||||||
|
@ -66,12 +66,19 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-4xl font-bold py-4;
|
@apply text-4xl;
|
||||||
|
@apply font-bold;
|
||||||
|
@apply py-4;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
@apply text-2xl font-bold pt-6 pb-1;
|
@apply text-2xl;
|
||||||
|
@apply font-bold;
|
||||||
|
@apply pt-6;
|
||||||
|
@apply pb-1;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
@apply text-base opacity-80 py-2;
|
@apply text-base;
|
||||||
|
@apply opacity-80;
|
||||||
|
@apply py-2;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Codeblock from '../components/codeblock.svelte';
|
import Codeblock from '../../components/codeblock.svelte';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
// This page is meant to guide people on how to use the API.
|
// This page is meant to guide people on how to use the API.
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,13 +9,13 @@
|
||||||
<meta name="title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
<meta name="title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
||||||
<meta name="twitter:title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
<meta name="twitter:title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
||||||
<meta property="og:title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
<meta property="og:title" content={$_('navigation.guide') + '-' + $_('meta.title')} />
|
||||||
<link rel="canonical" href="https://jokesbapak2.pages.dev/guide" />
|
<link rel="canonical" href="https://jokesbapak2.reinaldyrafli.com/guide" />
|
||||||
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<section>
|
<section class="guide_page">
|
||||||
<h1>{$_('navigation.guide')}</h1>
|
<h1>{$_('navigation.guide')}</h1>
|
||||||
<p>
|
<p>
|
||||||
{$_('guide.introduction.1')}
|
{$_('guide.introduction.1')}
|
||||||
|
@ -23,38 +23,52 @@
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section class="guide_page">
|
||||||
<h2>{$_('guide.direct.1')} <code><img></code> {$_('guide.direct.2')}</h2>
|
<h2>{$_('guide.direct.1')} <code><img></code> {$_('guide.direct.2')}</h2>
|
||||||
<Codeblock><img src="https://jokesbapak2.herokuapp.com/v1/" /></Codeblock>
|
<Codeblock><img src="https://jokesbapak2.reinaldyrafli.com/api/" /></Codeblock>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section class="guide_page">
|
||||||
<h2>{$_('guide.fetch.1')}</h2>
|
<h2>{$_('guide.fetch.1')}</h2>
|
||||||
<p>{$_('guide.fetch.2')}</p>
|
<p>{$_('guide.fetch.2')}</p>
|
||||||
<Codeblock>
|
<Codeblock>
|
||||||
fetch("https://jokesbapak2.herokuapp.com/v1/")<br />
|
const response = await fetch("https://jokesbapak2.reinaldyrafli.com/api/");<br />
|
||||||
.then(response => response.text())<br />
|
|
||||||
.then(data => console.log(data))<br />
|
|
||||||
<br />
|
<br />
|
||||||
// {$_('guide.fetch.3')}<br />
|
if (!response.ok) {<br />
|
||||||
|
// {$_('guide.fetch.3')}<br />
|
||||||
|
}<br />
|
||||||
<br />
|
<br />
|
||||||
<img src="data:image/jpeg;base64, { data }" />
|
const blob = await response.blob();<br />
|
||||||
|
<br />
|
||||||
|
const objectURL = URL.createObjectURL(blob);<br />
|
||||||
|
<br />
|
||||||
|
<img src="{ objectURL }" />
|
||||||
</Codeblock>
|
</Codeblock>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
p {
|
p {
|
||||||
@apply text-base py-2 'lg:w-2/3';
|
@apply text-base;
|
||||||
|
@apply py-2;
|
||||||
|
@apply lg\:w-2\/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-4xl font-bold py-2;
|
@apply text-4xl;
|
||||||
|
@apply font-bold;
|
||||||
|
@apply py-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
@apply text-2xl font-bold py-2;
|
@apply text-2xl;
|
||||||
|
@apply font-bold;
|
||||||
|
@apply py-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
/* This would probably be an error if you installed WindiCSS extension on VSCode */
|
@apply hover\:underline;
|
||||||
@apply 'hover:underline' 'dark:text-dodger-200' text-dodger-700;
|
@apply dark\:text-dodger-200;
|
||||||
|
@apply text-dodger-700;
|
||||||
}
|
}
|
||||||
section {
|
section {
|
||||||
@apply pt-6;
|
@apply pt-6;
|
|
@ -7,18 +7,18 @@
|
||||||
<meta name="title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
<meta name="title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
||||||
<meta name="twitter:title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
<meta name="twitter:title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
||||||
<meta property="og:title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
<meta property="og:title" content={$_('navigation.why') + '-' + $_('meta.title')} />
|
||||||
<link rel="canonical" href="https://jokesbapak2.pages.dev/why" />
|
<link rel="canonical" href="https://jokesbapak2.reinaldyrafli.com/why" />
|
||||||
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta name="twitter:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
<meta property="og:description" content="Largest collection of Indonesian dad jokes as a consumable API" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<section>
|
<section class="why_page">
|
||||||
<h1 id="why-does-this-project-exists">{$_('why.exists.title')}</h1>
|
<h1 id="why-does-this-project-exists">{$_('why.exists.title')}</h1>
|
||||||
<p>{$_('why.exists.body.1')} {$_('why.exists.body.2')} {$_('why.exists.body.3')} {$_('why.exists.body.4')}</p>
|
<p>{$_('why.exists.body.1')} {$_('why.exists.body.2')} {$_('why.exists.body.3')} {$_('why.exists.body.4')}</p>
|
||||||
<p>{$_('why.exists.body.5')} {$_('why.exists.body.6')}</p>
|
<p>{$_('why.exists.body.5')} {$_('why.exists.body.6')}</p>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section class="why_page">
|
||||||
<h1 id="can-i-submit-my-dad-joke">{$_('why.submit.title')}</h1>
|
<h1 id="can-i-submit-my-dad-joke">{$_('why.submit.title')}</h1>
|
||||||
<p>
|
<p>
|
||||||
{$_('why.submit.body.1')}
|
{$_('why.submit.body.1')}
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
{$_('why.submit.body.6')}
|
{$_('why.submit.body.6')}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section class="why_page">
|
||||||
<h1 id="can-i-contribute">{$_('why.contribute.title')}</h1>
|
<h1 id="can-i-contribute">{$_('why.contribute.title')}</h1>
|
||||||
<p>
|
<p>
|
||||||
{$_('why.contribute.body.1')}
|
{$_('why.contribute.body.1')}
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
{$_('why.contribute.body.4')}
|
{$_('why.contribute.body.4')}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section class="why_page">
|
||||||
<h1 id="other-inquiries">{$_('why.inquiries.title')}</h1>
|
<h1 id="other-inquiries">{$_('why.inquiries.title')}</h1>
|
||||||
<p>
|
<p>
|
||||||
{$_('why.inquiries.body.1')}
|
{$_('why.inquiries.body.1')}
|
||||||
|
@ -48,15 +48,23 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
p {
|
p {
|
||||||
@apply text-base py-2 'lg:w-2/3';
|
@apply text-base;
|
||||||
|
@apply py-2;
|
||||||
|
@apply lg\:w-2\/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-3xl font-bold py-2;
|
@apply text-3xl;
|
||||||
|
@apply font-bold;
|
||||||
|
@apply py-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
/* This would probably be an error if you installed WindiCSS extension on VSCode */
|
@apply hover\:underline;
|
||||||
@apply 'hover:underline' 'dark:text-dodger-200' text-dodger-700;
|
@apply dark\:text-dodger-200;
|
||||||
|
@apply text-dodger-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
@apply pt-6;
|
@apply pt-6;
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import preprocess from 'svelte-preprocess';
|
import preprocess from 'svelte-preprocess';
|
||||||
import adapter from '@sveltejs/adapter-static';
|
import adapter from '@sveltejs/adapter-node';
|
||||||
import { windi } from 'svelte-windicss-preprocess';
|
import { windi } from 'svelte-windicss-preprocess';
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
@ -8,25 +8,26 @@ const config = {
|
||||||
// for more information about preprocessors
|
// for more information about preprocessors
|
||||||
preprocess: [
|
preprocess: [
|
||||||
windi({
|
windi({
|
||||||
configPath: './windi.config.js',
|
configPath: './windi.config.ts',
|
||||||
|
preflights: false,
|
||||||
}),
|
}),
|
||||||
preprocess({ postcss: false }),
|
preprocess({ postcss: false }),
|
||||||
],
|
],
|
||||||
|
|
||||||
kit: {
|
kit: {
|
||||||
// hydrate the <div id="svelte"> element in src/app.html
|
// hydrate the <div id="svelte"> element in src/app.html
|
||||||
target: '#svelte',
|
|
||||||
trailingSlash: 'never',
|
trailingSlash: 'never',
|
||||||
files: {
|
files: {
|
||||||
routes: './src/routes',
|
routes: './src/routes',
|
||||||
assets: './static',
|
assets: './static',
|
||||||
hooks: './src',
|
hooks: {
|
||||||
|
server: './src',
|
||||||
|
client: './src',
|
||||||
|
},
|
||||||
lib: './src/lib',
|
lib: './src/lib',
|
||||||
},
|
},
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
// default options are shown
|
out: 'dist',
|
||||||
pages: 'dist',
|
|
||||||
assets: 'dist',
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"extends": "./.svelte-kit/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"module": "es2020",
|
"module": "es2020",
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"$lib": ["src/lib"],
|
||||||
"$lib/*": ["src/lib/*"]
|
"$lib/*": ["src/lib/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [sveltekit()],
|
||||||
|
});
|
2114
client/yarn.lock
2114
client/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,35 @@
|
||||||
services:
|
services:
|
||||||
api:
|
api:
|
||||||
build: ./api/
|
build: ./api/
|
||||||
restart: always
|
|
||||||
env_file: ./api/.env
|
env_file: ./api/.env
|
||||||
ports:
|
ports:
|
||||||
- 5000:5000
|
- 5000:5000
|
||||||
|
healthcheck:
|
||||||
|
test: "curl -f http://api:5000/health/"
|
||||||
|
interval: 15s
|
||||||
|
timeout: 12s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 30s
|
||||||
|
max_attempts: 20
|
||||||
|
window: 60s
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 1GB
|
||||||
|
cpus: '1'
|
||||||
|
reservations:
|
||||||
|
memory: 50MB
|
||||||
|
cpus: '0.1'
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
bucket:
|
||||||
- cache
|
condition: service_healthy
|
||||||
# Uncomment these if you want to have it on
|
cache:
|
||||||
# volumes:
|
condition: service_healthy
|
||||||
# ./api:/app
|
|
||||||
|
|
||||||
client:
|
client:
|
||||||
build: ./client/
|
build: ./client/
|
||||||
|
@ -18,38 +37,33 @@ services:
|
||||||
env_file: ./client/.env
|
env_file: ./client/.env
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
depends_on:
|
|
||||||
- api
|
|
||||||
# Uncomment these if you want to have it on
|
|
||||||
# volumes:
|
|
||||||
# ./client:/app
|
|
||||||
|
|
||||||
db:
|
|
||||||
build: ./database/postgres/
|
|
||||||
command: >
|
|
||||||
-c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: password
|
|
||||||
POSTGRES_DB: jokesbapak2
|
|
||||||
PGDATA: /data/postgres
|
|
||||||
# I got this key from somewhere. It works when you run it locally.
|
|
||||||
POSTGRES_SSL_CA_CERT: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURjekNDQWx1Z0F3SUJBZ0lVR3lDaElvR3g0
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: pg_isready -U postgres
|
test: "curl -f http://client:3000/"
|
||||||
interval: 10s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 12s
|
||||||
retries: 5
|
retries: 10
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
volumes:
|
deploy:
|
||||||
- ./database/postgres/data:/data/postgres
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 30s
|
||||||
|
max_attempts: 20
|
||||||
|
window: 60s
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 500MB
|
||||||
|
cpus: '1'
|
||||||
|
reservations:
|
||||||
|
memory: 50MB
|
||||||
|
cpus: '0.1'
|
||||||
|
depends_on:
|
||||||
|
api:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
image: redis:6.2.4-alpine
|
image: redis:6.2.7-alpine
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
ports:
|
||||||
- 6379:6379
|
- 6379:6379
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
@ -58,12 +72,27 @@ services:
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 30s
|
||||||
|
max_attempts: 20
|
||||||
|
window: 60s
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 2GB
|
||||||
|
cpus: '1'
|
||||||
|
reservations:
|
||||||
|
memory: 100MB
|
||||||
|
cpus: '0.1'
|
||||||
volumes:
|
volumes:
|
||||||
- ./database/redis/etc:/usr/local/etc/redis
|
- ./data/redis/etc:/usr/local/etc/redis
|
||||||
- ./database/redis/data:/data
|
- ./data/redis/data:/data
|
||||||
|
|
||||||
bucket:
|
bucket:
|
||||||
image: quay.io/minio/minio:RELEASE.2022-02-05T04-40-59Z
|
image: quay.io/minio/minio:RELEASE.2022-09-07T22-25-02Z
|
||||||
command: server /data --console-address ":9001"
|
command: server /data --console-address ":9001"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
|
@ -80,28 +109,20 @@ services:
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 60s
|
start_period: 60s
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 30s
|
||||||
|
max_attempts: 20
|
||||||
|
window: 60s
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4GB
|
||||||
|
cpus: '2'
|
||||||
|
reservations:
|
||||||
|
memory: 50MB
|
||||||
|
cpus: '0.1'
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/minio:/data
|
- ./data/minio:/data
|
||||||
|
|
||||||
cache-admin:
|
|
||||||
image: rediscommander/redis-commander:latest
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
REDIS_PORT: 6379
|
|
||||||
REDIS_HOST: redis
|
|
||||||
ports:
|
|
||||||
- 2084:8081
|
|
||||||
depends_on:
|
|
||||||
- cache
|
|
||||||
|
|
||||||
db-admin:
|
|
||||||
image: sosedoff/pgweb:0.11.8
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- 2086:8081
|
|
||||||
links:
|
|
||||||
- postgres:postgres
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: postgres://postgres:password@db/jokesbapak2
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
|
|
Loading…
Reference in New Issue