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: {}) => {
);
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])
+}
+