diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..6aff804 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node +{ + "name": "Node.js & TypeScript", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "yarn install", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + "remoteUser": "root" +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5d4b3d1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +pgdata +.env +.devcontainer +docker-compose.yml +Dockerfile +README.md diff --git a/.env.sample b/.env.sample index ea08bfa..4bf7c56 100644 --- a/.env.sample +++ b/.env.sample @@ -6,6 +6,7 @@ NEXTAUTH_URL=http://localhost:3000 PAGINATION_TAKE_COUNT= STORAGE_FOLDER= +AUTOSCROLL_TIMEOUT= # AWS S3 Settings SPACES_KEY= @@ -25,4 +26,7 @@ PRICE_ID= NEXT_PUBLIC_TRIAL_PERIOD_DAYS= NEXT_PUBLIC_STRIPE_BILLING_PORTAL_URL= BASE_URL=http://localhost:3000 -NEXT_PUBLIC_PRICING= \ No newline at end of file +NEXT_PUBLIC_PRICING= + +# Docker postgres settings +POSTGRES_PASSWORD= diff --git a/.gitignore b/.gitignore index 3cec5f6..77956c8 100644 --- a/.gitignore +++ b/.gitignore @@ -36,9 +36,14 @@ next-env.d.ts # generated files and folders /data +.idea +prisma/dev.db # tests /tests /test-results/ /playwright-report/ /playwright/.cache/ + +# docker +pgdata \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0a875e5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# playwright doesnt support debian image +FROM ubuntu:focal + +RUN apt-get update && apt-get install wget xz-utils -y + +RUN mkdir /data + +WORKDIR /data + +RUN wget https://nodejs.org/dist/v20.5.0/node-v20.5.0-linux-x64.tar.xz -O nodejs.tar.xz \ + && mkdir /opt/nodejs \ + && tar -xf nodejs.tar.xz --strip-components 1 -C /opt/nodejs \ + && rm nodejs.tar.xz +ENV PATH="$PATH:/opt/nodejs/bin" +RUN npm install -g yarn + +COPY ./package.json ./yarn.lock ./playwright.config.ts ./ + +RUN yarn +RUN npx playwright install-deps + +COPY . . + +RUN yarn prisma generate +RUN yarn build + +CMD yarn prisma migrate deploy && yarn start diff --git a/README.md b/README.md index e1d53cb..e1bf05c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@
Import/Export Data
+ +Dashboard
+ +Dashboard
+ -- All Links -
+ +Links
+ -- All Collections + +
+ Collections
diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..81457f5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.5" +services: + postgres: + image: postgres + env_file: .env + restart: always + volumes: + - ./pgdata:/var/lib/postgresql/data + linkwarden: + env_file: .env + platform: linux/x86_64 + environment: + - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres + restart: always + build: . + ports: + - 3000:3000 + volumes: + - ./data:/data/data + depends_on: + - postgres diff --git a/hooks/useInitialData.tsx b/hooks/useInitialData.tsx index b79d5a8..a0bd1c4 100644 --- a/hooks/useInitialData.tsx +++ b/hooks/useInitialData.tsx @@ -13,7 +13,10 @@ export default function useInitialData() { const { setAccount } = useAccountStore(); useEffect(() => { - if (status === "authenticated" && data.user.isSubscriber) { + if ( + status === "authenticated" && + (!process.env.NEXT_PUBLIC_STRIPE_IS_ACTIVE || data.user.isSubscriber) + ) { setCollections(); setTags(); // setLinks(); diff --git a/lib/api/archive.ts b/lib/api/archive.ts index 24c3ff6..1163f26 100644 --- a/lib/api/archive.ts +++ b/lib/api/archive.ts @@ -2,11 +2,7 @@ import { Page, chromium, devices } from "playwright"; import { prisma } from "@/lib/api/db"; import createFile from "@/lib/api/storage/createFile"; -export default async function archive( - url: string, - collectionId: number, - linkId: number -) { +export default async function archive(linkId: number, url: string) { const browser = await chromium.launch(); const context = await browser.newContext(devices["Desktop Chrome"]); const page = await context.newPage(); @@ -14,7 +10,10 @@ export default async function archive( try { await page.goto(url, { waitUntil: "domcontentloaded" }); - await autoScroll(page); + await page.evaluate( + autoScroll, + Number(process.env.AUTOSCROLL_TIMEOUT) || 30 + ); const linkExists = await prisma.link.findUnique({ where: { @@ -35,12 +34,12 @@ export default async function archive( createFile({ data: screenshot, - filePath: `archives/${collectionId}/${linkId}.png`, + filePath: `archives/${linkExists.collectionId}/${linkId}.png`, }); createFile({ data: pdf, - filePath: `archives/${collectionId}/${linkId}.pdf`, + filePath: `archives/${linkExists.collectionId}/${linkId}.pdf`, }); } @@ -51,29 +50,31 @@ export default async function archive( } } -const autoScroll = async (page: Page) => { - await page.evaluate(async () => { - const timeoutPromise = new Promise
- If you didn't recieve anything, go to the{" "}
+ If you didn't receive anything, go to the{" "}
Password Recovery
{" "}
diff --git a/pages/register.tsx b/pages/register.tsx
index d02ddbc..d2236ab 100644
--- a/pages/register.tsx
+++ b/pages/register.tsx
@@ -3,7 +3,7 @@ import { useState } from "react";
import { toast } from "react-hot-toast";
import SubmitButton from "@/components/SubmitButton";
import { signIn } from "next-auth/react";
-import Image from "next/image";
+import { useRouter } from "next/router";
import CenteredForm from "@/layouts/CenteredForm";
const emailEnabled = process.env.NEXT_PUBLIC_EMAIL_PROVIDER;
@@ -18,6 +18,7 @@ type FormData = {
export default function Register() {
const [submitLoader, setSubmitLoader] = useState(false);
+ const router = useRouter();
const [form, setForm] = useState