save to db
This commit is contained in:
parent
8b987bc589
commit
7874167582
@ -1,5 +1,4 @@
|
|||||||
import { css } from "@emotion/css";
|
import { css } from "@emotion/css";
|
||||||
import { Center, Cover, Stack } from "@firebox/components";
|
|
||||||
import { Pico8Console } from "./pico8-client/Pico8Console";
|
import { Pico8Console } from "./pico8-client/Pico8Console";
|
||||||
import testcarts from "./testcarts";
|
import testcarts from "./testcarts";
|
||||||
|
|
||||||
|
@ -4,10 +4,11 @@ DROP TABLE releases;
|
|||||||
|
|
||||||
CREATE TABLE releases (
|
CREATE TABLE releases (
|
||||||
id text,
|
id text,
|
||||||
picobook_version int,
|
|
||||||
repo text,
|
repo text,
|
||||||
|
author text,
|
||||||
slug text,
|
slug text,
|
||||||
version text,
|
version text,
|
||||||
carts json,
|
carts json,
|
||||||
title text,
|
manifest json,
|
||||||
|
created_at time
|
||||||
);
|
);
|
42
src/server/api/getRelease.ts
Normal file
42
src/server/api/getRelease.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Type } from "@sinclair/typebox";
|
||||||
|
import { FirRouteInput, FirRouteOptions } from "../util/routewrap.ts";
|
||||||
|
import { getRelease, getReleases } from "../dbal/dbal.ts";
|
||||||
|
|
||||||
|
const method = "GET";
|
||||||
|
const url = "/api/release";
|
||||||
|
|
||||||
|
const payloadT = Type.Any();
|
||||||
|
|
||||||
|
const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
||||||
|
const {author, slug, version} = payload;
|
||||||
|
|
||||||
|
if (typeof author !== "string") {
|
||||||
|
return {
|
||||||
|
release: null,
|
||||||
|
versions: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (typeof slug !== "string") {
|
||||||
|
return {
|
||||||
|
release: null,
|
||||||
|
versions: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const release = await getRelease({author, slug, version});
|
||||||
|
const releases = await getReleases({author, slug});
|
||||||
|
|
||||||
|
const versions = releases.map(r => r.version);
|
||||||
|
|
||||||
|
return {
|
||||||
|
release,
|
||||||
|
versions,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
payloadT,
|
||||||
|
handler,
|
||||||
|
} as const satisfies FirRouteOptions<typeof payloadT>;
|
@ -1,11 +1,12 @@
|
|||||||
import { Type } from "@sinclair/typebox";
|
import { Type } from "@sinclair/typebox";
|
||||||
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
||||||
import { FirRouteInput, FirRouteOptions } from "../util/routewrap";
|
import { FirRouteInput, FirRouteOptions } from "../util/routewrap";
|
||||||
import {git} from "../util/git.ts";
|
import {git} from "../util/git.ts";
|
||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {fileURLToPath} from 'url';
|
import {fileURLToPath} from 'url';
|
||||||
import { getCarts } from "../util/carts.ts";
|
import { getCarts } from "../util/carts.ts";
|
||||||
|
import { getRelease, insertRelease } from "../dbal/dbal.ts";
|
||||||
|
import { ManifestType } from "../types.ts";
|
||||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||||
const reposPath = path.resolve(__dirname, "..", "..", "..", "repos");
|
const reposPath = path.resolve(__dirname, "..", "..", "..", "repos");
|
||||||
|
|
||||||
@ -14,19 +15,6 @@ const url = "/api/release";
|
|||||||
|
|
||||||
const payloadT = Type.Any();
|
const payloadT = Type.Any();
|
||||||
|
|
||||||
const manifestT = Type.Object({
|
|
||||||
picobook_version: Type.Number(),
|
|
||||||
id: Type.String(),
|
|
||||||
version: Type.String(),
|
|
||||||
carts: Type.Array(Type.String()),
|
|
||||||
repo: Type.String(),
|
|
||||||
title: Type.Optional(Type.String()),
|
|
||||||
author: Type.Optional(Type.String()),
|
|
||||||
readme: Type.Optional(Type.String()),
|
|
||||||
});
|
|
||||||
|
|
||||||
const ManifestType = TypeCompiler.Compile(manifestT)
|
|
||||||
|
|
||||||
const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
||||||
const {manifest, token} = payload;
|
const {manifest, token} = payload;
|
||||||
|
|
||||||
@ -34,6 +22,11 @@ const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const release = await getRelease({author: manifest.author, slug: manifest.id, version: manifest.version});
|
||||||
|
if (release) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const uuid = randomUUID();
|
const uuid = randomUUID();
|
||||||
const repoPath = path.join(reposPath, uuid);
|
const repoPath = path.join(reposPath, uuid);
|
||||||
|
|
||||||
@ -45,6 +38,11 @@ const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
|||||||
|
|
||||||
const carts = await getCarts(repoPath, manifest.carts);
|
const carts = await getCarts(repoPath, manifest.carts);
|
||||||
|
|
||||||
|
insertRelease({
|
||||||
|
manifest,
|
||||||
|
carts,
|
||||||
|
});
|
||||||
|
|
||||||
console.log({
|
console.log({
|
||||||
manifest,
|
manifest,
|
||||||
carts,
|
carts,
|
||||||
|
@ -1 +1,89 @@
|
|||||||
// Database Access Layer stuff goes here
|
// Database Access Layer stuff goes here
|
||||||
|
|
||||||
|
// Database Access Layer stuff goes here
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { db, sql } from "../../database/db"
|
||||||
|
import { JsonValue } from '@firebox/tsutil';
|
||||||
|
import { PicobookManifest } from '../types';
|
||||||
|
|
||||||
|
export type DbRelease = {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
repo: string;
|
||||||
|
version: string;
|
||||||
|
carts: {name: string; rom: number[]}[];
|
||||||
|
author: string;
|
||||||
|
manifest: PicobookManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
const compareVersions = (a: string, b: string) => {
|
||||||
|
const [a1, a2] = a.split(".").map(x => Number(x));
|
||||||
|
const [b1, b2] = b.split(".").map(x => Number(x));
|
||||||
|
if (a1 !== b1) {
|
||||||
|
return a1 - b1;
|
||||||
|
} else {
|
||||||
|
return a2 - b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const compareByVersion = (a: DbRelease, b: DbRelease) => compareVersions(a.version, b.version);
|
||||||
|
|
||||||
|
export const getReleases = async (where: {
|
||||||
|
author: string;
|
||||||
|
slug: string;
|
||||||
|
version?: string;
|
||||||
|
}): Promise<DbRelease[]> => {
|
||||||
|
const {author, slug, version} = where;
|
||||||
|
if (!version) {
|
||||||
|
const rows = await db.query(sql`
|
||||||
|
SELECT * from releases
|
||||||
|
WHERE
|
||||||
|
slug = ${slug} AND
|
||||||
|
author = ${author}
|
||||||
|
`);
|
||||||
|
return rows;
|
||||||
|
} else {
|
||||||
|
const rows = await db.query(sql`
|
||||||
|
SELECT * from releases
|
||||||
|
WHERE
|
||||||
|
slug = ${slug} AND
|
||||||
|
author = ${author} AND
|
||||||
|
version = ${version}
|
||||||
|
`);
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getRelease = async (where: {
|
||||||
|
author: string;
|
||||||
|
slug: string;
|
||||||
|
version?: string;
|
||||||
|
}) => {
|
||||||
|
const {version} = where;
|
||||||
|
const releases = await getReleases(where);
|
||||||
|
if (version) {
|
||||||
|
if (releases.length === 1) {
|
||||||
|
return releases[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (releases.length < 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
releases.sort(compareByVersion);
|
||||||
|
return releases[releases.length-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const insertRelease = async (props: {manifest: PicobookManifest, carts: {name: string; rom: number[]}[]}) => {
|
||||||
|
const {manifest, carts} = props;
|
||||||
|
const {id: slug, author, repo, version} = manifest;
|
||||||
|
const id = uuidv4();
|
||||||
|
const now = new Date();
|
||||||
|
await db.query(sql`
|
||||||
|
INSERT INTO chats (id, slug, repo, version, author, carts, manifest, created_at)
|
||||||
|
VALUES (${id}, ${slug}, ${repo}, ${version}, ${author} ${carts}, ${manifest}, ${now})
|
||||||
|
`);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
17
src/server/types.ts
Normal file
17
src/server/types.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Static, Type } from "@sinclair/typebox";
|
||||||
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
||||||
|
|
||||||
|
export const manifestT = Type.Object({
|
||||||
|
picobook_version: Type.Number(),
|
||||||
|
id: Type.String(),
|
||||||
|
version: Type.String(),
|
||||||
|
carts: Type.Array(Type.String()),
|
||||||
|
repo: Type.String(),
|
||||||
|
author: Type.String(),
|
||||||
|
title: Type.Optional(Type.String()),
|
||||||
|
readme: Type.Optional(Type.String()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ManifestType = TypeCompiler.Compile(manifestT);
|
||||||
|
|
||||||
|
export type PicobookManifest = Static<typeof manifestT>;
|
Loading…
x
Reference in New Issue
Block a user