uwu tooling ftw (MUAHAHAHAHAHA ONE MUST CONFRONT THE BUN-- TYPE-SCRIPT (get it)
This commit is contained in:
parent
964ef740b0
commit
dba763ea75
22 changed files with 555 additions and 124 deletions
156
.gitignore
vendored
156
.gitignore
vendored
|
|
@ -1,132 +1,44 @@
|
|||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
**/*.trace
|
||||
**/*.zip
|
||||
**/*.tar.gz
|
||||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
|
||||
.env
|
||||
16
README.md
16
README.md
|
|
@ -1,3 +1,15 @@
|
|||
# reel-of-js-fortune
|
||||
# Elysia with Bun runtime
|
||||
|
||||
rewrite using uwu libs for Seb
|
||||
## Getting Started
|
||||
To get started with this template, simply paste this command into your terminal:
|
||||
```bash
|
||||
bun create elysia ./elysia-example
|
||||
```
|
||||
|
||||
## Development
|
||||
To start the development server run:
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
|
||||
Open http://localhost:3000/ with your browser to see the result.
|
||||
103
bun.lock
Normal file
103
bun.lock
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "reel-of-js-fortune",
|
||||
"dependencies": {
|
||||
"@elysia/html": "^1.4.1",
|
||||
"@elysia/static": "^1.4.11",
|
||||
"elysia": "latest",
|
||||
"tmdb-ts": "^2.3.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="],
|
||||
|
||||
"@elysia/html": ["@elysia/html@1.4.1", "", { "dependencies": { "@kitajs/html": "^4.1.0", "@kitajs/ts-html-plugin": "^4.0.1" }, "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-U9/8Au1hZBaqW16AKhoT+e3/QC9Y4wp5iplej6b3BnAiO37pqbByaTHpGIC2MoTE5EfVwSyeLECQDn/jiGjBJQ=="],
|
||||
|
||||
"@elysia/static": ["@elysia/static@1.4.11", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-L3PN8V+cgz9Oz9kTow7ed3DHHCTHb9ZqZZDLxmKhrIKcFmWvjqzTm9TcMR2aLKjjls+QMSGuB7ZyaO+usIXovA=="],
|
||||
|
||||
"@kitajs/html": ["@kitajs/html@4.2.13", "", { "dependencies": { "csstype": "^3.1.3" } }, "sha512-o+8e61EsoLDPTP7rsPkYolca1YFybHuxU2Lr5fWDZCUkYT/6uBlVkvnZUdCXMQKentJL9dxwpR8/xK2Q+U4LhA=="],
|
||||
|
||||
"@kitajs/ts-html-plugin": ["@kitajs/ts-html-plugin@4.1.4", "", { "dependencies": { "chalk": "^5.6.2", "tslib": "^2.8.1", "yargs": "^18.0.0" }, "peerDependencies": { "@kitajs/html": "^4.2.10", "typescript": "^5.9.3" }, "bin": { "xss-scan": "dist/cli.js", "ts-html-plugin": "dist/cli.js" } }, "sha512-xK5mNrhnIy73kJFKx5yVGChJyWFRGmIaE0sjlVxVYllk5dyaEYVCrIh1N8AfnseEHka8gAqzPGW95HlkhDvnJA=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="],
|
||||
|
||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="],
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
"@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
||||
|
||||
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
|
||||
"cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
|
||||
|
||||
"cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"elysia": ["elysia@1.4.29", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
"file-type": ["file-type@22.0.1", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.5", "token-types": "^6.1.2", "uint8array-extras": "^1.5.0" } }, "sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="],
|
||||
|
||||
"tmdb-ts": ["tmdb-ts@2.3.0", "", {}, "sha512-j7V85Gs8+fsSDOYmsChjCLn//ouxrwdWqlUUwKOM518PIcBU8VBS4YN/Lh2KJiLjEICHjYjv2SRvhMWn1Tdk4w=="],
|
||||
|
||||
"token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
|
||||
|
||||
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
|
||||
}
|
||||
}
|
||||
18
package.json
Normal file
18
package.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "reel-of-js-fortune",
|
||||
"version": "1.0.50",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "bun run --watch src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@elysia/html": "^1.4.1",
|
||||
"@elysia/static": "^1.4.11",
|
||||
"elysia": "latest",
|
||||
"tmdb-ts": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
},
|
||||
"module": "src/index.js"
|
||||
}
|
||||
BIN
public/assets/android-chrome-192x192.png
Normal file
BIN
public/assets/android-chrome-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
public/assets/android-chrome-512x512.png
Normal file
BIN
public/assets/android-chrome-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 359 KiB |
BIN
public/assets/apple-touch-icon.png
Normal file
BIN
public/assets/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
public/assets/favicon-16x16.png
Normal file
BIN
public/assets/favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 705 B |
BIN
public/assets/favicon-32x32.png
Normal file
BIN
public/assets/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/assets/favicon.ico
Normal file
BIN
public/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
29
public/pages/discover.html
Normal file
29
public/pages/discover.html
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{{ define "discover" }}
|
||||
<!doctype html>
|
||||
<html>
|
||||
{{ template "header" . }}
|
||||
<body
|
||||
class="h-screen overflow-hidden grid grid-rows-[auto,1fr] bg-gray-900 text-white"
|
||||
>
|
||||
<div class="w-screen text-center">
|
||||
<h1
|
||||
class="text-[3rem] uppercase tracking-[0.05em] text-white/30 bg-clip-text [text-shadow:_4px_4px_4px_rgb(0_0_0_/_0.6),_8px_8px_8px_rgb(0_0_0_/_0.4)]"
|
||||
>
|
||||
Reel of Fortune
|
||||
</h1>
|
||||
<button
|
||||
class="px-6 py-2.5 rounded-lg font-semibold text-white bg-gradient-to-b from-white/10 to-white/3 backdrop-blur-md border border-white/10 shadow-[0_2px_4px_rgba(0,0,0,0.4),_inset_0_1px_0_rgba(255,255,255,0.2)] hover:shadow-[0_0_30px_rgba(255,255,255,0.6),_0_4px_12px_rgba(255,255,255,0.15),_inset_0_1px_0_rgba(255,255,255,0.4)] hover:from-white/20 hover:to-white/10 active:translate-y-[1px] transition-all duration-[900ms] ease-[cubic-bezier(0.4,0,0.2,1)]"
|
||||
hx-get="/api/discover"
|
||||
hx-target="#movies"
|
||||
>
|
||||
Discover movie
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
id="movies"
|
||||
class="flex justify-center items-center overflow-hidden max-w-[80vw] mx-auto p-5"
|
||||
></div>
|
||||
</body>
|
||||
{{ template "footer" . }}
|
||||
</html>
|
||||
{{ end }}
|
||||
7
public/pages/movie.html
Normal file
7
public/pages/movie.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{{ define "movie" }}
|
||||
<html>
|
||||
{{ template "header" . }}
|
||||
<div class="p-16 h-full">{{ template "card" . }}</div>
|
||||
{{ template "footer" . }}
|
||||
</html>
|
||||
{{ end }}
|
||||
42
public/templates/card.html
Normal file
42
public/templates/card.html
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{{ define "card" }}
|
||||
<div
|
||||
id="{{ .ID }}"
|
||||
class="relative w-full h-full max-w-5xl mx-auto bg-white/10 backdrop-blur-md border border-white/20 rounded-2xl shadow-2xl text-white p-5 overflow-hidden flex flex-col"
|
||||
>
|
||||
<div
|
||||
class="flex-grow flex items-center justify-center overflow-hidden rounded-xl"
|
||||
>
|
||||
<img
|
||||
src="https://image.tmdb.org/t/p/original{{ .PosterPath }}"
|
||||
alt="{{ .Title }}"
|
||||
class="rounded-t-lg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex-none pt-4">
|
||||
<div class="flex-auto min-h-0 flex flex-col">
|
||||
<h5 class="text-2xl font-bold leading-tight mb-2">
|
||||
{{ .Title }} ({{ .ReleaseDate }}) - {{ .VoteAverage }}/10
|
||||
</h5>
|
||||
<p class="text-sm text-gray-200">{{ .Overview }}</p>
|
||||
<div
|
||||
id="providers"
|
||||
hx-trigger="load"
|
||||
hx-swap="outerHTML"
|
||||
hx-get="/api/providers/watch/{{ .ID }}?countryCode=US"
|
||||
class="flex w-screen justify-center pt-1"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed inset-0 pointer-events-none -z-10">
|
||||
<img
|
||||
src="https://image.tmdb.org/t/p/original{{ .PosterPath }}"
|
||||
alt="Backdrop"
|
||||
class="w-full h-full object-cover blur-3xl scale-110 opacity-60"
|
||||
/>
|
||||
<div
|
||||
class="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(51,65,85,0.4)_0%,rgba(30,41,59,0.6)_70%,rgba(17,24,39,0.8)_100%)] mix-blend-multiply"
|
||||
></div>
|
||||
</div>
|
||||
{{ end }}
|
||||
1
public/templates/footer.html
Normal file
1
public/templates/footer.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
{{ define "footer" }} {{ end }}
|
||||
11
public/templates/header.html
Normal file
11
public/templates/header.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{{ define "header" }}
|
||||
<head>
|
||||
<title>Reel of Fortune</title>
|
||||
<!--Use the `title` variable to set the title of the page-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charset="UTF-8" />
|
||||
<!--Load Tailwind & HTMX-->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.min.js"></script>
|
||||
</head>
|
||||
{{ end }}
|
||||
23
public/templates/providers.html
Normal file
23
public/templates/providers.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{{ define "providers" }}
|
||||
<div id="providers" class="flex gap-2 p-2">
|
||||
{{ range .FlatRate }}
|
||||
<a href="{{ $.Link }}">
|
||||
<img
|
||||
src="https://image.tmdb.org/t/p/original{{ .LogoPath }}"
|
||||
title="{{ .ProviderName }}"
|
||||
alt="{{ .ProviderName }}"
|
||||
class="[&[alt*=Apple]]:mix-blend-screen rounded-lg"
|
||||
/>
|
||||
</a>
|
||||
{{ end }} {{ range .Rent }}
|
||||
<a href="{{ $.Link }}">
|
||||
<img
|
||||
src="https://image.tmdb.org/t/p/original{{ .LogoPath }}"
|
||||
title="{{ .ProviderName }}"
|
||||
alt="{{ .ProviderName }}"
|
||||
class="[&[alt*=Apple]]:mix-blend-screen rounded-lg"
|
||||
/>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
1
reel-of-fortune
Submodule
1
reel-of-fortune
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9ba8cd18f710727747312c865b5ec6ea97e8b558
|
||||
37
src/api/index.ts
Normal file
37
src/api/index.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { Elysia, t } from 'elysia';
|
||||
import { API } from './service';
|
||||
import Yuck from '../util/gin';
|
||||
|
||||
export const api = new Elysia({ prefix: '/api' })
|
||||
.get("discover", async ({ query }) => {
|
||||
const movie = await API.discover(query);
|
||||
const releaseYear = movie.release_date.substring(0, 4);
|
||||
const voteAverage = movie.vote_average.toFixed(2);
|
||||
|
||||
return Yuck.renderMoviePage(
|
||||
movie.id,
|
||||
movie.title,
|
||||
releaseYear,
|
||||
voteAverage,
|
||||
movie.overview,
|
||||
movie.poster_path
|
||||
);
|
||||
})
|
||||
.get("movie/:id", async ({ params: { id } }) => {
|
||||
const movie = await API.movie(parseInt(id));
|
||||
const releaseYear = movie.release_date.substring(0, 4);
|
||||
const voteAverage = movie.vote_average.toFixed(2);
|
||||
|
||||
return Yuck.renderMoviePage(
|
||||
movie.id,
|
||||
movie.title,
|
||||
releaseYear,
|
||||
voteAverage,
|
||||
movie.overview,
|
||||
movie.poster_path!
|
||||
);
|
||||
})
|
||||
.get("providers/watch/:id", async ({ params: { id } }) => {
|
||||
const providers = await API.providers(parseInt(id));
|
||||
return Yuck.renderProviderPage()
|
||||
});
|
||||
24
src/api/service.ts
Normal file
24
src/api/service.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { MovieQueryOptions, TMDB } from "tmdb-ts";
|
||||
|
||||
const tmbd = new TMDB(process.env.TMBD_API_KEY!);
|
||||
|
||||
export class API {
|
||||
static async discover(query: MovieQueryOptions) {
|
||||
const response = await tmbd.discover.movie(query);
|
||||
const randomIndex = Math.floor(Math.random() * response.results.length);
|
||||
const selectedMovie = response.results[randomIndex];
|
||||
return selectedMovie;
|
||||
}
|
||||
|
||||
static async movie(id: number) {
|
||||
return await tmbd.movies.details(id);
|
||||
}
|
||||
|
||||
static async providers(movieId: number, countryCode = 'US') {
|
||||
// TODO: Fix surfacing the name of the provider somehow
|
||||
const providers = await tmbd.movies.watchProviders(movieId);
|
||||
const localProviders: { link: string } = (providers.results as any)[countryCode];
|
||||
console.log(localProviders)
|
||||
return localProviders;
|
||||
}
|
||||
}
|
||||
23
src/index.ts
Normal file
23
src/index.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { Elysia, file } from "elysia";
|
||||
import { api } from './api'
|
||||
import staticPlugin from "@elysia/static";
|
||||
import html from "@elysia/html";
|
||||
import Yuck from "./util/gin";
|
||||
|
||||
const HOST = process.env.HOST ?? 'localhost';
|
||||
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
||||
|
||||
const app = new Elysia()
|
||||
.use(api)
|
||||
.use(html())
|
||||
.get("/", () => (Yuck.renderDiscoverPage()))
|
||||
.get('/favicon.ico', file('public/assets/favicon.ico'))
|
||||
.use(staticPlugin({ prefix: '/assets', assets: 'public/assets' }))
|
||||
.listen({
|
||||
hostname: HOST,
|
||||
port: PORT
|
||||
})
|
||||
|
||||
console.log(
|
||||
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
|
||||
);
|
||||
85
src/util/gin.ts
Normal file
85
src/util/gin.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// TODO: Finish template engine and parse the data like god intended
|
||||
type GinNode = {
|
||||
|
||||
path: string;
|
||||
children: GinNode[];
|
||||
}
|
||||
|
||||
class Gin {
|
||||
|
||||
/**
|
||||
* Preprocess template files from a given path into some data structure that tags them and notes substitutable areas
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
setup(path: string) {}
|
||||
|
||||
/**
|
||||
* Creates HTML string from named template and supplied data
|
||||
*
|
||||
* @param name
|
||||
* @param mappings
|
||||
*/
|
||||
render(name: string, data: Record<string, string | number>): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs actual dependency tree. Parsing is prob gonna be some recursive business
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
private crawl(path: string): GinNode | undefined {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stopgap :(
|
||||
*/
|
||||
export default abstract class Yuck {
|
||||
static async renderDiscoverPage() {
|
||||
const discover = await Bun.file('public/pages/discover.html').text();
|
||||
const header = await Bun.file('public/templates/header.html').text();
|
||||
|
||||
const headerHtml = header
|
||||
.replaceAll(/{{\s*[^}]*?}}/g, '');
|
||||
|
||||
const discoverHtml = discover
|
||||
.replace('{{ template "header" . }}', headerHtml)
|
||||
.replaceAll(/{{\s*[^}]*?}}/g, '')
|
||||
|
||||
return discoverHtml;
|
||||
}
|
||||
|
||||
static async renderMoviePage(
|
||||
id: number,
|
||||
title: string,
|
||||
releaseYear: string,
|
||||
voteAverage: string,
|
||||
overview: string,
|
||||
posterPath: string
|
||||
) {
|
||||
const header = await Bun.file('public/templates/header.html').text();
|
||||
const card = await Bun.file('public/templates/card.html').text();
|
||||
|
||||
const headerHtml = header
|
||||
.replaceAll(/{{\s*[^}]*?}}/g, '');
|
||||
|
||||
const cardHtml = card
|
||||
.replaceAll('{{ .ID }}', id.toString())
|
||||
.replaceAll('{{ .Title }}', title)
|
||||
.replaceAll('{{ .ReleaseDate }}', releaseYear)
|
||||
.replaceAll('{{ .VoteAverage }}', voteAverage)
|
||||
.replaceAll('{{ .Overview }}', overview)
|
||||
.replaceAll('{{ .PosterPath }}', posterPath)
|
||||
.replaceAll(/{{\s*[^}]*?}}/g, '')
|
||||
|
||||
return [headerHtml, cardHtml].join("");
|
||||
}
|
||||
|
||||
static async renderProviderPage() {
|
||||
// NAH ima implement that in the engine
|
||||
return `<p>[look at me im a bunch of provider logos. yippeeee]</p>`
|
||||
}
|
||||
}
|
||||
103
tsconfig.json
Normal file
103
tsconfig.json
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "ES2022", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
"types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue