view update
This commit is contained in:
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.env
|
.env
|
||||||
src/data/data.db
|
.svelte-kit/
|
||||||
src/view/.svelte-kit
|
build/
|
||||||
|
|||||||
+4
-3
@@ -20,7 +20,8 @@ RUN apt-get update -qq && \
|
|||||||
|
|
||||||
# Install node modules
|
# Install node modules
|
||||||
COPY --link package.json .
|
COPY --link package.json .
|
||||||
RUN bun install --production
|
# RUN bun install --production
|
||||||
|
RUN bun install
|
||||||
|
|
||||||
# Copy application code
|
# Copy application code
|
||||||
COPY --link . .
|
COPY --link . .
|
||||||
@@ -34,5 +35,5 @@ COPY --from=build /app /app
|
|||||||
RUN apt-get update && apt-get install -y sqlite3 && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y sqlite3 && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Start the server by default, this can be overwritten at runtime
|
# Start the server by default, this can be overwritten at runtime
|
||||||
CMD [ "bun", "run", "db:seed:prod" ]
|
CMD [ "bun", "--bun", "build" ]
|
||||||
CMD [ "bun", "run", "start" ]
|
CMD [ "bun", "./build/index.js" ]
|
||||||
|
|||||||
@@ -154,7 +154,7 @@
|
|||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.5.1", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q=="],
|
"@types/node": ["@types/node@24.5.2", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="],
|
"@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="],
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
|
|
||||||
"devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="],
|
"devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="],
|
||||||
|
|
||||||
"elysia": ["elysia@1.4.5", "", { "dependencies": { "cookie": "^1.0.2", "elysia": "1.4.3-beta.0", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-slSMNyAuh6lFEjEwSkSkpzbUOLCtx6hOw4AYhpGOHqczu27eqxHbNtRtIPQuXDq6sqJ1ezXgw3gUjoasZozWRg=="],
|
"elysia": ["elysia@1.4.6", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-u2CorXLPs5ZXyWP+tQR+bgka/lJA4vNpB8lDE2w/sTmdaIwoPQmHEL4J3ai6OAlluWR1kfG7T9gO3EYT9D8viQ=="],
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
|
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@
|
|||||||
|
|
||||||
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
|
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
|
||||||
|
|
||||||
"svelte": ["svelte@5.38.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-UY+OhrWK7WI22bCZ00P/M3HtyWgwJPi9IxSRkoAE2MeAy6kl7ZlZWJZ8RaB+X4KD/G+wjis+cGVnVYaoqbzBqg=="],
|
"svelte": ["svelte@5.39.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-x4Me4TgiNprpLugcXyKbcGQhHdjWpITZzSeegv3jjIyA4jObVKBhNchGGDv257Eeolg3vUUSa4n2HGFMYNaPvg=="],
|
||||||
|
|
||||||
"svelte-adapter-bun": ["svelte-adapter-bun@0.5.2", "", { "dependencies": { "tiny-glob": "^0.2.9" } }, "sha512-xEtFgaal6UgrCwwkSIcapO9kopoFNUYCYqyKCikdqxX9bz2TDYnrWQZ7qBnkunMxi1HOIERUCvTcebYGiarZLA=="],
|
"svelte-adapter-bun": ["svelte-adapter-bun@0.5.2", "", { "dependencies": { "tiny-glob": "^0.2.9" } }, "sha512-xEtFgaal6UgrCwwkSIcapO9kopoFNUYCYqyKCikdqxX9bz2TDYnrWQZ7qBnkunMxi1HOIERUCvTcebYGiarZLA=="],
|
||||||
|
|
||||||
@@ -264,14 +264,12 @@
|
|||||||
|
|
||||||
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
||||||
|
|
||||||
"vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="],
|
"vite": ["vite@7.1.6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ=="],
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
||||||
|
|
||||||
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
||||||
|
|
||||||
"elysia/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
"elysia/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||||
|
|
||||||
"elysia/elysia": ["elysia@1.4.3-beta.0", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-UzanGZSqoKKcKgg+I4YB+ZOGeJNA7mlA8JPj7klYi0LDVcj/vtXKGRmsp4jEzZO+LjSpFuYTZcwHi4rCnvJj1w=="],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ primary_region = 'ord'
|
|||||||
[build]
|
[build]
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
PORT = '8080'
|
PORT = '3000'
|
||||||
|
|
||||||
[http_service]
|
[http_service]
|
||||||
internal_port = 8080
|
internal_port = 3000
|
||||||
force_https = true
|
force_https = true
|
||||||
auto_stop_machines = 'stop'
|
auto_stop_machines = 'stop'
|
||||||
auto_start_machines = true
|
auto_start_machines = true
|
||||||
|
|||||||
+6
-8
@@ -11,14 +11,12 @@
|
|||||||
"vite": "^7.0.4"
|
"vite": "^7.0.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"db:seed:dev": "sqlite3 ./data/data.db < ./data/seed.sql",
|
"dev": "vite dev",
|
||||||
"db:seed:prod": "sqlite3 /data/data.db < ./data/seed.sql",
|
"build": "vite build",
|
||||||
"dev": "cd ./src/view && vite dev",
|
"preview": "vite preview",
|
||||||
"build": "cd ./src/view && vite build",
|
"prepare": "svelte-kit sync || echo ''",
|
||||||
"preview": "cd ./src/view && vite preview",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"prepare": "cd ./src/view && svelte-kit sync || echo ''",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||||
"check": "cd ./src/view && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
||||||
"check:watch": "cd ./src/view && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elysiajs/cors": "^1.4.0",
|
"@elysiajs/cors": "^1.4.0",
|
||||||
|
|||||||
-88
@@ -1,88 +0,0 @@
|
|||||||
import { Elysia } from "elysia";
|
|
||||||
import { cors } from "@elysiajs/cors";
|
|
||||||
import { ActivityStandards, LevelCalculator, Standards } from "./services/calculator/main";
|
|
||||||
import { ActivityPerformance, Player } from "./services/calculator/util";
|
|
||||||
import { Printful } from "./services/commerce/printful";
|
|
||||||
import { Webflow } from "./services/commerce/webflow";
|
|
||||||
import rawStandards from "./data/standards.json" assert { type: "json" }
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { dirname, join } from 'path';
|
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
export const app = new Elysia({ prefix: "/api" })
|
|
||||||
.use(cors())
|
|
||||||
|
|
||||||
.get("/", () => "Hello world")
|
|
||||||
|
|
||||||
// CALCULATOR
|
|
||||||
|
|
||||||
.post("/calculate", async ({ body }) => {
|
|
||||||
const MAIN_STANDARDS = new Standards(rawStandards as ActivityStandards);
|
|
||||||
interface CalcRequest {
|
|
||||||
player: Player;
|
|
||||||
activityPerformances: ActivityPerformance[];
|
|
||||||
}
|
|
||||||
const { player, activityPerformances } = body as CalcRequest;
|
|
||||||
const levelCalculator = new LevelCalculator(MAIN_STANDARDS);
|
|
||||||
return { levels: levelCalculator.calculate(player, activityPerformances) };
|
|
||||||
})
|
|
||||||
|
|
||||||
// COMMERCE
|
|
||||||
|
|
||||||
.post("/products/sync", async () => {
|
|
||||||
const printfulProducts = await Printful.Products.getAll();
|
|
||||||
for (const p of printfulProducts) {
|
|
||||||
const exists = await Webflow.Products.exists(p.sync_product.external_id);
|
|
||||||
if (exists) await Webflow.Products.updateUsingPrintful(p);
|
|
||||||
else await Webflow.Products.createUsingPrintful(p);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// DATA
|
|
||||||
|
|
||||||
.get("/data/standards", async () => {
|
|
||||||
try {
|
|
||||||
return Bun.file(join(__dirname, "data/standards.json")).json();
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return new Response("Failed to load standards", { status: 500 });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// WEBHOOKS
|
|
||||||
|
|
||||||
.post("/webhook/printful", async ({ body, set }) => {
|
|
||||||
const payload = body as Printful.Webhook.EventPayload;
|
|
||||||
try {
|
|
||||||
switch (payload.type) {
|
|
||||||
case Printful.Webhook.Event.ProductUpdated: {
|
|
||||||
const prod = await Printful.Products.get(payload.data.sync_product.id);
|
|
||||||
const exists = await Webflow.Products.exists(prod.sync_product.external_id);
|
|
||||||
if (exists) await Webflow.Products.updateUsingPrintful(prod);
|
|
||||||
else await Webflow.Products.createUsingPrintful(prod);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Printful.Webhook.Event.ProductDeleted: {
|
|
||||||
await Webflow.Products.remove(payload.data.sync_product.external_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
set.status = 500;
|
|
||||||
return { error: "internal_error" };
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
app.listen(3000);
|
|
||||||
console.log(
|
|
||||||
`Listening at ${app.server?.hostname}:${app.server?.port}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type App = typeof app;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS product_records (
|
|
||||||
webflowProductId INTEGER NOT NULL,
|
|
||||||
printfulProductId INTEGER NOT NULL,
|
|
||||||
UNIQUE(webflowProductId, printfulProductId)
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { treaty } from "@elysiajs/eden";
|
||||||
|
import { Elysia } from "elysia";
|
||||||
|
import { cors } from "@elysiajs/cors";
|
||||||
|
import { LevelCalculator, Standards, type ActivityStandards } from "$lib/services/calculator/main";
|
||||||
|
import type { ActivityPerformance, Player } from "$lib/services/calculator/util";
|
||||||
|
import { Webflow } from "$lib/services/commerce/webflow";
|
||||||
|
import { Printful } from "$lib/services/commerce/printful";
|
||||||
|
import rawStandards from "$lib/data/standards.json" assert { type: "json" }
|
||||||
|
|
||||||
|
export const app = new Elysia({ prefix: "/api" })
|
||||||
|
.use(cors({
|
||||||
|
origin: '*'
|
||||||
|
}))
|
||||||
|
|
||||||
|
.get("/", () => "Hello world")
|
||||||
|
|
||||||
|
// CALCULATOR
|
||||||
|
|
||||||
|
.post("/calculate", async ({ body }) => {
|
||||||
|
const MAIN_STANDARDS = new Standards(rawStandards as ActivityStandards);
|
||||||
|
interface CalcRequest {
|
||||||
|
player: Player;
|
||||||
|
activityPerformances: ActivityPerformance[];
|
||||||
|
}
|
||||||
|
const { player, activityPerformances } = body as CalcRequest;
|
||||||
|
const levelCalculator = new LevelCalculator(MAIN_STANDARDS);
|
||||||
|
return { levels: levelCalculator.calculate(player, activityPerformances) };
|
||||||
|
})
|
||||||
|
|
||||||
|
// COMMERCE
|
||||||
|
|
||||||
|
.post("/products/sync", async () => {
|
||||||
|
const printfulProducts = await Printful.Products.getAll();
|
||||||
|
for (const p of printfulProducts) {
|
||||||
|
const exists = await Webflow.Products.exists(p.sync_product.external_id);
|
||||||
|
if (exists) await Webflow.Products.updateUsingPrintful(p);
|
||||||
|
else await Webflow.Products.createUsingPrintful(p);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
})
|
||||||
|
|
||||||
|
// WEBHOOKS
|
||||||
|
|
||||||
|
.post("/webhook/printful", async ({ body, set }) => {
|
||||||
|
const payload = body as Printful.Webhook.EventPayload;
|
||||||
|
try {
|
||||||
|
switch (payload.type) {
|
||||||
|
case Printful.Webhook.Event.ProductUpdated: {
|
||||||
|
const prod = await Printful.Products.get(payload.data.sync_product.id);
|
||||||
|
const exists = await Webflow.Products.exists(prod.sync_product.external_id);
|
||||||
|
if (exists) await Webflow.Products.updateUsingPrintful(prod);
|
||||||
|
else await Webflow.Products.createUsingPrintful(prod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Printful.Webhook.Event.ProductDeleted: {
|
||||||
|
await Webflow.Products.remove(payload.data.sync_product.external_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
set.status = 500;
|
||||||
|
return { error: "internal_error" };
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
||||||
|
export type App = typeof app;
|
||||||
|
|
||||||
|
const apiWrapper = treaty<App>(app);
|
||||||
|
export const api = apiWrapper.api;
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,4 +1,4 @@
|
|||||||
import { Activity, Attribute, Player, Gender, ActivityPerformance, lbToKg, StandardUnit } from "./util";
|
import { Activity, Attribute, Gender, lbToKg, type ActivityPerformance, type Player, type StandardUnit } from "./util";
|
||||||
|
|
||||||
// SOURCES
|
// SOURCES
|
||||||
// Squat, Bench, Dead Lift:
|
// Squat, Bench, Dead Lift:
|
||||||
@@ -434,7 +434,7 @@ export class Standards {
|
|||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLevels = {};
|
const newLevels: Levels = {};
|
||||||
let j = 1;
|
let j = 1;
|
||||||
for (let k = 0; k < Object.keys(levels).length; ++k) {
|
for (let k = 0; k < Object.keys(levels).length; ++k) {
|
||||||
const currLevel = Object.keys(levels)[k];
|
const currLevel = Object.keys(levels)[k];
|
||||||
@@ -489,7 +489,7 @@ export class Standards {
|
|||||||
|
|
||||||
const lerp = (lvl: string) => (lower[lvl] as number) + ((upper[lvl] as number) - (lower[lvl] as number)) * ratio;
|
const lerp = (lvl: string) => (lower[lvl] as number) + ((upper[lvl] as number) - (lower[lvl] as number)) * ratio;
|
||||||
|
|
||||||
const interpolatedLevels = {};
|
const interpolatedLevels: Levels = {};
|
||||||
for (const lvl in lower) {
|
for (const lvl in lower) {
|
||||||
interpolatedLevels[lvl] = lerp(lvl);
|
interpolatedLevels[lvl] = lerp(lvl);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Metrics } from "../calculator/main";
|
import { type Metrics } from "$lib/services/calculator/main";
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
// DATA MODELS
|
// DATA MODELS
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Printful } from "./printful"
|
import { Printful } from "$lib/services/commerce/printful"
|
||||||
|
|
||||||
export namespace Webflow {
|
export namespace Webflow {
|
||||||
export const API_SITES_URL = `https://api.webflow.com/v2/sites/${Bun.env.WEBFLOW_SITE_ID}`;
|
export const API_SITES_URL = `https://api.webflow.com/v2/sites/${Bun.env.WEBFLOW_SITE_ID}`;
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import { Activity, ActivityPerformance, feetToCm, Gender, inchesToCm, lbToKg, minToMs, Player, secToMs } from "../services/calculator/util";
|
import { Activity, feetToCm, Gender, inchesToCm, lbToKg, minToMs, secToMs, type ActivityPerformance, type Player } from "$lib/services/calculator/util";
|
||||||
import { ActivityStandards, LevelCalculator, Standards } from "../services/calculator/main"
|
|
||||||
import rawStandards from "../data/standards.json" assert { type: "json" }
|
|
||||||
|
|
||||||
const player: Player = {
|
const player: Player = {
|
||||||
metrics: {
|
metrics: {
|
||||||
@@ -41,6 +39,8 @@ const computedPerformances: ActivityPerformance[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const standards = new Stand();
|
||||||
|
|
||||||
// const newStandards: Standards = {
|
// const newStandards: Standards = {
|
||||||
// "Back Squat": [],
|
// "Back Squat": [],
|
||||||
// "Deadlift": [],
|
// "Deadlift": [],
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import {
|
||||||
Standards,
|
Standards,
|
||||||
|
type ActivityStandards,
|
||||||
type Standard,
|
type Standard,
|
||||||
} from "../../../services/calculator/main";
|
} from "$lib/services/calculator/main";
|
||||||
|
import allStandardsRaw from "$lib/data/standards.json" assert { type: "json" };
|
||||||
import {
|
import {
|
||||||
Activity,
|
Activity,
|
||||||
Gender,
|
Gender,
|
||||||
@@ -10,10 +12,7 @@
|
|||||||
lbToKg,
|
lbToKg,
|
||||||
msToTime,
|
msToTime,
|
||||||
range,
|
range,
|
||||||
} from "../../../services/calculator/util";
|
} from "$lib/services/calculator/util";
|
||||||
|
|
||||||
// data
|
|
||||||
const { data } = $props();
|
|
||||||
|
|
||||||
const selected = $state({
|
const selected = $state({
|
||||||
activity: Activity.BenchPress,
|
activity: Activity.BenchPress,
|
||||||
@@ -24,7 +23,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const allStandards = $derived(
|
const allStandards = $derived(
|
||||||
new Standards(data.allStandardsRaw, { maxLevel: selected.maxLevel }),
|
new Standards(allStandardsRaw as ActivityStandards, {
|
||||||
|
maxLevel: selected.maxLevel,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const getFormattedLevelValue = (
|
const getFormattedLevelValue = (
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { app } from "../../../../api"
|
import { app } from "$lib/api"
|
||||||
|
|
||||||
type RequestHandler = (v: { request: Request }) => Response | Promise<Response>
|
type RequestHandler = (v: { request: Request }) => Response | Promise<Response>
|
||||||
export const fallback: RequestHandler = ({ request }) => app.handle(request)
|
export const fallback: RequestHandler = ({ request }) => app.handle(request)
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { treaty } from "@elysiajs/eden";
|
|
||||||
import { app, type App } from "../../../api";
|
|
||||||
|
|
||||||
const apiWrapper = treaty<App>(app);
|
|
||||||
export const api = apiWrapper.api;
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { api } from "$lib";
|
|
||||||
import type { ActivityStandards } from "../../../services/calculator/main";
|
|
||||||
import type { LayoutServerLoad } from "./$types";
|
|
||||||
|
|
||||||
export const load: LayoutServerLoad = async ({ }) => {
|
|
||||||
const { data: allStandardsRaw } = await api.data.standards.get();
|
|
||||||
|
|
||||||
return {
|
|
||||||
allStandardsRaw: allStandardsRaw as ActivityStandards
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -2,5 +2,10 @@ import { sveltekit } from '@sveltejs/kit/vite';
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()]
|
plugins: [sveltekit()],
|
||||||
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 8080,
|
||||||
|
allowedHosts: ["blade-and-brawn.fly.dev"]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user