From 77508bddcf05d7df0e681b8fc573621ed38333da Mon Sep 17 00:00:00 2001 From: Fabricio Silva Date: Mon, 30 Dec 2024 22:37:24 +0000 Subject: [PATCH] start fresh nodejs project --- .tool-versions | 2 +- deno.json | 12 --- deno.lock | 147 ------------------------------------- deps.ts | 8 -- main.js | 1 + main.ts | 23 ------ package-lock.json | 60 +++++++++++++++ package.json | 23 ++++++ src/constants.ts | 10 --- src/cron/cleanup.ts | 30 -------- src/cron/index.ts | 1 - src/database.ts | 9 --- src/middlewares/assets.ts | 17 ----- src/middlewares/headers.ts | 15 ---- src/middlewares/index.ts | 4 - src/middlewares/logs.ts | 28 ------- src/middlewares/secure.ts | 12 --- src/router.ts | 17 ----- src/routes/create.ts | 55 -------------- src/routes/home.ts | 18 ----- src/routes/index.ts | 3 - src/routes/view.ts | 44 ----------- src/utils/encrypt.ts | 19 ----- src/views/home.ejs | 34 --------- src/views/view.ejs | 18 ----- 25 files changed, 85 insertions(+), 525 deletions(-) delete mode 100644 deno.json delete mode 100644 deno.lock delete mode 100644 deps.ts create mode 100644 main.js delete mode 100644 main.ts create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 src/constants.ts delete mode 100644 src/cron/cleanup.ts delete mode 100644 src/cron/index.ts delete mode 100644 src/database.ts delete mode 100644 src/middlewares/assets.ts delete mode 100644 src/middlewares/headers.ts delete mode 100644 src/middlewares/index.ts delete mode 100644 src/middlewares/logs.ts delete mode 100644 src/middlewares/secure.ts delete mode 100644 src/router.ts delete mode 100644 src/routes/create.ts delete mode 100644 src/routes/home.ts delete mode 100644 src/routes/index.ts delete mode 100644 src/routes/view.ts delete mode 100644 src/utils/encrypt.ts delete mode 100644 src/views/home.ejs delete mode 100644 src/views/view.ejs diff --git a/.tool-versions b/.tool-versions index cc23c20..a4f413c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -deno 2.1.4 +nodejs 23.5.0 diff --git a/deno.json b/deno.json deleted file mode 100644 index 45f97be..0000000 --- a/deno.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "tasks": { - "dev": "deno run --reload --watch --unstable-kv --unstable-cron --allow-net --allow-write --allow-read --allow-env --env-file=.env main.ts", - "start": "deno run --lock --cached-only --unstable-kv --unstable-cron --allow-net --allow-write --allow-read --allow-env --env-file=.env main.ts", - "build-assets": "esbuild assets/*.mjs assets/*.css --minify --out-extension:.js=.mjs --outdir=assets/dist", - "cache-deps": "deno install --entrypoint deps.ts" - }, - "fmt": { - "lineWidth": 120, - "semiColons": false - } -} diff --git a/deno.lock b/deno.lock deleted file mode 100644 index d28c883..0000000 --- a/deno.lock +++ /dev/null @@ -1,147 +0,0 @@ -{ - "version": "4", - "specifiers": { - "jsr:@b-fuze/deno-dom@*": "0.1.48", - "jsr:@oak/commons@1": "1.0.0", - "jsr:@oak/oak@*": "17.1.3", - "jsr:@std/assert@1": "1.0.10", - "jsr:@std/bytes@1": "1.0.4", - "jsr:@std/bytes@^1.0.2": "1.0.4", - "jsr:@std/crypto@1": "1.0.3", - "jsr:@std/encoding@1": "1.0.6", - "jsr:@std/encoding@^1.0.5": "1.0.6", - "jsr:@std/fmt@^1.0.3": "1.0.3", - "jsr:@std/fs@^1.0.7": "1.0.7", - "jsr:@std/http@1": "1.0.12", - "jsr:@std/io@0.224": "0.224.9", - "jsr:@std/io@0.225": "0.225.0", - "jsr:@std/log@*": "0.224.12", - "jsr:@std/media-types@1": "1.1.0", - "jsr:@std/path@*": "1.0.8", - "jsr:@std/path@1": "1.0.8", - "jsr:@viki/nanoid@*": "3.0.0", - "npm:path-to-regexp@6.2.1": "6.2.1" - }, - "jsr": { - "@b-fuze/deno-dom@0.1.48": { - "integrity": "bf5b591aef2e9e9c59adfcbb93a9ecd45bab5b7c8263625beafa5c8f1662e7da" - }, - "@oak/commons@1.0.0": { - "integrity": "49805b55603c3627a9d6235c0655aa2b6222d3036b3a13ff0380c16368f607ac", - "dependencies": [ - "jsr:@std/assert", - "jsr:@std/bytes@1", - "jsr:@std/crypto", - "jsr:@std/encoding@1", - "jsr:@std/http", - "jsr:@std/media-types" - ] - }, - "@oak/oak@17.1.3": { - "integrity": "d89296c22db91681dd3a2a1e1fd14e258d0d5a9654de55637aee5b661c159f33", - "dependencies": [ - "jsr:@oak/commons", - "jsr:@std/assert", - "jsr:@std/bytes@1", - "jsr:@std/crypto", - "jsr:@std/http", - "jsr:@std/io@0.224", - "jsr:@std/media-types", - "jsr:@std/path@1", - "npm:path-to-regexp" - ] - }, - "@std/assert@1.0.10": { - "integrity": "59b5cbac5bd55459a19045d95cc7c2ff787b4f8527c0dd195078ff6f9481fbb3" - }, - "@std/bytes@1.0.4": { - "integrity": "11a0debe522707c95c7b7ef89b478c13fb1583a7cfb9a85674cd2cc2e3a28abc" - }, - "@std/crypto@1.0.3": { - "integrity": "a2a32f51ddef632d299e3879cd027c630dcd4d1d9a5285d6e6788072f4e51e7f" - }, - "@std/encoding@1.0.6": { - "integrity": "ca87122c196e8831737d9547acf001766618e78cd8c33920776c7f5885546069" - }, - "@std/fmt@1.0.3": { - "integrity": "97765c16aa32245ff4e2204ecf7d8562496a3cb8592340a80e7e554e0bb9149f" - }, - "@std/fs@1.0.7": { - "integrity": "95ac7326e0e59089c979706e17bb28db03b5fb41c5a37c9c556788198b0662d6" - }, - "@std/http@1.0.12": { - "integrity": "85246d8bfe9c8e2538518725b158bdc31f616e0869255f4a8d9e3de919cab2aa", - "dependencies": [ - "jsr:@std/encoding@^1.0.5" - ] - }, - "@std/io@0.224.9": { - "integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3", - "dependencies": [ - "jsr:@std/bytes@^1.0.2" - ] - }, - "@std/io@0.225.0": { - "integrity": "c1db7c5e5a231629b32d64b9a53139445b2ca640d828c26bf23e1c55f8c079b3" - }, - "@std/log@0.224.12": { - "integrity": "d0f002f1340a11f28d482a7a9e1c904c26b8ff2c7dd4fe32175b3ece3e0b18c5", - "dependencies": [ - "jsr:@std/fmt", - "jsr:@std/fs", - "jsr:@std/io@0.225" - ] - }, - "@std/media-types@1.1.0": { - "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" - }, - "@std/path@1.0.8": { - "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" - }, - "@viki/nanoid@3.0.0": { - "integrity": "a21e85c3a7bacce19becc4aa3ddfbbaf2a19435b2596198713c8422ec128ca34" - } - }, - "npm": { - "path-to-regexp@6.2.1": { - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" - } - }, - "remote": { - "https://deno.land/std@0.137.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", - "https://deno.land/std@0.137.0/bytes/bytes_list.ts": "67eb118e0b7891d2f389dad4add35856f4ad5faab46318ff99653456c23b025d", - "https://deno.land/std@0.137.0/bytes/equals.ts": "a60ef9f01fb6e06a4e0343fc44d53d39d12dd66bc3f09ac8e6eb9cc1a6335e48", - "https://deno.land/std@0.137.0/bytes/mod.ts": "763f97d33051cc3f28af1a688dfe2830841192a9fea0cbaa55f927b49d49d0bf", - "https://deno.land/std@0.137.0/fmt/colors.ts": "30455035d6d728394781c10755351742dd731e3db6771b1843f9b9e490104d37", - "https://deno.land/std@0.137.0/io/buffer.ts": "bd0c4bf53db4b4be916ca5963e454bddfd3fcd45039041ea161dbf826817822b", - "https://deno.land/std@0.137.0/io/bufio.ts": "6892debf4476ba48591f47eadfde232a04f8d3ddaaf134f659234b09ea5d9c40", - "https://deno.land/std@0.137.0/io/files.ts": "d199ef64e918a256320ba8d8d44ae91de87c9077df8f8d6cca013f1b9fbbe285", - "https://deno.land/std@0.137.0/io/util.ts": "078da53bba767bec0d45f7da44411f6dbf269e51ef7fcfea5e3714e04681c674", - "https://deno.land/std@0.137.0/streams/conversion.ts": "712585bfa0172a97fb68dd46e784ae8ad59d11b88079d6a4ab098ff42e697d21", - "https://deno.land/std@0.137.0/testing/_diff.ts": "029a00560b0d534bc0046f1bce4bd36b3b41ada3f2a3178c85686eb2ff5f1413", - "https://deno.land/std@0.137.0/testing/_format.ts": "0d8dc79eab15b67cdc532826213bbe05bccfd276ca473a50a3fc7bbfb7260642", - "https://deno.land/std@0.137.0/testing/asserts.ts": "61d85fc80f548a6e1e66d93fb7874a2c9e097aeecc00643c5f4f340370cde56f", - "https://deno.land/x/dejs@0.10.3/mod.ts": "8ca07db9a85c978c1c3741e673429fbff2bd063cb535bdb1b5b3375dba0a6fe3", - "https://deno.land/x/dejs@0.10.3/vendor/https/deno.land/std/io/buffer.ts": "32a3beffa31a6a8e6ab4b666fed0037830aa42a2c7b375b8b5cf3d2039250088", - "https://deno.land/x/dejs@0.10.3/vendor/https/deno.land/std/io/bufio.ts": "6ea5a0845b0ebe428da235e6470664bdaed128b2f8b54e0d87b87acfd4347c79", - "https://deno.land/x/dejs@0.10.3/vendor/https/deno.land/std/io/util.ts": "4a713f517fb794dce2237aa36fe5873a45c3d374d38fdb4cc33fcff1b3fdaa47", - "https://deno.land/x/dejs@0.10.3/vendor/https/deno.land/x/lodash/escape.js": "653e406a1b9c947918c124ddbfb8d39d5cebe86884b819974b5de13279d52df5", - "https://deno.land/x/lodash@4.17.15-es/_Symbol.js": "631160c3c0cbd05ec8a3d1934ded4a312504a29f04a00be2b29372d00dd6bc6d", - "https://deno.land/x/lodash@4.17.15-es/_arrayMap.js": "ae3521733bd602f0f0443562ca13d3d1c8f42e130d4d4b0deacd931b68b0c60b", - "https://deno.land/x/lodash@4.17.15-es/_baseGetTag.js": "3a9eebe37ba231eff0380b5f76ac5b5fcee4590665642fd052d77aa51c7d063f", - "https://deno.land/x/lodash@4.17.15-es/_basePropertyOf.js": "a62950da12b7236a1524bc1191d43ed2edc6e93827f1b12e903d71f9f262e15b", - "https://deno.land/x/lodash@4.17.15-es/_baseToString.js": "dc45840c564e75b058f8492a207d84a80629facdc33d80c4f05018aacdad675b", - "https://deno.land/x/lodash@4.17.15-es/_escapeHtmlChar.js": "96451046e1ca9a2e38dafdd0635f163976631bea1a32688bfbed105f1c224940", - "https://deno.land/x/lodash@4.17.15-es/_freeGlobal.js": "0b65c37b3c1ce6d1800cb59a330dde73f1009f0d10eeaf8fd45f7607b87db4c5", - "https://deno.land/x/lodash@4.17.15-es/_getRawTag.js": "0023dec54160317b70d52df1d7918638bc16a2869b1bf355f0a4f3e755aa6faf", - "https://deno.land/x/lodash@4.17.15-es/_objectToString.js": "8f1bb6043dc27219e71dfae28900a7f214a0856118a628efeb120169fe46fe8c", - "https://deno.land/x/lodash@4.17.15-es/_root.js": "df58ff96c454ca91ace20d20e6af49b354c70dfba7e737adc00cd23e8ff77168", - "https://deno.land/x/lodash@4.17.15-es/escape.js": "7babdce893618e4104b3baec5664f7d645b9a18d38e94ed09c4430ebb0f0a0ff", - "https://deno.land/x/lodash@4.17.15-es/isArray.js": "0d9bcdfdf53955d9253076ddd68e0b992b2c91fb8364baa2ca971e57cbb74e4b", - "https://deno.land/x/lodash@4.17.15-es/isObjectLike.js": "e45d69136695e8568c6fb3c7327f96ac1a8ff7284b1b22f26fb4654255fd0c6c", - "https://deno.land/x/lodash@4.17.15-es/isSymbol.js": "f0dc1666c3cec2306cd4fd0f63a9a7ab1f25ed21d2db6664b1edc81bd3641a41", - "https://deno.land/x/lodash@4.17.15-es/toString.js": "3f4c8d942944c3fe622e9fba36275b6291e834113619b266909822becfa94976", - "https://deno.land/x/mimetypes@v1.0.0/mod.ts": "abd1ea614b32cfa7fd50b46f6e070617696664698b8a34935dc807f3035ad408", - "https://deno.land/x/mimetypes@v1.0.0/src/mime.ts": "7cd7590eae6127dc1abfe710900fc749e94d5c715ffe8a148e59fe20ee21a9a5" - } -} diff --git a/deps.ts b/deps.ts deleted file mode 100644 index 435b682..0000000 --- a/deps.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * as path from "jsr:@std/path" -export * as log from "jsr:@std/log" -export * as oak from "jsr:@oak/oak" -export * as denoDom from "jsr:@b-fuze/deno-dom" -export { nanoid } from "jsr:@viki/nanoid" - -export * as dejs from "https://deno.land/x/dejs@0.10.3/mod.ts" -export { mime } from "https://deno.land/x/mimetypes@v1.0.0/mod.ts" diff --git a/main.js b/main.js new file mode 100644 index 0000000..d914c60 --- /dev/null +++ b/main.js @@ -0,0 +1 @@ +console.log("hi"); diff --git a/main.ts b/main.ts deleted file mode 100644 index 1ae2e82..0000000 --- a/main.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { log, oak } from "./deps.ts" -import * as middleware from "./src/middlewares/index.ts" -import * as cron from "./src/cron/index.ts" -import { router } from "./src/router.ts" -import { LISTEN_PORT } from "./src/constants.ts" - -// take care of expired files -Deno.cron("Cleanup", "0 0 * * *", cron.cleanup) - -const app = new oak.Application() -const port = Number(LISTEN_PORT) - -app.use(middleware.logs) -app.use(middleware.headers) -app.use(router.routes()) -app.use(router.allowedMethods({ throw: true })) -app.use(middleware.assets) - -app.addEventListener("listen", () => { - log.info(`SERVER listening on port ${port}`) -}) - -await app.listen({ port }) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b5281aa --- /dev/null +++ b/package-lock.json @@ -0,0 +1,60 @@ +{ + "name": "logs.moe", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "logs.moe", + "version": "1.0.0", + "license": "WTFPL", + "devDependencies": { + "esbuild": "0.24.2" + }, + "engines": { + "node": ">=23.5.0" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ced8c6f --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "logs.moe", + "version": "1.0.0", + "private": true, + "description": "Share secure logs", + "author": "hi@fabricio.dev", + "license": "WTFPL", + "main": "main.js", + "type": "module", + "engines": { + "node": ">=23.5.0" + }, + "packageManager": "npm@11.0.0", + "scripts": { + "dev": "node --env-file=.env --watch main.js", + "start": "node --env-file=.env main.js", + "build-assets": "esbuild ./assets/*.mjs ./assets/*.css --minify --outdir=./assets/dist --out-extension:.js=.mjs" + }, + "dependencies": {}, + "devDependencies": { + "esbuild": "0.24.2" + } +} diff --git a/src/constants.ts b/src/constants.ts deleted file mode 100644 index 7a1082f..0000000 --- a/src/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const LISTEN_PORT = `${Deno.env.get("PORT")}` // port to server listen to -export const BASE_URL = `${Deno.env.get("BASE_URL")}` // url to print after upload -export const DATA_DIR = `${Deno.env.get("DATA_DIR")}` // directory to save .db file -export const FILES_DIR = `${DATA_DIR}/files` // directory to upload binaries - -export const ASSETS_DIR = `${Deno.cwd()}/assets` // directory to static assets -export const VIEWS_DIR = `${Deno.cwd()}/src/views` // directory contain .ejs templates - -export const MAX_REQUEST_SIZE = 21 * 1024 * 1024 // in bytes (21mb) -export const FILE_TTL = 7 * 24 * 60 * 60 * 1000 // in milliseconds (7 days) diff --git a/src/cron/cleanup.ts b/src/cron/cleanup.ts deleted file mode 100644 index fc37862..0000000 --- a/src/cron/cleanup.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { log, path } from "../../deps.ts" -import { FILE_TTL, FILES_DIR } from "../constants.ts" -import { kv } from "../database.ts" - -export const cleanup = async () => { - log.info("CRON Running cleanup") - - for await (const { isFile, name } of Deno.readDir(FILES_DIR)) { - const { birthtime } = await Deno.stat(`${FILES_DIR}/${name}`) - const createdAt = birthtime?.valueOf() - const { name: uuid } = path.parse(name) - - // invalid file or not yet expired - if (!isFile || !createdAt || (createdAt + FILE_TTL) > Date.now()) { - continue - } - - try { - await Promise.allSettled([ - kv.delete(["data", uuid]), - Deno.remove(`${FILES_DIR}/${name}`), - ]) - - log.info(`CRON Deleted: ${uuid}`) - } catch (err) { - log.error(`CRON Failed to delete: ${uuid}`) - log.error(err) - } - } -} diff --git a/src/cron/index.ts b/src/cron/index.ts deleted file mode 100644 index 50177f0..0000000 --- a/src/cron/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./cleanup.ts" diff --git a/src/database.ts b/src/database.ts deleted file mode 100644 index e09f762..0000000 --- a/src/database.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DATA_DIR } from "./constants.ts" - -export type Data = { - iv: Uint8Array - contentType: string -} - -await Deno.mkdir(DATA_DIR, { recursive: true, mode: 0o755 }) -export const kv = await Deno.openKv(`${DATA_DIR}/kv.db`) diff --git a/src/middlewares/assets.ts b/src/middlewares/assets.ts deleted file mode 100644 index 70f0340..0000000 --- a/src/middlewares/assets.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { oak } from "../../deps.ts" -import { ASSETS_DIR } from "../constants.ts" - -// use it as the last middleware to give priority to the router -export const assets: oak.Middleware = async (ctx) => { - const isProd = Deno.env.get("DENO_ENV")?.startsWith("prod") - - try { - if (ctx.request.method === "GET") { - await ctx.send({ - root: isProd ? `${ASSETS_DIR}/dist` : ASSETS_DIR, - }) - } - } catch { - return ctx.throw(oak.Status.NotFound) - } -} diff --git a/src/middlewares/headers.ts b/src/middlewares/headers.ts deleted file mode 100644 index faca570..0000000 --- a/src/middlewares/headers.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { oak } from "../../deps.ts" - -export const headers: oak.Middleware = async (ctx, next) => { - const start = Date.now() - - try { - await next() - } finally { - const end = Date.now() - start - ctx.response.headers.set("x-response-time", `${end}ms`) - - // disable robots by headers - ctx.response.headers.set("x-robots-tag", "none") - } -} diff --git a/src/middlewares/index.ts b/src/middlewares/index.ts deleted file mode 100644 index d759016..0000000 --- a/src/middlewares/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./assets.ts" -export * from "./headers.ts" -export * from "./logs.ts" -export * from "./secure.ts" diff --git a/src/middlewares/logs.ts b/src/middlewares/logs.ts deleted file mode 100644 index fb6f3f8..0000000 --- a/src/middlewares/logs.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { log, oak } from "../../deps.ts" - -export const logs: oak.Middleware = async (ctx, next) => { - const noBrowser = !ctx.request.userAgent.browser.name - let error - - try { - await next() - } catch ({ status = oak.Status.InternalServerError, message }: any) { - error = `${status}: ${message}` - - ctx.response.status = status - - // prints body message when client is not a browser - if (noBrowser) { - ctx.response.body = error - } - } finally { - log.info( - `${ctx.request.method} ${ctx.request.url} ${ctx.response.status} ${ctx.response.headers.get("x-response-time")}`, - ) - - // prints console errors right after request - if (error) { - log.error(`└─ ${error}`) - } - } -} diff --git a/src/middlewares/secure.ts b/src/middlewares/secure.ts deleted file mode 100644 index 598253e..0000000 --- a/src/middlewares/secure.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { oak } from "../../deps.ts" - -// if not set it will just bypass -export const secure: oak.Middleware = async (ctx, next) => { - const key = Deno.env.get("KEY") - - if (key && ctx.request.headers.get("x-key") !== key) { - return ctx.throw(oak.Status.Unauthorized) - } - - await next() -} diff --git a/src/router.ts b/src/router.ts deleted file mode 100644 index 1947aa6..0000000 --- a/src/router.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { oak } from "../deps.ts" -import * as middlewares from "./middlewares/index.ts" -import * as routes from "./routes/index.ts" - -export const router = new oak.Router() - -// returns the encrypted content as binary -router.get("/data/:uuid", routes.data) - -// renders the file -router.get("/:uuid", routes.view) - -// api to upload new file -router.post("/", middlewares.secure, routes.create) - -// render home page -router.get("/", routes.home) diff --git a/src/routes/create.ts b/src/routes/create.ts deleted file mode 100644 index c4a1e28..0000000 --- a/src/routes/create.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { mime, nanoid, oak } from "../../deps.ts" -import { BASE_URL, FILES_DIR, MAX_REQUEST_SIZE } from "../constants.ts" -import { encrypt } from "../utils/encrypt.ts" -import { Data, kv } from "../database.ts" - -export const create: oak.Middleware = async (ctx) => { - // api will only work with form-data - if (ctx.request.body.type() !== "form-data") { - return ctx.throw(oak.Status.BadRequest) - } - - // limit request size - if (Number(ctx.request.headers.get("content-length")) > MAX_REQUEST_SIZE) { - return ctx.throw(oak.Status.RequestEntityTooLarge) - } - - const reader = await ctx.request.body.formData() - const field = reader.get("data") - let content: Uint8Array | undefined - let contentType = "text/plain" - - // receive as file - if (field instanceof File) { - content = await field.arrayBuffer() as Uint8Array - contentType = mime.getType(`${field.name.split(".").pop()}`) || field.type - } - - // received as text - if (typeof field === "string") { - content = new TextEncoder().encode(field) - } - - // not get any content somehow - if (!content) { - return ctx.throw(oak.Status.UnprocessableEntity) - } - - const { iv, k, encrypted } = await encrypt(content) - const uuid = nanoid(8) - - // save on disk (Deno.kv is limited to 64KiB) - await Deno.mkdir(FILES_DIR, { recursive: true, mode: 0o755 }) - - await Promise.allSettled([ - kv.set(["data", uuid], { iv, contentType } as Data), - Deno.writeFile( - `${FILES_DIR}/${uuid}.bin`, - new Uint8Array(encrypted), - { mode: 0o644 }, - ), - ]) - - ctx.response.status = oak.Status.Created - ctx.response.body = `${BASE_URL}/${uuid}#${k}\n` -} diff --git a/src/routes/home.ts b/src/routes/home.ts deleted file mode 100644 index b5d1ea9..0000000 --- a/src/routes/home.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { dejs, denoDom, oak } from "../../deps.ts" -import { VIEWS_DIR } from "../constants.ts" - -export const home: oak.RouterMiddleware<"/"> = async ( - ctx, -) => { - const noBrowser = !ctx.request.userAgent.browser.name - const html = await dejs.renderFileToString(`${VIEWS_DIR}/home.ejs`, {}) - let textContent - - // curl client - if (noBrowser) { - const document = new denoDom.DOMParser().parseFromString(html, "text/html") - textContent = document?.body.textContent - } - - ctx.response.body = textContent || html -} diff --git a/src/routes/index.ts b/src/routes/index.ts deleted file mode 100644 index 15d17d8..0000000 --- a/src/routes/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./create.ts" -export * from "./view.ts" -export * from "./home.ts" diff --git a/src/routes/view.ts b/src/routes/view.ts deleted file mode 100644 index 5024b01..0000000 --- a/src/routes/view.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { dejs, oak } from "../../deps.ts" -import { Data, kv } from "../database.ts" -import { FILES_DIR, VIEWS_DIR } from "../constants.ts" - -export const view: oak.RouterMiddleware<"/:uuid", { uuid: string }> = async ( - ctx, - next, -) => { - const noBrowser = !ctx.request.userAgent.browser.name - const { value } = await kv.get(["data", ctx.params.uuid]) - - // needs continue the router because its a root route - if (!value?.iv) { - return await next() - } - - // curl client - if (noBrowser) { - ctx.response.status = oak.Status.NotImplemented - ctx.response.body = "Can only decrypt it on browsers" - return - } - - // a request to "/data/:uuid" will happens on the view.ejs to get the encrypted blob - // there it will process the decryption - ctx.response.body = await dejs.renderFileToString( - `${VIEWS_DIR}/view.ejs`, - value, - ) -} - -export const data: oak.RouterMiddleware<"/data/:uuid", { uuid: string }> = async ( - ctx, -) => { - // just serve binary files (if it exists) - try { - await ctx.send({ - root: FILES_DIR, - path: `${ctx.params.uuid}.bin`, - }) - } catch { - return ctx.throw(oak.Status.NotFound) - } -} diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts deleted file mode 100644 index 4daaf6e..0000000 --- a/src/utils/encrypt.ts +++ /dev/null @@ -1,19 +0,0 @@ -// keep on frontend as its needed to decrypt -import { ALGORITHM, ALGORITHM_PARAMS, KEY_USAGE } from "../../assets/subtle.mjs" - -export const encrypt = async (decrypted: Uint8Array) => { - const iv = crypto.getRandomValues(new Uint8Array(16)) - const key = await crypto.subtle.generateKey( - ALGORITHM_PARAMS, - true, - KEY_USAGE, - ) - const { k } = await crypto.subtle.exportKey("jwk", key) - const encrypted = await crypto.subtle.encrypt( - { name: ALGORITHM, iv }, - key, - decrypted, - ) - - return { iv, k, encrypted } -} diff --git a/src/views/home.ejs b/src/views/home.ejs deleted file mode 100644 index c9287f2..0000000 --- a/src/views/home.ejs +++ /dev/null @@ -1,34 +0,0 @@ - - - -logs.moe - - - - - - - - -
Share encrypted logs without leaving terminal
-
-from file
-  $ curl https://logs.moe -F data=@debug.log
-from stdin
-  $ cat debug.log | curl https://logs.moe -F data=@-
-alias (file or stdin)
-  logsmoe() { curl https://logs.moe -F data="@${1:--}"; }
-  $ logsmoe debug.log
-  $ git diff --staged | logsmoe
-
-- Only accepts form-data and field name "data"
-- Upload size limited to 20MiB
-- Anything is deleted in 7 days
-- Everything is saved encrypted
-- Decryption only happens on browser
-
-This is a personal project and nothing is collected
-
-Inspiration ....... https://x0.at | https://0bin.net/faq/
-Source ........ https://github.com/fabricionaweb/logs.moe
- diff --git a/src/views/view.ejs b/src/views/view.ejs deleted file mode 100644 index 39997a9..0000000 --- a/src/views/view.ejs +++ /dev/null @@ -1,18 +0,0 @@ - - - -logs.moe - - - - - - - - - -
still working ⏳
- -- 2.51.2