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:
		| @@ -44,7 +44,7 @@ for await (const dir of dirs) { | |||||||
| async function postNode(node: Node) { | async function postNode(node: Node) { | ||||||
|   const wasmContent = await Deno.readFile(node.path); |   const wasmContent = await Deno.readFile(node.path); | ||||||
|  |  | ||||||
|   const url = `http://localhost:8000/v1/nodes`; |   const url = `http://localhost:8000/nodes`; | ||||||
|  |  | ||||||
|   const res = await fetch(url, { |   const res = await fetch(url, { | ||||||
|     method: "POST", |     method: "POST", | ||||||
| @@ -55,7 +55,7 @@ async function postNode(node: Node) { | |||||||
|     console.log(`Uploaded ${node.id}`); |     console.log(`Uploaded ${node.id}`); | ||||||
|   } else { |   } else { | ||||||
|     const text = await res.text(); |     const text = await res.text(); | ||||||
|     console.log(`Failed to upload ${node.id}: ${text}`); |     console.log(`Failed to upload ${node.id}: ${res.status} ${text}`); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								store/drizzle/0001_amazing_weapon_omega.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								store/drizzle/0001_amazing_weapon_omega.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ALTER TABLE "nodes" ADD COLUMN "createdAt" timestamp DEFAULT now(); | ||||||
							
								
								
									
										217
									
								
								store/drizzle/meta/0001_snapshot.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								store/drizzle/meta/0001_snapshot.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | |||||||
|  | { | ||||||
|  |   "id": "080ee514-5516-4400-9286-295826df6f8a", | ||||||
|  |   "prevId": "b5fc8bcf-82d4-4d2e-bcd1-89d5a238f5e2", | ||||||
|  |   "version": "7", | ||||||
|  |   "dialect": "postgresql", | ||||||
|  |   "tables": { | ||||||
|  |     "public.users": { | ||||||
|  |       "name": "users", | ||||||
|  |       "schema": "", | ||||||
|  |       "columns": { | ||||||
|  |         "id": { | ||||||
|  |           "name": "id", | ||||||
|  |           "type": "uuid", | ||||||
|  |           "primaryKey": true, | ||||||
|  |           "notNull": true, | ||||||
|  |           "default": "gen_random_uuid()" | ||||||
|  |         }, | ||||||
|  |         "name": { | ||||||
|  |           "name": "name", | ||||||
|  |           "type": "text", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "indexes": {}, | ||||||
|  |       "foreignKeys": {}, | ||||||
|  |       "compositePrimaryKeys": {}, | ||||||
|  |       "uniqueConstraints": { | ||||||
|  |         "users_name_unique": { | ||||||
|  |           "name": "users_name_unique", | ||||||
|  |           "nullsNotDistinct": false, | ||||||
|  |           "columns": [ | ||||||
|  |             "name" | ||||||
|  |           ] | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "policies": {}, | ||||||
|  |       "checkConstraints": {}, | ||||||
|  |       "isRLSEnabled": false | ||||||
|  |     }, | ||||||
|  |     "public.nodes": { | ||||||
|  |       "name": "nodes", | ||||||
|  |       "schema": "", | ||||||
|  |       "columns": { | ||||||
|  |         "id": { | ||||||
|  |           "name": "id", | ||||||
|  |           "type": "serial", | ||||||
|  |           "primaryKey": true, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "userId": { | ||||||
|  |           "name": "userId", | ||||||
|  |           "type": "varchar", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "createdAt": { | ||||||
|  |           "name": "createdAt", | ||||||
|  |           "type": "timestamp", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": false, | ||||||
|  |           "default": "now()" | ||||||
|  |         }, | ||||||
|  |         "systemId": { | ||||||
|  |           "name": "systemId", | ||||||
|  |           "type": "varchar", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "nodeId": { | ||||||
|  |           "name": "nodeId", | ||||||
|  |           "type": "varchar", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "content": { | ||||||
|  |           "name": "content", | ||||||
|  |           "type": "bytea", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "definition": { | ||||||
|  |           "name": "definition", | ||||||
|  |           "type": "json", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "hash": { | ||||||
|  |           "name": "hash", | ||||||
|  |           "type": "varchar(8)", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": true | ||||||
|  |         }, | ||||||
|  |         "previous": { | ||||||
|  |           "name": "previous", | ||||||
|  |           "type": "varchar(8)", | ||||||
|  |           "primaryKey": false, | ||||||
|  |           "notNull": false | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "indexes": { | ||||||
|  |         "user_id_idx": { | ||||||
|  |           "name": "user_id_idx", | ||||||
|  |           "columns": [ | ||||||
|  |             { | ||||||
|  |               "expression": "userId", | ||||||
|  |               "isExpression": false, | ||||||
|  |               "asc": true, | ||||||
|  |               "nulls": "last" | ||||||
|  |             } | ||||||
|  |           ], | ||||||
|  |           "isUnique": false, | ||||||
|  |           "concurrently": false, | ||||||
|  |           "method": "btree", | ||||||
|  |           "with": {} | ||||||
|  |         }, | ||||||
|  |         "system_id_idx": { | ||||||
|  |           "name": "system_id_idx", | ||||||
|  |           "columns": [ | ||||||
|  |             { | ||||||
|  |               "expression": "systemId", | ||||||
|  |               "isExpression": false, | ||||||
|  |               "asc": true, | ||||||
|  |               "nulls": "last" | ||||||
|  |             } | ||||||
|  |           ], | ||||||
|  |           "isUnique": false, | ||||||
|  |           "concurrently": false, | ||||||
|  |           "method": "btree", | ||||||
|  |           "with": {} | ||||||
|  |         }, | ||||||
|  |         "node_id_idx": { | ||||||
|  |           "name": "node_id_idx", | ||||||
|  |           "columns": [ | ||||||
|  |             { | ||||||
|  |               "expression": "nodeId", | ||||||
|  |               "isExpression": false, | ||||||
|  |               "asc": true, | ||||||
|  |               "nulls": "last" | ||||||
|  |             } | ||||||
|  |           ], | ||||||
|  |           "isUnique": false, | ||||||
|  |           "concurrently": false, | ||||||
|  |           "method": "btree", | ||||||
|  |           "with": {} | ||||||
|  |         }, | ||||||
|  |         "hash_idx": { | ||||||
|  |           "name": "hash_idx", | ||||||
|  |           "columns": [ | ||||||
|  |             { | ||||||
|  |               "expression": "hash", | ||||||
|  |               "isExpression": false, | ||||||
|  |               "asc": true, | ||||||
|  |               "nulls": "last" | ||||||
|  |             } | ||||||
|  |           ], | ||||||
|  |           "isUnique": false, | ||||||
|  |           "concurrently": false, | ||||||
|  |           "method": "btree", | ||||||
|  |           "with": {} | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "foreignKeys": { | ||||||
|  |         "nodes_userId_users_name_fk": { | ||||||
|  |           "name": "nodes_userId_users_name_fk", | ||||||
|  |           "tableFrom": "nodes", | ||||||
|  |           "tableTo": "users", | ||||||
|  |           "columnsFrom": [ | ||||||
|  |             "userId" | ||||||
|  |           ], | ||||||
|  |           "columnsTo": [ | ||||||
|  |             "name" | ||||||
|  |           ], | ||||||
|  |           "onDelete": "no action", | ||||||
|  |           "onUpdate": "no action" | ||||||
|  |         }, | ||||||
|  |         "node_previous_fk": { | ||||||
|  |           "name": "node_previous_fk", | ||||||
|  |           "tableFrom": "nodes", | ||||||
|  |           "tableTo": "nodes", | ||||||
|  |           "columnsFrom": [ | ||||||
|  |             "previous" | ||||||
|  |           ], | ||||||
|  |           "columnsTo": [ | ||||||
|  |             "hash" | ||||||
|  |           ], | ||||||
|  |           "onDelete": "no action", | ||||||
|  |           "onUpdate": "no action" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "compositePrimaryKeys": {}, | ||||||
|  |       "uniqueConstraints": { | ||||||
|  |         "nodes_hash_unique": { | ||||||
|  |           "name": "nodes_hash_unique", | ||||||
|  |           "nullsNotDistinct": false, | ||||||
|  |           "columns": [ | ||||||
|  |             "hash" | ||||||
|  |           ] | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "policies": {}, | ||||||
|  |       "checkConstraints": {}, | ||||||
|  |       "isRLSEnabled": false | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "enums": {}, | ||||||
|  |   "schemas": {}, | ||||||
|  |   "sequences": {}, | ||||||
|  |   "roles": {}, | ||||||
|  |   "policies": {}, | ||||||
|  |   "views": {}, | ||||||
|  |   "_meta": { | ||||||
|  |     "columns": {}, | ||||||
|  |     "schemas": {}, | ||||||
|  |     "tables": {} | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -8,6 +8,13 @@ | |||||||
|       "when": 1734695353420, |       "when": 1734695353420, | ||||||
|       "tag": "0000_steep_bromley", |       "tag": "0000_steep_bromley", | ||||||
|       "breakpoints": true |       "breakpoints": true | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "idx": 1, | ||||||
|  |       "version": "7", | ||||||
|  |       "when": 1734696211359, | ||||||
|  |       "tag": "0001_amazing_weapon_omega", | ||||||
|  |       "breakpoints": true | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -78,7 +78,7 @@ nodeRouter.openapi(getNodeCollectionRoute, async (c) => { | |||||||
|  |  | ||||||
| const getNodeDefinitionRoute = createRoute({ | const getNodeDefinitionRoute = createRoute({ | ||||||
|   method: "get", |   method: "get", | ||||||
|   path: "/{user}/{system}/{nodeId}{.+\\.json}", |   path: "/{user}/{system}/{nodeId}.json", | ||||||
|   request: { |   request: { | ||||||
|     params: ParamsSchema, |     params: ParamsSchema, | ||||||
|   }, |   }, | ||||||
| @@ -111,7 +111,7 @@ nodeRouter.openapi(getNodeDefinitionRoute, async (c) => { | |||||||
|  |  | ||||||
| const getNodeWasmRoute = createRoute({ | const getNodeWasmRoute = createRoute({ | ||||||
|   method: "get", |   method: "get", | ||||||
|   path: "/{user}/{system}/{nodeId}{.+\\.wasm}", |   path: "/{user}/{system}/{nodeId}.wasm", | ||||||
|   request: { |   request: { | ||||||
|     params: ParamsSchema, |     params: ParamsSchema, | ||||||
|   }, |   }, | ||||||
| @@ -140,6 +140,63 @@ nodeRouter.openapi(getNodeWasmRoute, async (c) => { | |||||||
|   return c.body(wasmContent); |   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({ | const createNodeRoute = createRoute({ | ||||||
|   method: "post", |   method: "post", | ||||||
|   path: "/", |   path: "/", | ||||||
| @@ -165,8 +222,19 @@ const createNodeRoute = createRoute({ | |||||||
| nodeRouter.openapi(createNodeRoute, async (c) => { | nodeRouter.openapi(createNodeRoute, async (c) => { | ||||||
|   const buffer = await c.req.arrayBuffer(); |   const buffer = await c.req.arrayBuffer(); | ||||||
|   const bytes = await (await c.req.blob()).bytes(); |   const bytes = await (await c.req.blob()).bytes(); | ||||||
|  |  | ||||||
|  |   try { | ||||||
|     const node = await service.createNode(buffer, bytes); |     const node = await service.createNode(buffer, bytes); | ||||||
|     return c.json(node); |     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 }; | export { nodeRouter }; | ||||||
|   | |||||||
| @@ -2,14 +2,14 @@ import { | |||||||
|   customType, |   customType, | ||||||
|   foreignKey, |   foreignKey, | ||||||
|   index, |   index, | ||||||
|   integer, |  | ||||||
|   json, |   json, | ||||||
|   pgTable, |   pgTable, | ||||||
|   serial, |   serial, | ||||||
|  |   timestamp, | ||||||
|   varchar, |   varchar, | ||||||
| } from "drizzle-orm/pg-core"; | } from "drizzle-orm/pg-core"; | ||||||
| import { relations } from "drizzle-orm/relations"; |  | ||||||
| import { usersTable } from "../user/user.schema.ts"; | import { usersTable } from "../user/user.schema.ts"; | ||||||
|  | import { NodeDefinition } from "./validations/types.ts"; | ||||||
|  |  | ||||||
| const bytea = customType<{ | const bytea = customType<{ | ||||||
|   data: ArrayBuffer; |   data: ArrayBuffer; | ||||||
| @@ -23,12 +23,13 @@ const bytea = customType<{ | |||||||
| export const nodeTable = pgTable("nodes", { | export const nodeTable = pgTable("nodes", { | ||||||
|   id: serial().primaryKey(), |   id: serial().primaryKey(), | ||||||
|   userId: varchar().notNull().references(() => usersTable.name), |   userId: varchar().notNull().references(() => usersTable.name), | ||||||
|  |   createdAt: timestamp().defaultNow(), | ||||||
|   systemId: varchar().notNull(), |   systemId: varchar().notNull(), | ||||||
|   nodeId: varchar().notNull(), |   nodeId: varchar().notNull(), | ||||||
|   content: bytea().notNull(), |   content: bytea().notNull(), | ||||||
|   definition: json().notNull(), |   definition: json().notNull().$type<NodeDefinition>(), | ||||||
|   hash: varchar({ length: 8 }).notNull().unique(), |   hash: varchar({ length: 16 }).notNull().unique(), | ||||||
|   previous: varchar({ length: 8 }), |   previous: varchar({ length: 16 }), | ||||||
| }, (table) => [ | }, (table) => [ | ||||||
|   foreignKey({ |   foreignKey({ | ||||||
|     columns: [table.previous], |     columns: [table.previous], | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { db } from "../../db/db.ts"; | import { db } from "../../db/db.ts"; | ||||||
| import { nodeTable } from "./node.schema.ts"; | import { nodeTable } from "./node.schema.ts"; | ||||||
| import { NodeDefinition, NodeDefinitionSchema } from "./validations/types.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 { createHash } from "node:crypto"; | ||||||
| import { WorkerMessage } from "./worker/messages.ts"; | import { WorkerMessage } from "./worker/messages.ts"; | ||||||
|  |  | ||||||
| @@ -15,7 +15,7 @@ export type CreateNodeDTO = { | |||||||
| function getNodeHash(content: Uint8Array) { | function getNodeHash(content: Uint8Array) { | ||||||
|   const hash = createHash("sha256"); |   const hash = createHash("sha256"); | ||||||
|   hash.update(content); |   hash.update(content); | ||||||
|   return hash.digest("hex").slice(0, 8); |   return hash.digest("hex").slice(0, 16); | ||||||
| } | } | ||||||
|  |  | ||||||
| function extractDefinition(content: ArrayBuffer): Promise<NodeDefinition> { | function extractDefinition(content: ArrayBuffer): Promise<NodeDefinition> { | ||||||
| @@ -40,7 +40,6 @@ function extractDefinition(content: ArrayBuffer): Promise<NodeDefinition> { | |||||||
|           res(e.data.result); |           res(e.data.result); | ||||||
|           break; |           break; | ||||||
|         case "error": |         case "error": | ||||||
|           console.log("Worker error", e.data.error); |  | ||||||
|           rej(e.data.result); |           rej(e.data.result); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
| @@ -54,36 +53,46 @@ export async function createNode( | |||||||
|   wasmBuffer: ArrayBuffer, |   wasmBuffer: ArrayBuffer, | ||||||
|   content: Uint8Array, |   content: Uint8Array, | ||||||
| ): Promise<NodeDefinition> { | ): 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 hash = getNodeHash(content); | ||||||
|  |  | ||||||
|   const node: typeof nodeTable.$inferInsert = { |   const node: typeof nodeTable.$inferInsert = { | ||||||
|     userId, |     userId, | ||||||
|     systemId, |     systemId, | ||||||
|     nodeId, |     nodeId, | ||||||
|     definition: def, |     definition: def, | ||||||
|       hash: getNodeHash(content), |     hash, | ||||||
|     content: content, |     content: content, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|     await db.insert(nodeTable).values(node); |   const previousNode = await db | ||||||
|     console.log("new node created!"); |     .select({ hash: nodeTable.hash }) | ||||||
|     return def; |     .from(nodeTable) | ||||||
|   } catch (error) { |     .orderBy(asc(nodeTable.createdAt)) | ||||||
|     console.log("Creation Error", { error }); |     .limit(1); | ||||||
|     throw error; |  | ||||||
|  |   if (previousNode[0]) { | ||||||
|  |     node.previous = previousNode[0].hash; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   await db.insert(nodeTable).values(node); | ||||||
|  |   return def; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function getNodeDefinitionsByUser(userName: string) { | export async function getNodeDefinitionsByUser(userName: string) { | ||||||
|   return db.select({ definition: nodeTable.definition }).from(nodeTable) |   const nodes = await db.select({ definition: nodeTable.definition }).from( | ||||||
|  |     nodeTable, | ||||||
|  |   ) | ||||||
|     .where( |     .where( | ||||||
|       and( |       and( | ||||||
|         eq(nodeTable.userId, userName), |         eq(nodeTable.userId, userName), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  |   return nodes.map((n) => n.definition); | ||||||
| } | } | ||||||
|  |  | ||||||
| export async function getNodesBySystem( | export async function getNodesBySystem( | ||||||
| @@ -91,11 +100,14 @@ export async function getNodesBySystem( | |||||||
|   systemId: string, |   systemId: string, | ||||||
| ): Promise<NodeDefinition[]> { | ): Promise<NodeDefinition[]> { | ||||||
|   const nodes = await db |   const nodes = await db | ||||||
|     .select() |     .selectDistinctOn( | ||||||
|  |       [nodeTable.userId, nodeTable.systemId, nodeTable.nodeId], | ||||||
|  |       { definition: nodeTable.definition }, | ||||||
|  |     ) | ||||||
|     .from(nodeTable) |     .from(nodeTable) | ||||||
|     .where( |     .where( | ||||||
|       and(eq(nodeTable.systemId, systemId), eq(nodeTable.userId, username)), |       and(eq(nodeTable.systemId, systemId), eq(nodeTable.userId, username)), | ||||||
|     ); |     ).orderBy(nodeTable.userId, nodeTable.systemId, nodeTable.nodeId); | ||||||
|  |  | ||||||
|   const definitions = nodes |   const definitions = nodes | ||||||
|     .map((node) => NodeDefinitionSchema.safeParse(node.definition)) |     .map((node) => NodeDefinitionSchema.safeParse(node.definition)) | ||||||
| @@ -118,7 +130,9 @@ export async function getNodeWasmById( | |||||||
|         eq(nodeTable.systemId, systemId), |         eq(nodeTable.systemId, systemId), | ||||||
|         eq(nodeTable.nodeId, nodeId), |         eq(nodeTable.nodeId, nodeId), | ||||||
|       ), |       ), | ||||||
|     ).limit(1).execute(); |     ) | ||||||
|  |     .orderBy(asc(nodeTable.createdAt)) | ||||||
|  |     .limit(1); | ||||||
|   console.log("Time to load wasm", performance.now() - a); |   console.log("Time to load wasm", performance.now() - a); | ||||||
|  |  | ||||||
|   if (!node[0]) { |   if (!node[0]) { | ||||||
| @@ -141,7 +155,9 @@ export async function getNodeDefinitionById( | |||||||
|       eq(nodeTable.systemId, systemId), |       eq(nodeTable.systemId, systemId), | ||||||
|       eq(nodeTable.nodeId, nodeId), |       eq(nodeTable.nodeId, nodeId), | ||||||
|     ), |     ), | ||||||
|   ).limit(1); |   ) | ||||||
|  |     .orderBy(asc(nodeTable.createdAt)) | ||||||
|  |     .limit(1); | ||||||
|  |  | ||||||
|   if (!node[0]) { |   if (!node[0]) { | ||||||
|     return; |     return; | ||||||
| @@ -155,3 +171,55 @@ export async function getNodeDefinitionById( | |||||||
|  |  | ||||||
|   return definition.data; |   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