added PWA
This commit is contained in:
parent
07e52d26ce
commit
2fa3ec2f95
21 changed files with 2682 additions and 42365 deletions
112
components/PixiApp.tsx
Normal file
112
components/PixiApp.tsx
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
"use client"
|
||||||
|
import { Container, Sprite, Stage, Text, useTick } from "@pixi/react"
|
||||||
|
import { Application } from "pixi.js"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
const RotatingBunny = (props: any) => {
|
||||||
|
const [rotation, setRotation] = useState(0)
|
||||||
|
|
||||||
|
useTick((delta) => delta && setRotation(rotation + 0.0 * delta))
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Clean up event listener
|
||||||
|
return () => {}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sprite
|
||||||
|
image="https://s3-us-west-2.amazonaws.com/s.cdpn.io/693612/IaUrttj.png"
|
||||||
|
x={props.x}
|
||||||
|
y={props.y}
|
||||||
|
anchor={0.5}
|
||||||
|
scale={props.scale}
|
||||||
|
rotation={rotation}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PixiApp = (props: any) => {
|
||||||
|
// Initialize position state
|
||||||
|
const [position, setPosition] = useState({ x: 0, y: 0 })
|
||||||
|
|
||||||
|
const move = (direction: string | undefined) => {
|
||||||
|
switch (direction) {
|
||||||
|
case "left":
|
||||||
|
// Move left
|
||||||
|
setPosition((prevPosition) => ({
|
||||||
|
...prevPosition,
|
||||||
|
x: prevPosition.x - 50,
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
case "right":
|
||||||
|
// Move right
|
||||||
|
setPosition((prevPosition) => ({
|
||||||
|
...prevPosition,
|
||||||
|
x: prevPosition.x + 50,
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
case "up":
|
||||||
|
// Move left
|
||||||
|
setPosition((prevPosition) => ({
|
||||||
|
...prevPosition,
|
||||||
|
y: prevPosition.y - 50,
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
case "down":
|
||||||
|
// Move right
|
||||||
|
setPosition((prevPosition) => ({
|
||||||
|
...prevPosition,
|
||||||
|
y: prevPosition.y + 50,
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [apptext, setext] = useState("hello")
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Start moving the circle according to the directions array
|
||||||
|
|
||||||
|
console.log("rerun")
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
function processDirections() {
|
||||||
|
// To keep track of the current direction
|
||||||
|
|
||||||
|
if (index < props.directions.length) {
|
||||||
|
move(props.directions[index])
|
||||||
|
index++
|
||||||
|
setTimeout(processDirections, 500) // Adjust delay as needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processDirections()
|
||||||
|
|
||||||
|
// Clean up event listener
|
||||||
|
return () => {}
|
||||||
|
}, [props.directions])
|
||||||
|
|
||||||
|
//reset
|
||||||
|
const originalPosition = { x: props.width / 2, y: props.height - 30 }
|
||||||
|
|
||||||
|
// State to hold the current position of the sprite
|
||||||
|
const [spritePosition, setSpritePosition] = useState(originalPosition)
|
||||||
|
|
||||||
|
// Function to reset the position of the sprite to the original position
|
||||||
|
const resetSpritePosition = () => {
|
||||||
|
setSpritePosition(originalPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stage width={props.width} height={props.height} options={{ backgroundColor: "purple" }}>
|
||||||
|
<Container position={[spritePosition.x, spritePosition.y]}>
|
||||||
|
<RotatingBunny scale={1.5} x={position.x} y={position.y} />
|
||||||
|
</Container>
|
||||||
|
</Stage>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PixiApp
|
||||||
|
|
@ -26,9 +26,9 @@ export default function MenuItem(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card onClick={handleOnClick}>
|
<Card onClick={handleOnClick} h={["50vh"]}>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Image src={props.image_url} alt={props.image_desc} borderRadius="lg" />
|
<Image src={props.image_url} alt={props.image_desc} borderRadius="lg" margin={"auto"} h="50%" w="100%" />
|
||||||
<Stack mt="6" spacing="3">
|
<Stack mt="6" spacing="3">
|
||||||
<Heading size="md">{props.title}</Heading>
|
<Heading size="md">{props.title}</Heading>
|
||||||
<Text>{props.summary}</Text>
|
<Text>{props.summary}</Text>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import useSWR from "swr"
|
||||||
const fetcher = (...args) => fetch(...args).then((res) => res.json())
|
const fetcher = (...args) => fetch(...args).then((res) => res.json())
|
||||||
|
|
||||||
export function menuitemfetcher(url) {
|
export function menuitemfetcher(url) {
|
||||||
const { data, error, isLoading } = useSWR("https://jsonplaceholder.typicode.com/posts", fetcher)
|
const { data, error, isLoading } = useSWR("http://192.168.178.20:3001/data", fetcher)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: data,
|
data: data,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export default async function middleware(req, res) {
|
||||||
// Extract token from request headers or cookies or wherever it's stored
|
// Extract token from request headers or cookies or wherever it's stored
|
||||||
const token = req.cookies.get("token")
|
const token = req.cookies.get("token")
|
||||||
|
|
||||||
|
|
||||||
if (!token || token.value == "") {
|
if (!token || token.value == "") {
|
||||||
if (req.url == "http://localhost:3000/login") {
|
if (req.url == "http://localhost:3000/login") {
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -69,5 +70,5 @@ export default async function middleware(req, res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
matcher: ["/((?!api|_next/static|_next/image|favicon.ico|sw.js|manifest.json|test.html|icon*|images/*).*)"],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,28 @@
|
||||||
// next.config.js
|
// // next.config.js
|
||||||
module.exports = {
|
// module.exports = {
|
||||||
// ... rest of the configuration.
|
// // ... rest of the configuration.
|
||||||
|
// output: "standalone",
|
||||||
|
// async redirects() {
|
||||||
|
// return [
|
||||||
|
// {
|
||||||
|
// source: "/",
|
||||||
|
// destination: "/home",
|
||||||
|
// permanent: true,
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
|
||||||
|
const withPWA = require("next-pwa")({
|
||||||
|
dest: "public",
|
||||||
|
swSrc: "public/service-worker.js",
|
||||||
|
disable: process.env.NODE_ENV === "development",
|
||||||
|
register: true,
|
||||||
|
skipWaiting: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = withPWA({
|
||||||
|
reactStrictMode: true,
|
||||||
|
// next.js config
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
async redirects() {
|
})
|
||||||
return [
|
|
||||||
{
|
|
||||||
source: "/",
|
|
||||||
destination: "/home",
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
||||||
39577
package-lock.json
generated
39577
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -30,6 +30,7 @@
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@headlessui/react": "^1.7.18",
|
"@headlessui/react": "^1.7.18",
|
||||||
"@next/bundle-analyzer": "^14.0.3",
|
"@next/bundle-analyzer": "^14.0.3",
|
||||||
|
"@pixi/react": "^7.1.1",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
|
|
@ -66,6 +67,8 @@
|
||||||
"next": "^14.0.3",
|
"next": "^14.0.3",
|
||||||
"next-auth": "^4.24.5",
|
"next-auth": "^4.24.5",
|
||||||
"next-compose-plugins": "^2.2.1",
|
"next-compose-plugins": "^2.2.1",
|
||||||
|
"next-pwa": "^5.6.0",
|
||||||
|
"pixi.js": "^7.4.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.10.0",
|
"react-bootstrap": "^2.10.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { initializeApp } from "firebase/app"
|
import { initializeApp } from "firebase/app"
|
||||||
|
import Head from 'next/head'
|
||||||
import React, { useContext, useEffect, useState } from "react"
|
import React, { useContext, useEffect, useState } from "react"
|
||||||
|
|
||||||
//Auth imports
|
//Auth imports
|
||||||
|
|
@ -61,15 +62,28 @@ function MyApp({ Component, pageProps }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////
|
/////////
|
||||||
|
const [registration, setRegistration] = useState(null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* useEffect has been uesd to take actions on the first rendering
|
* useEffect has been uesd to take actions on the first rendering
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const app = initializeApp(firebaseConfig)
|
// const app = initializeApp(firebaseConfig)
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
console.log("1st check", firebaseConfig)
|
// console.log("1st check", firebaseConfig)
|
||||||
|
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
window.addEventListener("load", function () {
|
||||||
|
navigator.serviceWorker.register("/sw.js").then(
|
||||||
|
function (registration) {
|
||||||
|
setRegistration(registration)
|
||||||
|
console.log("Service Worker registration successful with scope: ", registration.scope)
|
||||||
|
},
|
||||||
|
function (err) {}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setLoaded(true)
|
setLoaded(true)
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +92,6 @@ function MyApp({ Component, pageProps }) {
|
||||||
///// Manual test with console
|
///// Manual test with console
|
||||||
const getLayout = Component.getLayout ?? ((page) => page)
|
const getLayout = Component.getLayout ?? ((page) => page)
|
||||||
return (
|
return (
|
||||||
<SSRProvider>
|
|
||||||
<ChakraProvider theme={customTheme}>
|
<ChakraProvider theme={customTheme}>
|
||||||
<AuthContext.Provider
|
<AuthContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|
@ -95,7 +108,6 @@ function MyApp({ Component, pageProps }) {
|
||||||
{getLayout(<Component {...pageProps} />)}
|
{getLayout(<Component {...pageProps} />)}
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
</ChakraProvider>
|
</ChakraProvider>
|
||||||
</SSRProvider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
25
pages/_document.js
Normal file
25
pages/_document.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Head, Html, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html>
|
||||||
|
<Head>
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<link rel="apple-touch-icon" href="/icon.png"></link>
|
||||||
|
<meta name="theme-color" content="#fff" />
|
||||||
|
<meta name='application-name' content={"pwa test"} />
|
||||||
|
<meta name='apple-mobile-web-app-capable' content='yes' />
|
||||||
|
<meta name='apple-mobile-web-app-status-bar-style' content='default' />
|
||||||
|
<meta name='apple-mobile-web-app-title' content={"pwa test"} />
|
||||||
|
<meta name='description' content={"fuck me whattttt"} />
|
||||||
|
<meta name='format-detection' content='telephone=no' />
|
||||||
|
<meta name='mobile-web-app-capable' content='yes' />
|
||||||
|
<meta name='theme-color' content='#FFFFFF' />
|
||||||
|
</Head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -12,19 +12,16 @@ export default async function handler(req, res) {
|
||||||
//fetch data from postgres database where we store password as hash
|
//fetch data from postgres database where we store password as hash
|
||||||
|
|
||||||
// Here, for demonstration, let's assume a hardcoded user
|
// Here, for demonstration, let's assume a hardcoded user
|
||||||
const user = {
|
const response = await fetch(`http://localhost:3001/user`)
|
||||||
id: 1,
|
const user_data = await response.json()
|
||||||
email: "user@example.com",
|
|
||||||
passwordHash: "$2a$10$Zy/TYg6WwOOctCQ6e/KOXebvH3AliSDjdopPxrIUWELVJBf/KE.iq", // hashed password: "password123"
|
|
||||||
}
|
|
||||||
|
|
||||||
const isValid = await verifyPassword(password, user.passwordHash)
|
const isValid = await verifyPassword(password, user_data.password)
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
return res.status(401).json({ message: "Invalid credentials" })
|
return res.status(401).json({ message: "Invalid credentials" })
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = await createTokens(user.id)
|
const token = await createTokens(user_data.id)
|
||||||
|
|
||||||
res.setHeader("Set-Cookie", [
|
res.setHeader("Set-Cookie", [
|
||||||
`token=${token.accessToken}; Path=/; HttpOnly`,
|
`token=${token.accessToken}; Path=/; HttpOnly`,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
import React, { useContext, useEffect, useState } from "react"
|
import React, { useContext, useEffect, useState } from "react"
|
||||||
import MyButton from "../components/button"
|
|
||||||
import Header from "../components/headbar"
|
import Header from "../components/headbar"
|
||||||
import Logincomponent from "../components/logincomponent"
|
import Logincomponent from "../components/logincomponent"
|
||||||
import Signupcomponent from "../components/signupcomponent"
|
import Signupcomponent from "../components/signupcomponent"
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import * as me from "melonjs"
|
|
||||||
import { useRouter } from "next/router"
|
|
||||||
import React, { useContext, useEffect, useState } from "react"
|
|
||||||
|
|
||||||
import Layout from "../../components/layout"
|
|
||||||
|
|
||||||
export default function Page(props) {
|
|
||||||
const [isloaded, setIsLoaded] = React.useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isloaded) {
|
|
||||||
console.log("isloaded called")
|
|
||||||
|
|
||||||
setIsLoaded(true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
return <></>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**This place should be used to get any information from the server side
|
|
||||||
* example : we need to get the session token
|
|
||||||
* or any thing related to the page */
|
|
||||||
|
|
||||||
Page.getLayout = function getLayout(page) {
|
|
||||||
return <Layout>{page}</Layout>
|
|
||||||
}
|
|
||||||
105
pages/learningpage/[page].tsx
Normal file
105
pages/learningpage/[page].tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
"use client"
|
||||||
|
import { Box, Editable, Flex, FormLabel, Input, Spacer } from "@chakra-ui/react"
|
||||||
|
import { Container, Sprite, Stage, Text } from "@pixi/react"
|
||||||
|
import dynamic from "next/dynamic"
|
||||||
|
import { useRouter } from "next/router"
|
||||||
|
|
||||||
|
import React, { useContext, useEffect, useMemo, useReducer, useState } from "react"
|
||||||
|
import Layout from "../../components/layout"
|
||||||
|
// import PixiApp from "../../components/PixiApp"
|
||||||
|
|
||||||
|
const PixiApp = dynamic(() => import("../../components/PixiApp"), { ssr: false })
|
||||||
|
|
||||||
|
export default function Page(props: any) {
|
||||||
|
const [isloaded, setIsLoaded] = React.useState(false)
|
||||||
|
|
||||||
|
const [name, setName] = React.useState("app")
|
||||||
|
const [scale, setScale] = React.useState(0.5)
|
||||||
|
const [directions, setDirections] = React.useState(["up", "down", "up", "down", "up", "down", "up", "down"])
|
||||||
|
|
||||||
|
const [screenSize, setScreenSize] = useState({
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Function to update the screen size
|
||||||
|
const updateScreenSize = () => {
|
||||||
|
setScreenSize({
|
||||||
|
width: window.innerWidth,
|
||||||
|
height: window.innerHeight,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update screen size upon mount to capture the initial values
|
||||||
|
updateScreenSize()
|
||||||
|
|
||||||
|
// Add event listener for resize events
|
||||||
|
window.addEventListener("resize", updateScreenSize)
|
||||||
|
console.log("screenSize", screenSize)
|
||||||
|
return () => window.removeEventListener("resize", updateScreenSize)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
function handleClick() {}
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const handleupdate = () => {
|
||||||
|
setIsLoaded(!isloaded)
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log("Asdasdasd");
|
||||||
|
function cal_screen_size() {}
|
||||||
|
|
||||||
|
function convertStringToArray(rangeString: string) {
|
||||||
|
var range: string[] = rangeString.split("-")
|
||||||
|
|
||||||
|
return range
|
||||||
|
}
|
||||||
|
|
||||||
|
const dire = ["up", "right", "down", "right", "left"]
|
||||||
|
|
||||||
|
const direstr = dire.join("-")
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box h={30} backgroundColor={"pink"}></Box>
|
||||||
|
<Flex direction={"row-reverse"} alignItems="center">
|
||||||
|
<Box flexBasis={0} flexGrow={1} alignContent={"right"}>
|
||||||
|
<PixiApp
|
||||||
|
n={name}
|
||||||
|
scale={scale}
|
||||||
|
width={screenSize.width / 2}
|
||||||
|
height={screenSize.height - 30}
|
||||||
|
directions={directions}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box flexBasis={0} flexGrow={1} scrollBehavior={"smooth"}>
|
||||||
|
<div style={{ height: screenSize.height - 30, width: screenSize.width / 2, overflowY: "scroll" }}>
|
||||||
|
<Input
|
||||||
|
onChange={(e) => {
|
||||||
|
setName(e.target.value)
|
||||||
|
}}
|
||||||
|
value={name}
|
||||||
|
placeholder="name"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setDirections(convertStringToArray(name))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
change
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**This place should be used to get any information from the server side
|
||||||
|
* example : we need to get the session token
|
||||||
|
* or any thing related to the page */
|
||||||
|
|
||||||
|
Page.getLayout = function getLayout(page: any) {
|
||||||
|
return page
|
||||||
|
}
|
||||||
|
|
@ -26,8 +26,8 @@ function Menubox(props) {
|
||||||
id={item.id}
|
id={item.id}
|
||||||
itemid={item.userId}
|
itemid={item.userId}
|
||||||
title={item.title}
|
title={item.title}
|
||||||
summary={item.body}
|
summary={item.summary}
|
||||||
image_url="https://example.com/image1.jpg"
|
image_url={"https://i.etsystatic.com/41743066/r/il/51b87b/5227514595/il_1140xN.5227514595_gkk6.jpg"}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@
|
||||||
{
|
{
|
||||||
"src": "/icon-192x192.png",
|
"src": "/icon-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png"
|
||||||
"purpose": "any maskable"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/icon-384x384.png",
|
"src": "/icon-384x384.png",
|
||||||
|
|
@ -19,12 +18,25 @@
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"gcm_sender_id": "1084271040061",
|
|
||||||
"theme_color": "#007",
|
"theme_color": "#007",
|
||||||
"background_color": "#007",
|
"background_color": "#007",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"orientation": "portrait"
|
"orientation": "portrait",
|
||||||
|
"screenshots": [
|
||||||
|
{
|
||||||
|
"src": "/images/SMOR-512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x495",
|
||||||
|
"form_factor": "narrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/images/SMOR-512.png",
|
||||||
|
"type": "image/jpg",
|
||||||
|
"sizes": "512x495",
|
||||||
|
"form_factor": "wide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
182
public/service-worker.js
Normal file
182
public/service-worker.js
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
import { skipWaiting, clientsClaim } from 'workbox-core';
|
||||||
|
import { ExpirationPlugin } from 'workbox-expiration';
|
||||||
|
import { NetworkOnly, NetworkFirst, CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
|
||||||
|
import { registerRoute, setDefaultHandler, setCatchHandler } from 'workbox-routing';
|
||||||
|
import { matchPrecache, precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching';
|
||||||
|
|
||||||
|
skipWaiting();
|
||||||
|
clientsClaim();
|
||||||
|
|
||||||
|
// must include following lines when using inject manifest module from workbox
|
||||||
|
// https://developers.google.com/web/tools/workbox/guides/precache-files/workbox-build#add_an_injection_point
|
||||||
|
const WB_MANIFEST = self.__WB_MANIFEST;
|
||||||
|
// Precache fallback route and image
|
||||||
|
WB_MANIFEST.push({
|
||||||
|
url: '/fallback',
|
||||||
|
revision: '1234567890',
|
||||||
|
});
|
||||||
|
precacheAndRoute(WB_MANIFEST);
|
||||||
|
|
||||||
|
cleanupOutdatedCaches();
|
||||||
|
registerRoute(
|
||||||
|
'/',
|
||||||
|
new NetworkFirst({
|
||||||
|
cacheName: 'start-url',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 1,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
|
||||||
|
new CacheFirst({
|
||||||
|
cacheName: 'google-fonts',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 4,
|
||||||
|
maxAgeSeconds: 31536e3,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
|
||||||
|
new StaleWhileRevalidate({
|
||||||
|
cacheName: 'static-font-assets',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 4,
|
||||||
|
maxAgeSeconds: 604800,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
// disable image cache, so we could observe the placeholder image when offline
|
||||||
|
registerRoute(
|
||||||
|
/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
|
||||||
|
new NetworkOnly({
|
||||||
|
cacheName: 'static-image-assets',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 64,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/\.(?:js)$/i,
|
||||||
|
new StaleWhileRevalidate({
|
||||||
|
cacheName: 'static-js-assets',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 32,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/\.(?:css|less)$/i,
|
||||||
|
new StaleWhileRevalidate({
|
||||||
|
cacheName: 'static-style-assets',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 32,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/\.(?:json|xml|csv)$/i,
|
||||||
|
new NetworkFirst({
|
||||||
|
cacheName: 'static-data-assets',
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 32,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/\/api\/.*$/i,
|
||||||
|
new NetworkFirst({
|
||||||
|
cacheName: 'apis',
|
||||||
|
networkTimeoutSeconds: 10,
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 16,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
registerRoute(
|
||||||
|
/.*/i,
|
||||||
|
new NetworkFirst({
|
||||||
|
cacheName: 'others',
|
||||||
|
networkTimeoutSeconds: 10,
|
||||||
|
plugins: [
|
||||||
|
new ExpirationPlugin({
|
||||||
|
maxEntries: 32,
|
||||||
|
maxAgeSeconds: 86400,
|
||||||
|
purgeOnQuotaError: !0,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
'GET'
|
||||||
|
);
|
||||||
|
|
||||||
|
// following lines gives you control of the offline fallback strategies
|
||||||
|
// https://developers.google.com/web/tools/workbox/guides/advanced-recipes#comprehensive_fallbacks
|
||||||
|
|
||||||
|
// Use a stale-while-revalidate strategy for all other requests.
|
||||||
|
setDefaultHandler(new StaleWhileRevalidate());
|
||||||
|
|
||||||
|
// This "catch" handler is triggered when any of the other routes fail to
|
||||||
|
// generate a response.
|
||||||
|
setCatchHandler(({ event }) => {
|
||||||
|
// The FALLBACK_URL entries must be added to the cache ahead of time, either
|
||||||
|
// via runtime or precaching. If they are precached, then call
|
||||||
|
// `matchPrecache(FALLBACK_URL)` (from the `workbox-precaching` package)
|
||||||
|
// to get the response from the correct cache.
|
||||||
|
//
|
||||||
|
// Use event, request, and url to figure out how to respond.
|
||||||
|
// One approach would be to use request.destination, see
|
||||||
|
// https://medium.com/dev-channel/service-worker-caching-strategies-based-on-request-types-57411dd7652c
|
||||||
|
switch (event.request.destination) {
|
||||||
|
case 'document':
|
||||||
|
// If using precached URLs:
|
||||||
|
return matchPrecache('/fallback');
|
||||||
|
case 'image':
|
||||||
|
case 'font':
|
||||||
|
// If using precached URLs:
|
||||||
|
// return matchPrecache(FALLBACK_FONT_URL);
|
||||||
|
// return caches.match('/static/fonts/fallback.otf')
|
||||||
|
// break
|
||||||
|
default:
|
||||||
|
// If we don't have a fallback, just return an error response.
|
||||||
|
return Response.error();
|
||||||
|
}
|
||||||
|
});
|
||||||
269
public/sw.js
269
public/sw.js
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
262
testdata/user.json
vendored
Normal file
262
testdata/user.json
vendored
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
{
|
||||||
|
"user": {
|
||||||
|
"id": "1",
|
||||||
|
"email": "user@example.com",
|
||||||
|
"password": "$2a$10$Zy/TYg6WwOOctCQ6e/KOXebvH3AliSDjdopPxrIUWELVJBf/KE.iq"
|
||||||
|
},
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 1",
|
||||||
|
"image_url": "https://example.com/image1.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 2",
|
||||||
|
"image_url": "https://example.com/image2.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 3",
|
||||||
|
"image_url": "https://example.com/image3.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 4",
|
||||||
|
"image_url": "https://example.com/image4.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 5",
|
||||||
|
"image_url": "https://example.com/image5.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 6",
|
||||||
|
"image_url": "https://example.com/image6.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 7",
|
||||||
|
"image_url": "https://example.com/image7.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 8",
|
||||||
|
"image_url": "https://example.com/image8.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 9",
|
||||||
|
"image_url": "https://example.com/image9.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 10",
|
||||||
|
"image_url": "https://example.com/image10.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 11",
|
||||||
|
"image_url": "https://example.com/image11.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 12",
|
||||||
|
"image_url": "https://example.com/image12.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 13",
|
||||||
|
"image_url": "https://example.com/image13.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 14",
|
||||||
|
"image_url": "https://example.com/image14.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 15",
|
||||||
|
"image_url": "https://example.com/image15.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 16",
|
||||||
|
"image_url": "https://example.com/image16.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 17",
|
||||||
|
"image_url": "https://example.com/image17.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 18",
|
||||||
|
"image_url": "https://example.com/image18.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 19",
|
||||||
|
"image_url": "https://example.com/image19.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 20",
|
||||||
|
"image_url": "https://example.com/image20.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 21",
|
||||||
|
"image_url": "https://example.com/image21.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 22",
|
||||||
|
"image_url": "https://example.com/image22.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 23",
|
||||||
|
"image_url": "https://example.com/image23.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 24",
|
||||||
|
"image_url": "https://example.com/image24.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 25",
|
||||||
|
"image_url": "https://example.com/image25.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 26",
|
||||||
|
"image_url": "https://example.com/image26.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 27",
|
||||||
|
"image_url": "https://example.com/image27.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 28",
|
||||||
|
"image_url": "https://example.com/image28.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 29",
|
||||||
|
"image_url": "https://example.com/image29.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 30",
|
||||||
|
"image_url": "https://example.com/image30.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 31",
|
||||||
|
"image_url": "https://example.com/image31.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 32",
|
||||||
|
"image_url": "https://example.com/image32.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 33",
|
||||||
|
"image_url": "https://example.com/image33.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 34",
|
||||||
|
"image_url": "https://example.com/image34.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 35",
|
||||||
|
"image_url": "https://example.com/image35.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 36",
|
||||||
|
"image_url": "https://example.com/image36.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 37",
|
||||||
|
"image_url": "https://example.com/image37.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 38",
|
||||||
|
"image_url": "https://example.com/image38.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 39",
|
||||||
|
"image_url": "https://example.com/image39.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 40",
|
||||||
|
"image_url": "https://example.com/image40.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 41",
|
||||||
|
"image_url": "https://example.com/image41.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 42",
|
||||||
|
"image_url": "https://example.com/image42.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 43",
|
||||||
|
"image_url": "https://example.com/image43.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 44",
|
||||||
|
"image_url": "https://example.com/image44.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 45",
|
||||||
|
"image_url": "https://example.com/image45.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 46",
|
||||||
|
"image_url": "https://example.com/image46.jpg",
|
||||||
|
"summary": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 47",
|
||||||
|
"image_url": "https://example.com/image47.jpg",
|
||||||
|
"summary": "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 48",
|
||||||
|
"image_url": "https://example.com/image48.jpg",
|
||||||
|
"summary": "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 49",
|
||||||
|
"image_url": "https://example.com/image49.jpg",
|
||||||
|
"summary": "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Lorem Ipsum 50",
|
||||||
|
"image_url": "https://example.com/image50.jpg",
|
||||||
|
"summary": "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ export const issueAccessToken = async (userId) => {
|
||||||
purpose: "access", // Indicate the purpose of this token
|
purpose: "access", // Indicate the purpose of this token
|
||||||
}
|
}
|
||||||
|
|
||||||
const accessToken = await generateToken(accessTokenPayload, "1m") // 15 minutes expiry
|
const accessToken = await generateToken(accessTokenPayload, "15m") // 15 minutes expiry
|
||||||
|
|
||||||
return accessToken
|
return accessToken
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue