diff --git a/Dockerfile b/Dockerfile index 19ed17f..6d0c045 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,13 @@ # Installs Node image -FROM node:18-alpine as base +FROM node:18-buster as base # sets the working directory for any RUN, CMD, COPY command WORKDIR /app -# ENV PORT=3000 -# ENV DB_HOST=postgres -# ENV DB_USER=postgres -# ENV DB_NAME=db_name -# ENV DB_PASSWORD=password -# ENV DB_PORT=5432 -# ENV DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} - -# intentionally here only for temporary cache-busting test -# COPY ./client ./client - -# RUN apt update -# RUN apt -y install python3 - -# RUN apt-get update -# RUN apt-get -y install libsdl2-dev -# RUN apt-get -y install xorg-dev - -# COPY ./pico8 ./pico8 -# RUN echo "chmoding pico8" -# RUN chmod +x ./usr/bin/pico8 +# Install Python and pip +RUN apk add --update python3 py3-pip +RUN python3 -m ensurepip +RUN pip3 install --no-cache --upgrade pip setuptools # Copies stuff to cache for install COPY ./package.json ./package-lock.json tsconfig.json ./ diff --git a/TODO.md b/TODO.md index 946d6e2..905cea5 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,10 @@ # TODO ## MVP -- [ ] Update GH Workflow to be by push - [ ] Add version prop to picobook.json - [ ] "Compile" carts in server and save them to db - [ ] Load cart by URL in React +- [ ] Update GH Workflow to be by push ## Later - [ ] Update pico console handle diff --git a/pico8.dat b/pico8.dat new file mode 100644 index 0000000..310586c Binary files /dev/null and b/pico8.dat differ diff --git a/src/client/app.tsx b/src/client/app.tsx index 5efe6e2..6b90721 100644 --- a/src/client/app.tsx +++ b/src/client/app.tsx @@ -8,6 +8,7 @@ const App = (props: {}) => {
+

Picobook

); diff --git a/src/server/api/release.ts b/src/server/api/release.ts index 6bcda82..b84f55b 100644 --- a/src/server/api/release.ts +++ b/src/server/api/release.ts @@ -1,71 +1,37 @@ import { Type } from "@sinclair/typebox"; -import { FirRouteInput, FirRouteOptions } from "../util/routewrap.js"; -import fs from "fs"; +import { FirRouteInput, FirRouteOptions } from "../util/routewrap"; +import {git} from "../util/git.ts"; +import { randomUUID } from "crypto"; import path from "path"; -import git from "isomorphic-git"; -import http from "isomorphic-git/http/node"; import {fileURLToPath} from 'url'; -import { pico8 } from "../util/pico8.js"; +import { getCarts } from "../util/carts.ts"; const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const reposPath = path.resolve(__dirname, "..", "..", "..", "repos"); const method = "POST"; const url = "/api/release"; -// const payloadT = Type.Object({ -// png: Type.String(), -// }); - const payloadT = Type.Any(); -const repoPath = path.resolve(__dirname, "..", "..", "..", "repo"); - -// const {stdout, } = await execa(picoBinPath, ["/home/dylan/.lexaloffle/pico-8/carts/candles/candles.p8", "-export", path.join(__dirname, "result.js")]); -// const {stdout, } = await execa("ls", ["-la", picoDirPath]); -// console.log(stdout); - -// const {stdout: stdout2, } = await execa(picoBinPath, ["-x"]); -// console.log(stdout2); - const handler = async ({payload}: FirRouteInput) => { const {manifest, token} = payload; - if (!fs.existsSync(repoPath)) { - fs.mkdirSync(repoPath, {recursive: true}) - } - console.log(manifest); - console.log("cloning..."); + + const uuid = randomUUID(); + const repoPath = path.join(reposPath, uuid); + await git.clone({ - fs, - http, - // headers: { - // "Authorization": `Bearer ${token}`, - // }, - onAuth() { - return { - username: 'x-access-token', - password: token, - } - }, - dir: repoPath, - url: manifest.repo, + from: manifest.repo, + to: repoPath, + auth: token, }); - console.log("cloned"); - console.log("read local manifest"); - console.log("manifest exists: ", fs.existsSync(path.join(repoPath, "picobook.json"))); - console.log("main exists: ", fs.existsSync(path.join(repoPath, manifest.main))); - // const {stdout} = await execa("ls", ["-la", picoDirPath], {shell: true}); - // console.log(stdout); - const exported=await pico8.export(path.join(repoPath, manifest.main), path.join(repoPath, "result.js")); - console.log((exported as any).stdout); - // await execa(picoBinPath, [path.join(repoPath, manifest.main), "-export", path.join(repoPath, "result.js")]); - // await execa(picoBinPath, [path.join(repoPath, manifest.main), "-export", path.join(repoPath, "result.png")]); - const js = await fs.promises.readFile(path.join(repoPath, "result.js"), "utf8"); - // const png = Buffer.from(await fs.promises.readFile(path.join(repoPath, "result.png"))).toString("base64"); - fs.promises.rm(repoPath, {recursive: true, force: true}); + + const carts = await getCarts(manifest.carts); + console.log({ manifest, - js, - // png, + carts, }); + return true; }; diff --git a/src/server/index.ts b/src/server/index.ts index f0304a5..010f12f 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -3,8 +3,15 @@ import Fastify from 'fastify' import fastifyStatic from '@fastify/static' import { routeList } from "./routelist.ts"; import { route } from "./util/routewrap.ts"; +import { git } from './util/git.ts'; +import path from "path"; +import {fileURLToPath} from 'url'; +const __dirname = fileURLToPath(new URL('.', import.meta.url)); -console.log(process.env["DATABASE_URL"]); +await git.clone({ + from: "https://github.com/thisismypassport/shrinko8/tree/v1.1.2", + to: path.resolve(__dirname, "shrinko8"), +}); const server = Fastify({ logger: true diff --git a/src/server/util/carts.ts b/src/server/util/carts.ts new file mode 100644 index 0000000..a06a822 --- /dev/null +++ b/src/server/util/carts.ts @@ -0,0 +1,40 @@ +import { randomUUID } from "crypto"; +import { shrinko8 } from "./shrinko8"; +import path from "path"; +import fs from "fs"; +import { fileURLToPath } from "url"; +const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const outputDirPath = path.resolve(__dirname, "..", "..", "..", "output"); + +const getRom = async (inputFile: string) => { + const uuid = randomUUID(); + const dir = path.join(outputDirPath, uuid); + const outputFile = path.join(dir, inputFile+".js"); + + await shrinko8({ + inputFile, + outputFile, + }); + + const js = await fs.promises.readFile(outputFile, "utf8"); + + await fs.promises.rm(dir, {recursive: true, force: true}); + + const match = js.match(/\b_cartdat\s*=\s*(\[.*\])/); + if (!match) { + throw Error("Could not properly parse js file to find _cartdat"); + } + + return JSON.parse(match[1]) as number[] +} + +const getCart = async (inputFile: string) => { + return { + name: inputFile, + rom: await getRom(inputFile), + } +} + +export const getCarts = async (inputFiles: string[]) => { + return await Promise.all(inputFiles.map(getCart)); +} \ No newline at end of file diff --git a/src/server/util/git.ts b/src/server/util/git.ts new file mode 100644 index 0000000..64914e2 --- /dev/null +++ b/src/server/util/git.ts @@ -0,0 +1,27 @@ +import fs from "fs"; +import isogit from "isomorphic-git"; +import http from "isomorphic-git/http/node"; + +const clone = async (options: { + from: string; + to: string; + auth?: string; +}) => { + fs.mkdirSync(options.to, {recursive: true}); + await isogit.clone({ + fs, + http, + onAuth() { + return { + username: 'x-access-token', + password: options.auth, + } + }, + dir: options.to, + url: options.from, + }); +} + +export const git = { + clone, +} \ No newline at end of file diff --git a/src/server/util/shrinko8.ts b/src/server/util/shrinko8.ts new file mode 100644 index 0000000..cdef05f --- /dev/null +++ b/src/server/util/shrinko8.ts @@ -0,0 +1,18 @@ +import { execa } from "execa"; +import path from "path"; +import {fileURLToPath} from 'url'; + +const __dirname = fileURLToPath(new URL('.', import.meta.url)); + +const shrinko8Path = path.resolve(__dirname, "../shrinko8"); +const pico8DatPath = path.resolve(__dirname, "../../pico8.dat"); + +export const shrinko8 = async (props: { + inputFile: string; + outputFile: string; + options?: string[]; +}) => { + const {inputFile, outputFile, options = []} = props; + return await execa("python3", [shrinko8Path, inputFile, outputFile, "--pico8-dat", pico8DatPath, ...options]) +} +