This commit is contained in:
dylan 2024-03-25 00:29:43 -07:00
parent 334c09df7c
commit f960083e94
8 changed files with 213 additions and 26 deletions

View File

@ -1,7 +1,7 @@
version: '3.9'
services:
app:
container_name: app
container_name: picobook-app
image: node
build:
context: .
@ -16,7 +16,7 @@ services:
profiles: ["prod"]
db:
container_name: postgres
container_name: picobook-postgres
image: postgres
env_file:
.env

166
package-lock.json generated
View File

@ -11,13 +11,16 @@
"dependencies": {
"@databases/pg": "^5.4.1",
"@fastify/cookie": "^9.0.4",
"@fastify/secure-session": "^7.1.0",
"@fastify/static": "^6.10.2",
"@firebox/components": "^0.1.5",
"@firebox/tsutil": "^0.1.2",
"@sinclair/typebox": "^0.31.5",
"dotenv": "^16.3.1",
"dotenv": "^16.4.5",
"fastify": "^4.22.0",
"react-pico-8": "^4.1.0"
"react-pico-8": "^4.1.0",
"react-router-dom": "^6.18.0",
"uuid": "^9.0.1"
},
"devDependencies": {
"@databases/pg-migrations": "^5.0.2",
@ -25,6 +28,7 @@
"@emotion/react": "^11.11.1",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"@types/uuid": "^9.0.7",
"esbuild": "^0.19.2",
"nodemon": "^3.0.1",
"react": "^18.2.0",
@ -956,6 +960,19 @@
"fast-json-stringify": "^5.7.0"
}
},
"node_modules/@fastify/secure-session": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@fastify/secure-session/-/secure-session-7.1.0.tgz",
"integrity": "sha512-x0ZW57+sf6fQaL05B3n64m7DRe81NAtFAKpCKKuqdX9FDqzOH5uQbfDDfVQy2/qhDn3N343RMlNtY1iQyvvA9A==",
"dependencies": {
"@fastify/cookie": "^9.0.4",
"fastify-plugin": "^4.0.0",
"sodium-native": "^4.0.0"
},
"bin": {
"secure-session": "genkey.js"
}
},
"node_modules/@fastify/send": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz",
@ -1139,6 +1156,14 @@
"node": ">=8"
}
},
"node_modules/@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@sinclair/typebox": {
"version": "0.31.5",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.5.tgz",
@ -1217,6 +1242,12 @@
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
"dev": true
},
"node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
"dev": true
},
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@ -1822,14 +1853,14 @@
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"version": "16.4.5",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/motdotla/dotenv?sponsor=1"
"url": "https://dotenvx.com"
}
},
"node_modules/emoji-regex": {
@ -2983,6 +3014,16 @@
"thenify-all": "^1.0.0"
}
},
"node_modules/node-gyp-build": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/nodemon": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz",
@ -3632,6 +3673,36 @@
"react": "^0.13.0 || ^0.14.0 || >=15"
}
},
"node_modules/react-router": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"dependencies": {
"@remix-run/router": "1.15.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
"dependencies": {
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -3883,6 +3954,15 @@
"node": ">=10"
}
},
"node_modules/sodium-native": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz",
"integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==",
"hasInstallScript": true,
"dependencies": {
"node-gyp-build": "^4.8.0"
}
},
"node_modules/sonic-boom": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
@ -4186,6 +4266,18 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@ -4985,6 +5077,16 @@
"fast-json-stringify": "^5.7.0"
}
},
"@fastify/secure-session": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@fastify/secure-session/-/secure-session-7.1.0.tgz",
"integrity": "sha512-x0ZW57+sf6fQaL05B3n64m7DRe81NAtFAKpCKKuqdX9FDqzOH5uQbfDDfVQy2/qhDn3N343RMlNtY1iQyvvA9A==",
"requires": {
"@fastify/cookie": "^9.0.4",
"fastify-plugin": "^4.0.0",
"sodium-native": "^4.0.0"
}
},
"@fastify/send": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz",
@ -5125,6 +5227,11 @@
"resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.1.tgz",
"integrity": "sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA=="
},
"@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w=="
},
"@sinclair/typebox": {
"version": "0.31.5",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.5.tgz",
@ -5203,6 +5310,12 @@
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
"dev": true
},
"@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
"dev": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@ -5638,9 +5751,9 @@
"dev": true
},
"dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ=="
"version": "16.4.5",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg=="
},
"emoji-regex": {
"version": "8.0.0",
@ -6498,6 +6611,11 @@
"thenify-all": "^1.0.0"
}
},
"node-gyp-build": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og=="
},
"nodemon": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz",
@ -6967,6 +7085,23 @@
"integrity": "sha512-/Hi0rH+IJ3ifuoWhPvQkUIwFJjRGcccqoa+MQeB4ceb/u5jRt/hSRS7XD5BsFC79I2VJE1Jh7kyugdDraHFJkg==",
"requires": {}
},
"react-router": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"requires": {
"@remix-run/router": "1.15.3"
}
},
"react-router-dom": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
"requires": {
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
}
},
"readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -7149,6 +7284,14 @@
"semver": "^7.5.3"
}
},
"sodium-native": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz",
"integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==",
"requires": {
"node-gyp-build": "^4.8.0"
}
},
"sonic-boom": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
@ -7365,6 +7508,11 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
},
"v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",

View File

@ -5,16 +5,16 @@
"description": "Firstack is a template repo for a tech stack.",
"main": "index.js",
"scripts": {
"makeuser": "npm run withenv ./scripts/makeuser.ts",
"dev-docker": "docker compose --profile dev up -d",
"dev-server": "echo \"starting server\" && npm run dev-ts ./src/server/index.ts",
"dev-ts": "nodemon --require 'dotenv/config'",
"dev-watch-client": "ts-node ./scripts/watch.ts",
"dev-server": "echo \"starting server\" && npm run withenv ./src/server/index.ts",
"dev-watch-client": "npm run withenv ./scripts/watch.ts",
"dev-migrate": "source ./.env && pg-migrations apply --directory ./src/database/migrations",
"prod-migrate": "pg-migrations apply --directory ./src/database/migrations",
"prod-build-client": "ts-node ./scripts/build.ts",
"prod-build-client": "npm run withenv ./scripts/build.ts",
"prod-docker": "docker compose --profile prod up -d",
"prod-start": "echo \"building frontend\" && npm run prod-build-client && echo \"running migrations\" && npm run prod-migrate && echo \"starting server\" && npm run prod-ts ./src/server/index.ts",
"prod-ts": "ts-node --require 'dotenv/config'",
"prod-start": "echo \"building frontend\" && npm run prod-build-client && echo \"${DATABASE_URL}\" && echo \"running migrations\" && npm run prod-migrate && echo \"starting server\" && npm run withenv ./src/server/index.ts",
"withenv": "tsx ./scripts/run-with-env.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@ -26,12 +26,15 @@
"dependencies": {
"@databases/pg": "^5.4.1",
"@fastify/cookie": "^9.0.4",
"@fastify/secure-session": "^7.1.0",
"@fastify/static": "^6.10.2",
"@firebox/components": "^0.1.5",
"@firebox/tsutil": "^0.1.2",
"@sinclair/typebox": "^0.31.5",
"dotenv": "^16.3.1",
"dotenv": "^16.4.5",
"fastify": "^4.22.0",
"react-router-dom": "^6.18.0",
"uuid": "^9.0.1",
"react-pico-8": "^4.1.0"
},
"devDependencies": {
@ -40,6 +43,7 @@
"@emotion/react": "^11.11.1",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"@types/uuid": "^9.0.7",
"esbuild": "^0.19.2",
"nodemon": "^3.0.1",
"react": "^18.2.0",

11
scripts/run-with-env.ts Normal file
View File

@ -0,0 +1,11 @@
import dotenv from 'dotenv';
import * as url from 'url';
import * as path from 'path';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const dotenvPath = path.join(__dirname, "..", ".env");
dotenv.config({
path: dotenvPath,
});
if (process.argv[2]) {
import(path.join(process.cwd(), process.argv[2]));
}

View File

@ -1,8 +1,6 @@
CREATE TABLE games (
CREATE TABLE repos (
id text,
name text, -- user defined
repo_fullname text, -- e.g. "username/reponame"
repo_hosttype text, -- "github", "gitea", "gitlab", ...
repo_token text, -- an api auth token to read from the repo
user_id text
)

View File

@ -1,7 +1,7 @@
CREATE TABLE game_instances (
CREATE TABLE releases (
id text,
game_id text,
cart_data text,
created_at time,
is_official boolean
repo_id text,
release_number integer,
cart_png_base64 text,
created_at time
)

24
src/server/api/release.ts Normal file
View File

@ -0,0 +1,24 @@
import { Type } from "@sinclair/typebox";
import { FirRouteInput, FirRouteOptions } from "../util/routewrap.js";
const method = "POST";
const url = "/release";
// const payloadT = Type.Object({
// png: Type.String(),
// });
const payloadT = Type.Any();
const handler = ({payload}: FirRouteInput<typeof payloadT>) => {
const {png} = payload;
console.log(png);
// return payload;
};
export default {
method,
url,
payloadT,
handler,
} as const satisfies FirRouteOptions<typeof payloadT>;

View File

@ -1,9 +1,11 @@
import echo from "./api/echo.ts";
import release from "./api/release.ts";
import webhook from "./api/webhook.ts";
export const routeList = [
echo,
webhook,
release,
];
export type RouteList = typeof routeList;