diff --git a/Dockerfile b/Dockerfile index b212f0f..7309c02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,19 +5,23 @@ WORKDIR /app COPY package.json package-lock.json ./ -RUN npm ci --silent +RUN npm ci -COPY . ./ +COPY . . RUN npm run build +RUN npm ci --prod # Serve the built project FROM node:20.7.0-alpine as serve +USER node:node + WORKDIR /app -COPY --from=build /app/build . -COPY --from=build /app/package.json . -COPY --from=build /app/node_modules ./node_modules +COPY --from=build --chown=node:node /app/build ./build +COPY --from=build --chown=node:node /app/node_modules ./node_modules -CMD ["node", "index.js"] +COPY --chown=node:node package.json . + +ENTRYPOINT ["node", "build/index.js"] diff --git a/package-lock.json b/package-lock.json index 11abf30..4b860de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,7 @@ "highlight.js": "^11.8.0", "highlightjs-zig": "^1.0.2", "mongodb": "^6.1.0", - "random-words": "^2.0.0", - "svelte-tabler": "^0.6.3" + "random-words": "^2.0.0" }, "devDependencies": { "@skeletonlabs/skeleton": "^2.2.0", @@ -37,6 +36,7 @@ "prettier-plugin-svelte": "^2.10.1", "svelte": "^4.0.5", "svelte-check": "^3.4.3", + "svelte-tabler": "^0.6.3", "tailwindcss": "^3.3.2", "tslib": "^2.4.1", "typescript": "^5.0.0", @@ -71,6 +71,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -197,6 +198,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -210,6 +212,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -218,6 +221,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -225,12 +229,14 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.19", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -679,7 +685,8 @@ "node_modules/@types/estree": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==" + "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.13", @@ -923,6 +930,7 @@ "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1025,6 +1033,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -1079,6 +1088,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -1278,6 +1288,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", + "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "@types/estree": "^1.0.1", @@ -1351,6 +1362,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -1406,6 +1418,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, "engines": { "node": ">=6" } @@ -1757,6 +1770,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, "dependencies": { "@types/estree": "^1.0.0" } @@ -2186,6 +2200,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dev": true, "dependencies": { "@types/estree": "*" } @@ -2290,7 +2305,8 @@ "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true }, "node_modules/locate-path": { "version": "6.0.0", @@ -2346,6 +2362,7 @@ "version": "0.30.4", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz", "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==", + "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -2356,7 +2373,8 @@ "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/memory-pager": { "version": "1.5.0", @@ -2707,6 +2725,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", @@ -3228,6 +3247,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -3346,6 +3366,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.1.tgz", "integrity": "sha512-LpLqY2Jr7cRxkrTc796/AaaoMLF/1ax7cto8Ot76wrvKQhrPmZ0JgajiWPmg9mTSDqO16SSLiD17r9MsvAPTmw==", + "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", @@ -3504,6 +3525,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/svelte-tabler/-/svelte-tabler-0.6.3.tgz", "integrity": "sha512-YRAsznRtTvLJZx6MtbzaBlG9TCkGvLwd/3/uc3ZVYkxi4OMLbgTUpQnLWrURRKjy2VI1BJOBpBh+lxqsIn4Hxw==", + "dev": true, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0" } diff --git a/src/db/index.ts b/src/db/index.ts deleted file mode 100644 index c82439c..0000000 --- a/src/db/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { MongoClient } from 'mongodb'; -import { env } from '$env/dynamic/private'; -import type PasteSchema from "./paste-schema"; - -const client = new MongoClient(env.DB_URL); -await client.connect(); - -const db = client.db("paste69"); - -const pastes = db.collection("pastes"); - -export { - db, - pastes, -} \ No newline at end of file diff --git a/src/db/paste-schema.ts b/src/db/paste-schema.ts deleted file mode 100644 index 7fb1c3a..0000000 --- a/src/db/paste-schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -export default interface PasteSchema { - id: string; - contents: string; - highlight: string; - encrypted: boolean; - burnAfterReading: boolean; - createdAt: Date; - } \ No newline at end of file diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 841b8f2..0f6f817 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,9 +1,10 @@ import { env } from '$env/dynamic/private'; +import { Mongo } from '$lib/db/index'; import * as Sentry from '@sentry/node'; -import type { HandleServerError } from '@sveltejs/kit'; +import type { Handle, HandleServerError } from '@sveltejs/kit'; Sentry.init({ - dsn: env.SENTRY_DSN, + dsn: env.SENTRY_DSN, }); interface ServerError extends Error { diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 1484927..aa1f817 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,4 +1,4 @@ -import { pastes } from "$db/index"; +import { Mongo } from "$lib/db/index"; import type { PageServerLoad } from "./$types"; export const load: PageServerLoad = async ({ url }) => { @@ -7,6 +7,7 @@ export const load: PageServerLoad = async ({ url }) => { if (copyFrom) { // If it is, we need to fetch the paste from the database // and return it to the client. + const pastes = await Mongo.getNamedCollection("pastes"); const paste = await pastes.findOne({ id: copyFrom }); return { paste: structuredClone(paste), diff --git a/src/routes/[slug]/+page.server.ts b/src/routes/[slug]/+page.server.ts index 115ca62..b5cb51a 100644 --- a/src/routes/[slug]/+page.server.ts +++ b/src/routes/[slug]/+page.server.ts @@ -1,12 +1,13 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -import { pastes } from '$db/index'; +import { Mongo } from '$lib/db/index'; import { env } from '$env/dynamic/private'; export const load: PageLoad = async ({ params }) => { const [id, ext] = params.slug.split('.'); // Fetch the paste + const pastes = await Mongo.getNamedCollection('pastes'); const paste = await pastes.findOne({ id }); if (!paste) { throw error(404, 'Paste not found'); diff --git a/src/routes/[slug]/created/+page.server.ts b/src/routes/[slug]/created/+page.server.ts index 138719b..1aacb33 100644 --- a/src/routes/[slug]/created/+page.server.ts +++ b/src/routes/[slug]/created/+page.server.ts @@ -1,9 +1,10 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -import { pastes } from '$db/index'; +import { Mongo } from '$lib/db/index'; import { env } from '$env/dynamic/private'; export const load: PageLoad = async ({ params }) => { + const pastes = await Mongo.getNamedCollection('pastes'); const paste = await pastes.findOne({ id: params.slug }); if (!paste) { diff --git a/src/routes/api/pastes/+server.ts b/src/routes/api/pastes/+server.ts index cb3cec1..bd6127b 100644 --- a/src/routes/api/pastes/+server.ts +++ b/src/routes/api/pastes/+server.ts @@ -2,7 +2,7 @@ import { detectLanguage } from "$utils/hljs"; import { encrypt as doEncrypt } from "$utils/crypto"; import { error, json, type RequestHandler } from "@sveltejs/kit"; import { generate } from 'random-words'; -import { pastes } from "$db/index"; +import { Mongo } from "$lib/db/index"; import { env } from "$env/dynamic/private"; import { extensionMap } from "$utils/languages"; @@ -44,6 +44,7 @@ export const POST: RequestHandler = async ({ request }) => { createdAt: new Date(), }; + const pastes = await Mongo.getNamedCollection("pastes"); const res = await pastes.insertOne(data); if (!res.acknowledged) { diff --git a/src/routes/api/pastes/[id]/+server.ts b/src/routes/api/pastes/[id]/+server.ts index 1c5e699..908bb5e 100644 --- a/src/routes/api/pastes/[id]/+server.ts +++ b/src/routes/api/pastes/[id]/+server.ts @@ -1,10 +1,11 @@ -import { pastes } from "$db/index"; +import { Mongo } from "$lib/db/index"; import { error, json, type RequestHandler } from "@sveltejs/kit"; // Fetch the paste with the given ID, returning it as a JSON object. export const GET: RequestHandler = async ({ params }) => { const { id } = params; + const pastes = await Mongo.getNamedCollection("pastes"); const paste = await pastes.findOne({ id }); if (!paste) { diff --git a/src/routes/api/pastes/[id]/decrypt/+server.ts b/src/routes/api/pastes/[id]/decrypt/+server.ts index e1fadde..92240f9 100644 --- a/src/routes/api/pastes/[id]/decrypt/+server.ts +++ b/src/routes/api/pastes/[id]/decrypt/+server.ts @@ -1,5 +1,5 @@ import { error, json, type RequestHandler } from "@sveltejs/kit"; -import { pastes } from "$db/index"; +import { Mongo } from "$lib/db/index"; import { decrypt } from "$utils/crypto"; // Decrypt the paste with the given ID using the provided password. @@ -7,6 +7,7 @@ export const POST: RequestHandler = async ({ params, request }) => { const { id } = params; const { password } = await request.json(); + const pastes = await Mongo.getNamedCollection("pastes"); const paste = await pastes.findOne({ id }); if (!paste) { diff --git a/src/routes/images/paste/[id]/+server.ts b/src/routes/images/paste/[id]/+server.ts index 8436116..7b5248c 100644 --- a/src/routes/images/paste/[id]/+server.ts +++ b/src/routes/images/paste/[id]/+server.ts @@ -1,10 +1,11 @@ -import { pastes } from "$db/index"; +import { Mongo } from "$lib/db/index"; import { env } from "$env/dynamic/private"; import { error, type RequestHandler } from "@sveltejs/kit"; export const GET: RequestHandler = async ({ params }) => { const { id } = params; + const pastes = await Mongo.getNamedCollection("pastes"); const paste = await pastes.findOne({ id }); if (!paste) { diff --git a/src/stores/app.ts b/src/stores/app.ts index 25866d9..8ed3ba9 100644 --- a/src/stores/app.ts +++ b/src/stores/app.ts @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; -import type PasteSchema from '$db/paste-schema'; +import type PasteSchema from '$lib/db/paste-schema'; export const paste = writable({ id: '', diff --git a/svelte.config.js b/svelte.config.js index 97b83b2..b2479cf 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -14,7 +14,7 @@ const config = { adapter: adapter(), alias: { - '$db/*': './src/db/*', + '$db/*': './src/lib/db/*', '$utils/*': './src/utils/*', } }