fix: some shit
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m55s
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m55s
This commit is contained in:
@ -78,7 +78,7 @@ nodeRouter.openapi(getNodeCollectionRoute, async (c) => {
|
||||
|
||||
const getNodeDefinitionRoute = createRoute({
|
||||
method: "get",
|
||||
path: "/{user}/{system}/{nodeId}{.+\\.json}",
|
||||
path: "/{user}/{system}/{nodeId}.json",
|
||||
request: {
|
||||
params: ParamsSchema,
|
||||
},
|
||||
@ -111,7 +111,7 @@ nodeRouter.openapi(getNodeDefinitionRoute, async (c) => {
|
||||
|
||||
const getNodeWasmRoute = createRoute({
|
||||
method: "get",
|
||||
path: "/{user}/{system}/{nodeId}{.+\\.wasm}",
|
||||
path: "/{user}/{system}/{nodeId}.wasm",
|
||||
request: {
|
||||
params: ParamsSchema,
|
||||
},
|
||||
@ -140,6 +140,63 @@ nodeRouter.openapi(getNodeWasmRoute, async (c) => {
|
||||
return c.body(wasmContent);
|
||||
});
|
||||
|
||||
const getNodeVersionRoute = createRoute({
|
||||
method: "get",
|
||||
path: "/{user}/{system}/{nodeId}@{hash}.json",
|
||||
request: {
|
||||
params: ParamsSchema,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: NodeDefinitionSchema,
|
||||
},
|
||||
},
|
||||
description: "Create a single node",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
nodeRouter.openapi(getNodeVersionRoute, async (c) => {
|
||||
const { user, system, nodeId } = c.req.valid("param");
|
||||
|
||||
const nodes = await service.getNodeVersions(user, system, nodeId);
|
||||
|
||||
return c.json(nodes);
|
||||
});
|
||||
|
||||
const getNodeVersionsRoute = createRoute({
|
||||
method: "get",
|
||||
path: "/{user}/{system}/{nodeId}/versions.json",
|
||||
request: {
|
||||
params: z.object({
|
||||
user: SingleParam("user"),
|
||||
system: SingleParam("system"),
|
||||
nodeId: SingleParam("nodeId"),
|
||||
hash: SingleParam("hash"),
|
||||
}),
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: NodeDefinitionSchema,
|
||||
},
|
||||
},
|
||||
description: "Create a single node",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
nodeRouter.openapi(getNodeVersionsRoute, async (c) => {
|
||||
const { user, system, nodeId, hash } = c.req.valid("param");
|
||||
|
||||
const node = await service.getNodeVersion(user, system, nodeId, hash);
|
||||
|
||||
return c.json(node);
|
||||
});
|
||||
|
||||
const createNodeRoute = createRoute({
|
||||
method: "post",
|
||||
path: "/",
|
||||
@ -165,8 +222,19 @@ const createNodeRoute = createRoute({
|
||||
nodeRouter.openapi(createNodeRoute, async (c) => {
|
||||
const buffer = await c.req.arrayBuffer();
|
||||
const bytes = await (await c.req.blob()).bytes();
|
||||
const node = await service.createNode(buffer, bytes);
|
||||
return c.json(node);
|
||||
|
||||
try {
|
||||
const node = await service.createNode(buffer, bytes);
|
||||
return c.json(node);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && "code" in error) {
|
||||
switch (error.code) {
|
||||
case "23505":
|
||||
throw new HTTPException(409, { message: "node already exists" });
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new HTTPException(500);
|
||||
});
|
||||
|
||||
export { nodeRouter };
|
||||
|
@ -2,14 +2,14 @@ import {
|
||||
customType,
|
||||
foreignKey,
|
||||
index,
|
||||
integer,
|
||||
json,
|
||||
pgTable,
|
||||
serial,
|
||||
timestamp,
|
||||
varchar,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { relations } from "drizzle-orm/relations";
|
||||
import { usersTable } from "../user/user.schema.ts";
|
||||
import { NodeDefinition } from "./validations/types.ts";
|
||||
|
||||
const bytea = customType<{
|
||||
data: ArrayBuffer;
|
||||
@ -23,12 +23,13 @@ const bytea = customType<{
|
||||
export const nodeTable = pgTable("nodes", {
|
||||
id: serial().primaryKey(),
|
||||
userId: varchar().notNull().references(() => usersTable.name),
|
||||
createdAt: timestamp().defaultNow(),
|
||||
systemId: varchar().notNull(),
|
||||
nodeId: varchar().notNull(),
|
||||
content: bytea().notNull(),
|
||||
definition: json().notNull(),
|
||||
hash: varchar({ length: 8 }).notNull().unique(),
|
||||
previous: varchar({ length: 8 }),
|
||||
definition: json().notNull().$type<NodeDefinition>(),
|
||||
hash: varchar({ length: 16 }).notNull().unique(),
|
||||
previous: varchar({ length: 16 }),
|
||||
}, (table) => [
|
||||
foreignKey({
|
||||
columns: [table.previous],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { db } from "../../db/db.ts";
|
||||
import { nodeTable } from "./node.schema.ts";
|
||||
import { NodeDefinition, NodeDefinitionSchema } from "./validations/types.ts";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { and, asc, eq } from "drizzle-orm";
|
||||
import { createHash } from "node:crypto";
|
||||
import { WorkerMessage } from "./worker/messages.ts";
|
||||
|
||||
@ -15,7 +15,7 @@ export type CreateNodeDTO = {
|
||||
function getNodeHash(content: Uint8Array) {
|
||||
const hash = createHash("sha256");
|
||||
hash.update(content);
|
||||
return hash.digest("hex").slice(0, 8);
|
||||
return hash.digest("hex").slice(0, 16);
|
||||
}
|
||||
|
||||
function extractDefinition(content: ArrayBuffer): Promise<NodeDefinition> {
|
||||
@ -40,7 +40,6 @@ function extractDefinition(content: ArrayBuffer): Promise<NodeDefinition> {
|
||||
res(e.data.result);
|
||||
break;
|
||||
case "error":
|
||||
console.log("Worker error", e.data.error);
|
||||
rej(e.data.result);
|
||||
break;
|
||||
default:
|
||||
@ -54,36 +53,46 @@ export async function createNode(
|
||||
wasmBuffer: ArrayBuffer,
|
||||
content: Uint8Array,
|
||||
): Promise<NodeDefinition> {
|
||||
try {
|
||||
const def = await extractDefinition(wasmBuffer);
|
||||
const def = await extractDefinition(wasmBuffer);
|
||||
|
||||
const [userId, systemId, nodeId] = def.id.split("/");
|
||||
const [userId, systemId, nodeId] = def.id.split("/");
|
||||
|
||||
const node: typeof nodeTable.$inferInsert = {
|
||||
userId,
|
||||
systemId,
|
||||
nodeId,
|
||||
definition: def,
|
||||
hash: getNodeHash(content),
|
||||
content: content,
|
||||
};
|
||||
const hash = getNodeHash(content);
|
||||
|
||||
await db.insert(nodeTable).values(node);
|
||||
console.log("new node created!");
|
||||
return def;
|
||||
} catch (error) {
|
||||
console.log("Creation Error", { error });
|
||||
throw error;
|
||||
const node: typeof nodeTable.$inferInsert = {
|
||||
userId,
|
||||
systemId,
|
||||
nodeId,
|
||||
definition: def,
|
||||
hash,
|
||||
content: content,
|
||||
};
|
||||
|
||||
const previousNode = await db
|
||||
.select({ hash: nodeTable.hash })
|
||||
.from(nodeTable)
|
||||
.orderBy(asc(nodeTable.createdAt))
|
||||
.limit(1);
|
||||
|
||||
if (previousNode[0]) {
|
||||
node.previous = previousNode[0].hash;
|
||||
}
|
||||
|
||||
await db.insert(nodeTable).values(node);
|
||||
return def;
|
||||
}
|
||||
|
||||
export function getNodeDefinitionsByUser(userName: string) {
|
||||
return db.select({ definition: nodeTable.definition }).from(nodeTable)
|
||||
export async function getNodeDefinitionsByUser(userName: string) {
|
||||
const nodes = await db.select({ definition: nodeTable.definition }).from(
|
||||
nodeTable,
|
||||
)
|
||||
.where(
|
||||
and(
|
||||
eq(nodeTable.userId, userName),
|
||||
),
|
||||
);
|
||||
|
||||
return nodes.map((n) => n.definition);
|
||||
}
|
||||
|
||||
export async function getNodesBySystem(
|
||||
@ -91,11 +100,14 @@ export async function getNodesBySystem(
|
||||
systemId: string,
|
||||
): Promise<NodeDefinition[]> {
|
||||
const nodes = await db
|
||||
.select()
|
||||
.selectDistinctOn(
|
||||
[nodeTable.userId, nodeTable.systemId, nodeTable.nodeId],
|
||||
{ definition: nodeTable.definition },
|
||||
)
|
||||
.from(nodeTable)
|
||||
.where(
|
||||
and(eq(nodeTable.systemId, systemId), eq(nodeTable.userId, username)),
|
||||
);
|
||||
).orderBy(nodeTable.userId, nodeTable.systemId, nodeTable.nodeId);
|
||||
|
||||
const definitions = nodes
|
||||
.map((node) => NodeDefinitionSchema.safeParse(node.definition))
|
||||
@ -118,7 +130,9 @@ export async function getNodeWasmById(
|
||||
eq(nodeTable.systemId, systemId),
|
||||
eq(nodeTable.nodeId, nodeId),
|
||||
),
|
||||
).limit(1).execute();
|
||||
)
|
||||
.orderBy(asc(nodeTable.createdAt))
|
||||
.limit(1);
|
||||
console.log("Time to load wasm", performance.now() - a);
|
||||
|
||||
if (!node[0]) {
|
||||
@ -141,7 +155,9 @@ export async function getNodeDefinitionById(
|
||||
eq(nodeTable.systemId, systemId),
|
||||
eq(nodeTable.nodeId, nodeId),
|
||||
),
|
||||
).limit(1);
|
||||
)
|
||||
.orderBy(asc(nodeTable.createdAt))
|
||||
.limit(1);
|
||||
|
||||
if (!node[0]) {
|
||||
return;
|
||||
@ -155,3 +171,55 @@ export async function getNodeDefinitionById(
|
||||
|
||||
return definition.data;
|
||||
}
|
||||
|
||||
export async function getNodeVersions(
|
||||
user: string,
|
||||
system: string,
|
||||
nodeId: string,
|
||||
) {
|
||||
const nodes = await db.select({
|
||||
definition: nodeTable.definition,
|
||||
hash: nodeTable.hash,
|
||||
}).from(
|
||||
nodeTable,
|
||||
).where(
|
||||
and(
|
||||
eq(nodeTable.userId, user),
|
||||
eq(nodeTable.systemId, system),
|
||||
eq(nodeTable.nodeId, nodeId),
|
||||
),
|
||||
)
|
||||
.orderBy(asc(nodeTable.createdAt));
|
||||
|
||||
return nodes.map((node) => ({
|
||||
...node.definition,
|
||||
id: node.definition.id + "@" + node.hash,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getNodeVersion(
|
||||
user: string,
|
||||
system: string,
|
||||
nodeId: string,
|
||||
hash: string,
|
||||
) {
|
||||
const nodes = await db.select({
|
||||
definition: nodeTable.definition,
|
||||
hash: nodeTable.hash,
|
||||
}).from(
|
||||
nodeTable,
|
||||
).where(
|
||||
and(
|
||||
eq(nodeTable.userId, user),
|
||||
eq(nodeTable.systemId, system),
|
||||
eq(nodeTable.nodeId, nodeId),
|
||||
eq(nodeTable.hash, hash),
|
||||
),
|
||||
).limit(1);
|
||||
|
||||
if (nodes.length === 0) {
|
||||
throw new Error("Node not found");
|
||||
}
|
||||
|
||||
return nodes[0].definition;
|
||||
}
|
||||
|
Reference in New Issue
Block a user