feat: add preview image builder
This commit is contained in:
		
							parent
							
								
									314eb9fd16
								
							
						
					
					
						commit
						9937252777
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1 +1,2 @@
 | 
				
			|||||||
__pycache__
 | 
					__pycache__
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
@ -13,5 +13,7 @@ SPACES_SECRET="aaa"
 | 
				
			|||||||
SPACES_CDN_DONT_INCLUDE_BUCKET="false"
 | 
					SPACES_CDN_DONT_INCLUDE_BUCKET="false"
 | 
				
			||||||
SPACES_CDN_FORCE_PATH_STYLE="true"
 | 
					SPACES_CDN_FORCE_PATH_STYLE="true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MODAL_BUILDER_URL=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
JWT_SECRET="openssl rand -hex 32"
 | 
					JWT_SECRET="openssl rand -hex 32"
 | 
				
			||||||
PLAUSIBLE_DOMAIN=
 | 
					PLAUSIBLE_DOMAIN=
 | 
				
			||||||
							
								
								
									
										9
									
								
								web/drizzle/0020_complete_black_tom.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								web/drizzle/0020_complete_black_tom.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					DO $$ BEGIN
 | 
				
			||||||
 | 
					 CREATE TYPE "machine_status" AS ENUM('ready', 'building', 'error');
 | 
				
			||||||
 | 
					EXCEPTION
 | 
				
			||||||
 | 
					 WHEN duplicate_object THEN null;
 | 
				
			||||||
 | 
					END $$;
 | 
				
			||||||
 | 
					--> statement-breakpoint
 | 
				
			||||||
 | 
					ALTER TABLE "comfyui_deploy"."machines" ADD COLUMN "status" "machine_status" DEFAULT 'ready' NOT NULL;--> statement-breakpoint
 | 
				
			||||||
 | 
					ALTER TABLE "comfyui_deploy"."machines" ADD COLUMN "snapshot" jsonb;--> statement-breakpoint
 | 
				
			||||||
 | 
					ALTER TABLE "comfyui_deploy"."machines" ADD COLUMN "build_log" text;
 | 
				
			||||||
							
								
								
									
										703
									
								
								web/drizzle/meta/0020_snapshot.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										703
									
								
								web/drizzle/meta/0020_snapshot.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,703 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "id": "60fd6aaf-0bd4-4b77-b707-fea7c44e829d",
 | 
				
			||||||
 | 
					  "prevId": "4c2423cd-420e-49fc-a6fe-2e6c56ce8c61",
 | 
				
			||||||
 | 
					  "version": "5",
 | 
				
			||||||
 | 
					  "dialect": "pg",
 | 
				
			||||||
 | 
					  "tables": {
 | 
				
			||||||
 | 
					    "api_keys": {
 | 
				
			||||||
 | 
					      "name": "api_keys",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "key": {
 | 
				
			||||||
 | 
					          "name": "key",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "name": {
 | 
				
			||||||
 | 
					          "name": "name",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "user_id": {
 | 
				
			||||||
 | 
					          "name": "user_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "org_id": {
 | 
				
			||||||
 | 
					          "name": "org_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "revoked": {
 | 
				
			||||||
 | 
					          "name": "revoked",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "api_keys_user_id_users_id_fk": {
 | 
				
			||||||
 | 
					          "name": "api_keys_user_id_users_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "api_keys",
 | 
				
			||||||
 | 
					          "tableTo": "users",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "user_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {
 | 
				
			||||||
 | 
					        "api_keys_key_unique": {
 | 
				
			||||||
 | 
					          "name": "api_keys_key_unique",
 | 
				
			||||||
 | 
					          "nullsNotDistinct": false,
 | 
				
			||||||
 | 
					          "columns": [
 | 
				
			||||||
 | 
					            "key"
 | 
				
			||||||
 | 
					          ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "deployments": {
 | 
				
			||||||
 | 
					      "name": "deployments",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "user_id": {
 | 
				
			||||||
 | 
					          "name": "user_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_version_id": {
 | 
				
			||||||
 | 
					          "name": "workflow_version_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_id": {
 | 
				
			||||||
 | 
					          "name": "workflow_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "machine_id": {
 | 
				
			||||||
 | 
					          "name": "machine_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "environment": {
 | 
				
			||||||
 | 
					          "name": "environment",
 | 
				
			||||||
 | 
					          "type": "deployment_environment",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "deployments_user_id_users_id_fk": {
 | 
				
			||||||
 | 
					          "name": "deployments_user_id_users_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "deployments",
 | 
				
			||||||
 | 
					          "tableTo": "users",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "user_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "deployments_workflow_version_id_workflow_versions_id_fk": {
 | 
				
			||||||
 | 
					          "name": "deployments_workflow_version_id_workflow_versions_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "deployments",
 | 
				
			||||||
 | 
					          "tableTo": "workflow_versions",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "workflow_version_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "no action",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "deployments_workflow_id_workflows_id_fk": {
 | 
				
			||||||
 | 
					          "name": "deployments_workflow_id_workflows_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "deployments",
 | 
				
			||||||
 | 
					          "tableTo": "workflows",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "workflow_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "deployments_machine_id_machines_id_fk": {
 | 
				
			||||||
 | 
					          "name": "deployments_machine_id_machines_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "deployments",
 | 
				
			||||||
 | 
					          "tableTo": "machines",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "machine_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "no action",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "machines": {
 | 
				
			||||||
 | 
					      "name": "machines",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "user_id": {
 | 
				
			||||||
 | 
					          "name": "user_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "name": {
 | 
				
			||||||
 | 
					          "name": "name",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "org_id": {
 | 
				
			||||||
 | 
					          "name": "org_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "endpoint": {
 | 
				
			||||||
 | 
					          "name": "endpoint",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "disabled": {
 | 
				
			||||||
 | 
					          "name": "disabled",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "auth_token": {
 | 
				
			||||||
 | 
					          "name": "auth_token",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "type": {
 | 
				
			||||||
 | 
					          "name": "type",
 | 
				
			||||||
 | 
					          "type": "machine_type",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "'classic'"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "status": {
 | 
				
			||||||
 | 
					          "name": "status",
 | 
				
			||||||
 | 
					          "type": "machine_status",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "'ready'"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "snapshot": {
 | 
				
			||||||
 | 
					          "name": "snapshot",
 | 
				
			||||||
 | 
					          "type": "jsonb",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "build_log": {
 | 
				
			||||||
 | 
					          "name": "build_log",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "machines_user_id_users_id_fk": {
 | 
				
			||||||
 | 
					          "name": "machines_user_id_users_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "machines",
 | 
				
			||||||
 | 
					          "tableTo": "users",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "user_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "users": {
 | 
				
			||||||
 | 
					      "name": "users",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "username": {
 | 
				
			||||||
 | 
					          "name": "username",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "name": {
 | 
				
			||||||
 | 
					          "name": "name",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {},
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflow_run_outputs": {
 | 
				
			||||||
 | 
					      "name": "workflow_run_outputs",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "run_id": {
 | 
				
			||||||
 | 
					          "name": "run_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "data": {
 | 
				
			||||||
 | 
					          "name": "data",
 | 
				
			||||||
 | 
					          "type": "jsonb",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "workflow_run_outputs_run_id_workflow_runs_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflow_run_outputs",
 | 
				
			||||||
 | 
					          "tableTo": "workflow_runs",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "run_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflow_runs": {
 | 
				
			||||||
 | 
					      "name": "workflow_runs",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_version_id": {
 | 
				
			||||||
 | 
					          "name": "workflow_version_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_inputs": {
 | 
				
			||||||
 | 
					          "name": "workflow_inputs",
 | 
				
			||||||
 | 
					          "type": "jsonb",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_id": {
 | 
				
			||||||
 | 
					          "name": "workflow_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "machine_id": {
 | 
				
			||||||
 | 
					          "name": "machine_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "origin": {
 | 
				
			||||||
 | 
					          "name": "origin",
 | 
				
			||||||
 | 
					          "type": "workflow_run_origin",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "'api'"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "status": {
 | 
				
			||||||
 | 
					          "name": "status",
 | 
				
			||||||
 | 
					          "type": "workflow_run_status",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "'not-started'"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "ended_at": {
 | 
				
			||||||
 | 
					          "name": "ended_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "workflow_runs_workflow_version_id_workflow_versions_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflow_runs",
 | 
				
			||||||
 | 
					          "tableTo": "workflow_versions",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "workflow_version_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "set null",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_runs_workflow_id_workflows_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflow_runs_workflow_id_workflows_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflow_runs",
 | 
				
			||||||
 | 
					          "tableTo": "workflows",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "workflow_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_runs_machine_id_machines_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflow_runs_machine_id_machines_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflow_runs",
 | 
				
			||||||
 | 
					          "tableTo": "machines",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "machine_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "set null",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflows": {
 | 
				
			||||||
 | 
					      "name": "workflows",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "user_id": {
 | 
				
			||||||
 | 
					          "name": "user_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "org_id": {
 | 
				
			||||||
 | 
					          "name": "org_id",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "name": {
 | 
				
			||||||
 | 
					          "name": "name",
 | 
				
			||||||
 | 
					          "type": "text",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "workflows_user_id_users_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflows_user_id_users_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflows",
 | 
				
			||||||
 | 
					          "tableTo": "users",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "user_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflow_versions": {
 | 
				
			||||||
 | 
					      "name": "workflow_versions",
 | 
				
			||||||
 | 
					      "schema": "comfyui_deploy",
 | 
				
			||||||
 | 
					      "columns": {
 | 
				
			||||||
 | 
					        "workflow_id": {
 | 
				
			||||||
 | 
					          "name": "workflow_id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "id": {
 | 
				
			||||||
 | 
					          "name": "id",
 | 
				
			||||||
 | 
					          "type": "uuid",
 | 
				
			||||||
 | 
					          "primaryKey": true,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "gen_random_uuid()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow": {
 | 
				
			||||||
 | 
					          "name": "workflow",
 | 
				
			||||||
 | 
					          "type": "jsonb",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "workflow_api": {
 | 
				
			||||||
 | 
					          "name": "workflow_api",
 | 
				
			||||||
 | 
					          "type": "jsonb",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": false
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "version": {
 | 
				
			||||||
 | 
					          "name": "version",
 | 
				
			||||||
 | 
					          "type": "integer",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "created_at": {
 | 
				
			||||||
 | 
					          "name": "created_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "updated_at": {
 | 
				
			||||||
 | 
					          "name": "updated_at",
 | 
				
			||||||
 | 
					          "type": "timestamp",
 | 
				
			||||||
 | 
					          "primaryKey": false,
 | 
				
			||||||
 | 
					          "notNull": true,
 | 
				
			||||||
 | 
					          "default": "now()"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "indexes": {},
 | 
				
			||||||
 | 
					      "foreignKeys": {
 | 
				
			||||||
 | 
					        "workflow_versions_workflow_id_workflows_id_fk": {
 | 
				
			||||||
 | 
					          "name": "workflow_versions_workflow_id_workflows_id_fk",
 | 
				
			||||||
 | 
					          "tableFrom": "workflow_versions",
 | 
				
			||||||
 | 
					          "tableTo": "workflows",
 | 
				
			||||||
 | 
					          "columnsFrom": [
 | 
				
			||||||
 | 
					            "workflow_id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "columnsTo": [
 | 
				
			||||||
 | 
					            "id"
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          "onDelete": "cascade",
 | 
				
			||||||
 | 
					          "onUpdate": "no action"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "compositePrimaryKeys": {},
 | 
				
			||||||
 | 
					      "uniqueConstraints": {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "enums": {
 | 
				
			||||||
 | 
					    "deployment_environment": {
 | 
				
			||||||
 | 
					      "name": "deployment_environment",
 | 
				
			||||||
 | 
					      "values": {
 | 
				
			||||||
 | 
					        "staging": "staging",
 | 
				
			||||||
 | 
					        "production": "production"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "machine_status": {
 | 
				
			||||||
 | 
					      "name": "machine_status",
 | 
				
			||||||
 | 
					      "values": {
 | 
				
			||||||
 | 
					        "ready": "ready",
 | 
				
			||||||
 | 
					        "building": "building",
 | 
				
			||||||
 | 
					        "error": "error"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "machine_type": {
 | 
				
			||||||
 | 
					      "name": "machine_type",
 | 
				
			||||||
 | 
					      "values": {
 | 
				
			||||||
 | 
					        "classic": "classic",
 | 
				
			||||||
 | 
					        "runpod-serverless": "runpod-serverless",
 | 
				
			||||||
 | 
					        "modal-serverless": "modal-serverless"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflow_run_origin": {
 | 
				
			||||||
 | 
					      "name": "workflow_run_origin",
 | 
				
			||||||
 | 
					      "values": {
 | 
				
			||||||
 | 
					        "manual": "manual",
 | 
				
			||||||
 | 
					        "api": "api"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "workflow_run_status": {
 | 
				
			||||||
 | 
					      "name": "workflow_run_status",
 | 
				
			||||||
 | 
					      "values": {
 | 
				
			||||||
 | 
					        "not-started": "not-started",
 | 
				
			||||||
 | 
					        "running": "running",
 | 
				
			||||||
 | 
					        "uploading": "uploading",
 | 
				
			||||||
 | 
					        "success": "success",
 | 
				
			||||||
 | 
					        "failed": "failed"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "schemas": {
 | 
				
			||||||
 | 
					    "comfyui_deploy": "comfyui_deploy"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "_meta": {
 | 
				
			||||||
 | 
					    "schemas": {},
 | 
				
			||||||
 | 
					    "tables": {},
 | 
				
			||||||
 | 
					    "columns": {}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -141,6 +141,13 @@
 | 
				
			|||||||
      "when": 1704174903117,
 | 
					      "when": 1704174903117,
 | 
				
			||||||
      "tag": "0019_damp_stick",
 | 
					      "tag": "0019_damp_stick",
 | 
				
			||||||
      "breakpoints": true
 | 
					      "breakpoints": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "idx": 20,
 | 
				
			||||||
 | 
					      "version": "5",
 | 
				
			||||||
 | 
					      "when": 1704350033885,
 | 
				
			||||||
 | 
					      "tag": "0020_complete_black_tom",
 | 
				
			||||||
 | 
					      "breakpoints": true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										50
									
								
								web/src/app/(app)/api/machine-built/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								web/src/app/(app)/api/machine-built/route.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					import { parseDataSafe } from "../../../../lib/parseDataSafe";
 | 
				
			||||||
 | 
					import { db } from "@/db/db";
 | 
				
			||||||
 | 
					import { machinesTable } from "@/db/schema";
 | 
				
			||||||
 | 
					import { eq } from "drizzle-orm";
 | 
				
			||||||
 | 
					import { NextResponse } from "next/server";
 | 
				
			||||||
 | 
					import { z } from "zod";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Request = z.object({
 | 
				
			||||||
 | 
					  machine_id: z.string(),
 | 
				
			||||||
 | 
					  endpoint: z.string().optional(),
 | 
				
			||||||
 | 
					  build_log: z.string().optional(),
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function POST(request: Request) {
 | 
				
			||||||
 | 
					  const [data, error] = await parseDataSafe(Request, request);
 | 
				
			||||||
 | 
					  if (!data || error) return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const { machine_id, endpoint, build_log } = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (endpoint) {
 | 
				
			||||||
 | 
					    await db
 | 
				
			||||||
 | 
					      .update(machinesTable)
 | 
				
			||||||
 | 
					      .set({
 | 
				
			||||||
 | 
					        status: "ready",
 | 
				
			||||||
 | 
					        endpoint: endpoint,
 | 
				
			||||||
 | 
					        build_log: build_log,
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      .where(eq(machinesTable.id, machine_id));
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    // console.log(data);
 | 
				
			||||||
 | 
					    await db
 | 
				
			||||||
 | 
					      .update(machinesTable)
 | 
				
			||||||
 | 
					      .set({
 | 
				
			||||||
 | 
					        status: "error",
 | 
				
			||||||
 | 
					        build_log: build_log,
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      .where(eq(machinesTable.id, machine_id));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return NextResponse.json(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      message: "success",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      status: 200,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								web/src/app/(app)/machines/[machine_id]/loading.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								web/src/app/(app)/machines/[machine_id]/loading.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { LoadingPageWrapper } from "@/components/LoadingWrapper";
 | 
				
			||||||
 | 
					import { usePathname } from "next/navigation";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Loading() {
 | 
				
			||||||
 | 
					  const pathName = usePathname();
 | 
				
			||||||
 | 
					  return <LoadingPageWrapper className="h-full" tag={pathName.toLowerCase()} />;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								web/src/app/(app)/machines/[machine_id]/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								web/src/app/(app)/machines/[machine_id]/page.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					import { MachineBuildLog } from "../../../../components/MachineBuildLog";
 | 
				
			||||||
 | 
					import { LogsViewer } from "@/components/LogsViewer";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  Card,
 | 
				
			||||||
 | 
					  CardContent,
 | 
				
			||||||
 | 
					  CardDescription,
 | 
				
			||||||
 | 
					  CardHeader,
 | 
				
			||||||
 | 
					  CardTitle,
 | 
				
			||||||
 | 
					} from "@/components/ui/card";
 | 
				
			||||||
 | 
					import { getRelativeTime } from "@/lib/getRelativeTime";
 | 
				
			||||||
 | 
					import { getMachineById } from "@/server/curdMachine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function Page({
 | 
				
			||||||
 | 
					  params,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					  params: { machine_id: string };
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  const machine = await getMachineById(params.machine_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					      <Card className="w-full h-fit mt-4">
 | 
				
			||||||
 | 
					        <CardHeader>
 | 
				
			||||||
 | 
					          <CardTitle>{machine.name}</CardTitle>
 | 
				
			||||||
 | 
					          <CardDescription suppressHydrationWarning={true}>
 | 
				
			||||||
 | 
					            {getRelativeTime(machine?.updated_at)}
 | 
				
			||||||
 | 
					          </CardDescription>
 | 
				
			||||||
 | 
					        </CardHeader>
 | 
				
			||||||
 | 
					        <CardContent>
 | 
				
			||||||
 | 
					          {machine.status == "building" && (
 | 
				
			||||||
 | 
					            <MachineBuildLog
 | 
				
			||||||
 | 
					              machine_id={params.machine_id}
 | 
				
			||||||
 | 
					              endpoint={process.env.MODAL_BUILDER_URL!}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					          {machine.build_log && (
 | 
				
			||||||
 | 
					            <LogsViewer logs={JSON.parse(machine.build_log)} />
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					        </CardContent>
 | 
				
			||||||
 | 
					      </Card>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,6 +0,0 @@
 | 
				
			|||||||
import { LoadingPageWrapper } from "@/components/LoadingWrapper";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default function Loading() {
 | 
					 | 
				
			||||||
  // You can add any UI inside Loading, including a Skeleton.
 | 
					 | 
				
			||||||
  return <LoadingPageWrapper tag="workflow" />;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										46
									
								
								web/src/components/LogsViewer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								web/src/components/LogsViewer.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React, { useEffect, useRef } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type LogsType = {
 | 
				
			||||||
 | 
					  machine_id?: string;
 | 
				
			||||||
 | 
					  logs: string;
 | 
				
			||||||
 | 
					  timestamp: number;
 | 
				
			||||||
 | 
					}[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function LogsViewer({ logs }: { logs: LogsType }) {
 | 
				
			||||||
 | 
					  const container = useRef<HTMLDivElement | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    // console.log(logs.length, container.current);
 | 
				
			||||||
 | 
					    if (container.current) {
 | 
				
			||||||
 | 
					      const scrollHeight = container.current.scrollHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      container.current.scrollTo({
 | 
				
			||||||
 | 
					        top: scrollHeight,
 | 
				
			||||||
 | 
					        behavior: "smooth",
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [logs.length]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      ref={(ref) => {
 | 
				
			||||||
 | 
					        if (!container.current && ref) {
 | 
				
			||||||
 | 
					          const scrollHeight = ref.scrollHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          ref.scrollTo({
 | 
				
			||||||
 | 
					            top: scrollHeight,
 | 
				
			||||||
 | 
					            behavior: "instant",
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        container.current = ref;
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      className="flex flex-col text-xs p-2 overflow-y-scroll max-h-[400px] whitespace-break-spaces"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {logs.map((x, i) => (
 | 
				
			||||||
 | 
					        <div key={i}>{x.logs}</div>
 | 
				
			||||||
 | 
					      ))}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								web/src/components/MachineBuildLog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								web/src/components/MachineBuildLog.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { LogsType } from "@/components/LogsViewer";
 | 
				
			||||||
 | 
					import { LogsViewer } from "@/components/LogsViewer";
 | 
				
			||||||
 | 
					import { getConnectionStatus } from "@/components/getConnectionStatus";
 | 
				
			||||||
 | 
					import { useEffect, useState } from "react";
 | 
				
			||||||
 | 
					import useWebSocket from "react-use-websocket";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function MachineBuildLog({
 | 
				
			||||||
 | 
					  machine_id,
 | 
				
			||||||
 | 
					  endpoint,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					  machine_id: string;
 | 
				
			||||||
 | 
					  endpoint: string;
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  const [logs, setLogs] = useState<LogsType>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const wsEndpoint = endpoint.replace(/^http/, "ws");
 | 
				
			||||||
 | 
					  const { lastMessage, readyState } = useWebSocket(
 | 
				
			||||||
 | 
					    `${wsEndpoint}/ws/${machine_id}`,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      shouldReconnect: () => true,
 | 
				
			||||||
 | 
					      reconnectAttempts: 20,
 | 
				
			||||||
 | 
					      reconnectInterval: 1000,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const connectionStatus = getConnectionStatus(readyState);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    if (!lastMessage?.data) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const message = JSON.parse(lastMessage.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log(message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (message?.event === "LOGS") {
 | 
				
			||||||
 | 
					      setLogs((logs) => [...(logs ?? []), message.data]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [lastMessage]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					      {connectionStatus}
 | 
				
			||||||
 | 
					      <LogsViewer logs={logs} />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -23,8 +23,12 @@ import {
 | 
				
			|||||||
  TableRow,
 | 
					  TableRow,
 | 
				
			||||||
} from "@/components/ui/table";
 | 
					} from "@/components/ui/table";
 | 
				
			||||||
import { type MachineType } from "@/db/schema";
 | 
					import { type MachineType } from "@/db/schema";
 | 
				
			||||||
import { addMachineSchema } from "@/server/addMachineSchema";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					  addCustomMachineSchema,
 | 
				
			||||||
 | 
					  addMachineSchema,
 | 
				
			||||||
 | 
					} from "@/server/addMachineSchema";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  addCustomMachine,
 | 
				
			||||||
  addMachine,
 | 
					  addMachine,
 | 
				
			||||||
  deleteMachine,
 | 
					  deleteMachine,
 | 
				
			||||||
  disableMachine,
 | 
					  disableMachine,
 | 
				
			||||||
@ -92,10 +96,15 @@ export const columns: ColumnDef<Machine>[] = [
 | 
				
			|||||||
      return (
 | 
					      return (
 | 
				
			||||||
        // <a className="hover:underline" href={`/${row.original.id}`}>
 | 
					        // <a className="hover:underline" href={`/${row.original.id}`}>
 | 
				
			||||||
        <div className="flex flex-row gap-2 items-center">
 | 
					        <div className="flex flex-row gap-2 items-center">
 | 
				
			||||||
          <div>{row.getValue("name")}</div>
 | 
					          <a href={`/machines/${row.original.id}`} className="hover:underline">
 | 
				
			||||||
 | 
					            {row.getValue("name")}
 | 
				
			||||||
 | 
					          </a>
 | 
				
			||||||
          {row.original.disabled && (
 | 
					          {row.original.disabled && (
 | 
				
			||||||
            <Badge variant="destructive">Disabled</Badge>
 | 
					            <Badge variant="destructive">Disabled</Badge>
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
 | 
					          {!row.original.disabled && row.original.status && (
 | 
				
			||||||
 | 
					            <Badge variant="outline">{row.original.status}</Badge>
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        // </a>
 | 
					        // </a>
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -254,6 +263,20 @@ export function MachineList({ data }: { data: Machine[] }) {
 | 
				
			|||||||
            serverAction={addMachine}
 | 
					            serverAction={addMachine}
 | 
				
			||||||
            formSchema={addMachineSchema}
 | 
					            formSchema={addMachineSchema}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
 | 
					          <InsertModal
 | 
				
			||||||
 | 
					            title="Custom Machine"
 | 
				
			||||||
 | 
					            description="Add custom Comfyui machines to your account."
 | 
				
			||||||
 | 
					            serverAction={addCustomMachine}
 | 
				
			||||||
 | 
					            formSchema={addCustomMachineSchema}
 | 
				
			||||||
 | 
					            fieldConfig={{
 | 
				
			||||||
 | 
					              type: {
 | 
				
			||||||
 | 
					                fieldType: "fallback",
 | 
				
			||||||
 | 
					                inputProps: {
 | 
				
			||||||
 | 
					                  disabled: true,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div className="rounded-md border overflow-x-auto w-full">
 | 
					      <div className="rounded-md border overflow-x-auto w-full">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,7 @@
 | 
				
			|||||||
"use client";
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { LogsViewer } from "./LogsViewer";
 | 
				
			||||||
 | 
					import { getConnectionStatus } from "./getConnectionStatus";
 | 
				
			||||||
import { Badge } from "@/components/ui/badge";
 | 
					import { Badge } from "@/components/ui/badge";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Dialog,
 | 
					  Dialog,
 | 
				
			||||||
@ -10,9 +12,8 @@ import {
 | 
				
			|||||||
  DialogTrigger,
 | 
					  DialogTrigger,
 | 
				
			||||||
} from "@/components/ui/dialog";
 | 
					} from "@/components/ui/dialog";
 | 
				
			||||||
import type { getMachines } from "@/server/curdMachine";
 | 
					import type { getMachines } from "@/server/curdMachine";
 | 
				
			||||||
import { Check, CircleOff, SatelliteDish } from "lucide-react";
 | 
					import React, { useEffect, useState } from "react";
 | 
				
			||||||
import React, { useEffect, useRef, useState } from "react";
 | 
					import useWebSocket from "react-use-websocket";
 | 
				
			||||||
import useWebSocket, { ReadyState } from "react-use-websocket";
 | 
					 | 
				
			||||||
import { create } from "zustand";
 | 
					import { create } from "zustand";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type State = {
 | 
					type State = {
 | 
				
			||||||
@ -98,17 +99,7 @@ function MachineWS({
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const connectionStatus = {
 | 
					  const connectionStatus = getConnectionStatus(readyState);
 | 
				
			||||||
    [ReadyState.CONNECTING]: (
 | 
					 | 
				
			||||||
      <SatelliteDish size={14} className="text-orange-500" />
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    [ReadyState.OPEN]: <Check size={14} className="text-green-500" />,
 | 
					 | 
				
			||||||
    [ReadyState.CLOSING]: <CircleOff size={14} className="text-orange-500" />,
 | 
					 | 
				
			||||||
    [ReadyState.CLOSED]: <CircleOff size={14} className="text-red-500" />,
 | 
					 | 
				
			||||||
    [ReadyState.UNINSTANTIATED]: "Uninstantiated",
 | 
					 | 
				
			||||||
  }[readyState];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const container = useRef<HTMLDivElement | null>(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    if (!lastMessage?.data) return;
 | 
					    if (!lastMessage?.data) return;
 | 
				
			||||||
@ -130,18 +121,6 @@ function MachineWS({
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }, [lastMessage]);
 | 
					  }, [lastMessage]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					 | 
				
			||||||
    // console.log(logs.length, container.current);
 | 
					 | 
				
			||||||
    if (container.current) {
 | 
					 | 
				
			||||||
      const scrollHeight = container.current.scrollHeight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      container.current.scrollTo({
 | 
					 | 
				
			||||||
        top: scrollHeight,
 | 
					 | 
				
			||||||
        behavior: "smooth",
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }, [logs.length]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Dialog>
 | 
					    <Dialog>
 | 
				
			||||||
      <DialogTrigger asChild className="">
 | 
					      <DialogTrigger asChild className="">
 | 
				
			||||||
@ -156,24 +135,7 @@ function MachineWS({
 | 
				
			|||||||
            You can view your run's outputs here
 | 
					            You can view your run's outputs here
 | 
				
			||||||
          </DialogDescription>
 | 
					          </DialogDescription>
 | 
				
			||||||
        </DialogHeader>
 | 
					        </DialogHeader>
 | 
				
			||||||
        <div
 | 
					        <LogsViewer logs={logs} />
 | 
				
			||||||
          ref={(ref) => {
 | 
					 | 
				
			||||||
            if (!container.current && ref) {
 | 
					 | 
				
			||||||
              const scrollHeight = ref.scrollHeight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              ref.scrollTo({
 | 
					 | 
				
			||||||
                top: scrollHeight,
 | 
					 | 
				
			||||||
                behavior: "instant",
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            container.current = ref;
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
          className="flex flex-col text-xs p-2 overflow-y-scroll max-h-[400px] whitespace-break-spaces"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          {logs.map((x, i) => (
 | 
					 | 
				
			||||||
            <div key={i}>{x.logs}</div>
 | 
					 | 
				
			||||||
          ))}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </DialogContent>
 | 
					      </DialogContent>
 | 
				
			||||||
    </Dialog>
 | 
					    </Dialog>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								web/src/components/getConnectionStatus.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								web/src/components/getConnectionStatus.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import { Check, CircleOff, SatelliteDish } from "lucide-react";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { ReadyState } from "react-use-websocket";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getConnectionStatus(readyState: ReadyState) {
 | 
				
			||||||
 | 
					  const connectionStatus = {
 | 
				
			||||||
 | 
					    [ReadyState.CONNECTING]: (
 | 
				
			||||||
 | 
					      <SatelliteDish size={14} className="text-orange-500" />
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    [ReadyState.OPEN]: <Check size={14} className="text-green-500" />,
 | 
				
			||||||
 | 
					    [ReadyState.CLOSING]: <CircleOff size={14} className="text-orange-500" />,
 | 
				
			||||||
 | 
					    [ReadyState.CLOSED]: <CircleOff size={14} className="text-red-500" />,
 | 
				
			||||||
 | 
					    [ReadyState.UNINSTANTIATED]: "Uninstantiated",
 | 
				
			||||||
 | 
					  }[readyState];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return connectionStatus;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -108,6 +108,12 @@ export const machinesType = pgEnum("machine_type", [
 | 
				
			|||||||
  "modal-serverless",
 | 
					  "modal-serverless",
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const machinesStatus = pgEnum("machine_status", [
 | 
				
			||||||
 | 
					  "ready",
 | 
				
			||||||
 | 
					  "building",
 | 
				
			||||||
 | 
					  "error",
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We still want to keep the workflow run record.
 | 
					// We still want to keep the workflow run record.
 | 
				
			||||||
export const workflowRunsTable = dbSchema.table("workflow_runs", {
 | 
					export const workflowRunsTable = dbSchema.table("workflow_runs", {
 | 
				
			||||||
  id: uuid("id").primaryKey().defaultRandom().notNull(),
 | 
					  id: uuid("id").primaryKey().defaultRandom().notNull(),
 | 
				
			||||||
@ -193,6 +199,9 @@ export const machinesTable = dbSchema.table("machines", {
 | 
				
			|||||||
  disabled: boolean("disabled").default(false).notNull(),
 | 
					  disabled: boolean("disabled").default(false).notNull(),
 | 
				
			||||||
  auth_token: text("auth_token"),
 | 
					  auth_token: text("auth_token"),
 | 
				
			||||||
  type: machinesType("type").notNull().default("classic"),
 | 
					  type: machinesType("type").notNull().default("classic"),
 | 
				
			||||||
 | 
					  status: machinesStatus("status").notNull().default("ready"),
 | 
				
			||||||
 | 
					  snapshot: jsonb("snapshot").$type<any>(),
 | 
				
			||||||
 | 
					  build_log: text("build_log"),
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const insertMachineSchema = createInsertSchema(machinesTable, {
 | 
					export const insertMachineSchema = createInsertSchema(machinesTable, {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import { insertMachineSchema } from "@/db/schema";
 | 
					import { insertMachineSchema, machinesTable } from "@/db/schema";
 | 
				
			||||||
 | 
					import { createInsertSchema } from "drizzle-zod";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const addMachineSchema = insertMachineSchema.pick({
 | 
					export const addMachineSchema = insertMachineSchema.pick({
 | 
				
			||||||
  name: true,
 | 
					  name: true,
 | 
				
			||||||
@ -6,3 +7,14 @@ export const addMachineSchema = insertMachineSchema.pick({
 | 
				
			|||||||
  type: true,
 | 
					  type: true,
 | 
				
			||||||
  auth_token: true,
 | 
					  auth_token: true,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const insertCustomMachineSchema = createInsertSchema(machinesTable, {
 | 
				
			||||||
 | 
					  name: (schema) => schema.name.default("My Machine"),
 | 
				
			||||||
 | 
					  type: (schema) => schema.type.default("modal-serverless"),
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addCustomMachineSchema = insertCustomMachineSchema.pick({
 | 
				
			||||||
 | 
					  name: true,
 | 
				
			||||||
 | 
					  type: true,
 | 
				
			||||||
 | 
					  snapshot: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,17 @@
 | 
				
			|||||||
"use server";
 | 
					"use server";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { addMachineSchema } from "./addMachineSchema";
 | 
					import type {
 | 
				
			||||||
 | 
					  addCustomMachineSchema,
 | 
				
			||||||
 | 
					  addMachineSchema,
 | 
				
			||||||
 | 
					} from "./addMachineSchema";
 | 
				
			||||||
import { withServerPromise } from "./withServerPromise";
 | 
					import { withServerPromise } from "./withServerPromise";
 | 
				
			||||||
import { db } from "@/db/db";
 | 
					import { db } from "@/db/db";
 | 
				
			||||||
import { machinesTable } from "@/db/schema";
 | 
					import { machinesTable } from "@/db/schema";
 | 
				
			||||||
import { auth } from "@clerk/nextjs";
 | 
					import { auth } from "@clerk/nextjs";
 | 
				
			||||||
import { and, eq } from "drizzle-orm";
 | 
					import { and, eq, isNull } from "drizzle-orm";
 | 
				
			||||||
import { revalidatePath } from "next/cache";
 | 
					import { revalidatePath } from "next/cache";
 | 
				
			||||||
 | 
					import { headers } from "next/headers";
 | 
				
			||||||
 | 
					import { redirect } from "next/navigation";
 | 
				
			||||||
import "server-only";
 | 
					import "server-only";
 | 
				
			||||||
import type { z } from "zod";
 | 
					import type { z } from "zod";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,6 +32,26 @@ export async function getMachines() {
 | 
				
			|||||||
  return machines;
 | 
					  return machines;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function getMachineById(id: string) {
 | 
				
			||||||
 | 
					  const { userId, orgId } = auth();
 | 
				
			||||||
 | 
					  if (!userId) throw new Error("No user id");
 | 
				
			||||||
 | 
					  const machines = await db
 | 
				
			||||||
 | 
					    .select()
 | 
				
			||||||
 | 
					    .from(machinesTable)
 | 
				
			||||||
 | 
					    .where(
 | 
				
			||||||
 | 
					      and(
 | 
				
			||||||
 | 
					        orgId
 | 
				
			||||||
 | 
					          ? eq(machinesTable.org_id, orgId)
 | 
				
			||||||
 | 
					          : and(
 | 
				
			||||||
 | 
					              eq(machinesTable.user_id, userId),
 | 
				
			||||||
 | 
					              isNull(machinesTable.org_id)
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        eq(machinesTable.id, id)
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  return machines[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const addMachine = withServerPromise(
 | 
					export const addMachine = withServerPromise(
 | 
				
			||||||
  async (data: z.infer<typeof addMachineSchema>) => {
 | 
					  async (data: z.infer<typeof addMachineSchema>) => {
 | 
				
			||||||
    const { userId, orgId } = auth();
 | 
					    const { userId, orgId } = auth();
 | 
				
			||||||
@ -42,6 +67,72 @@ export const addMachine = withServerPromise(
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addCustomMachine = withServerPromise(
 | 
				
			||||||
 | 
					  async (data: z.infer<typeof addCustomMachineSchema>) => {
 | 
				
			||||||
 | 
					    const { userId, orgId } = auth();
 | 
				
			||||||
 | 
					    const headersList = headers();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!userId) return { error: "No user id" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Insert to our db
 | 
				
			||||||
 | 
					    const a = await db
 | 
				
			||||||
 | 
					      .insert(machinesTable)
 | 
				
			||||||
 | 
					      .values({
 | 
				
			||||||
 | 
					        ...data,
 | 
				
			||||||
 | 
					        org_id: orgId,
 | 
				
			||||||
 | 
					        user_id: userId,
 | 
				
			||||||
 | 
					        status: "building",
 | 
				
			||||||
 | 
					        endpoint: "not-ready",
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      .returning();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const b = a[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // const origin = new URL(request.url).origin;
 | 
				
			||||||
 | 
					    const domain = headersList.get("x-forwarded-host") || "";
 | 
				
			||||||
 | 
					    const protocol = headersList.get("x-forwarded-proto") || "";
 | 
				
			||||||
 | 
					    // console.log("domain", domain);
 | 
				
			||||||
 | 
					    // console.log("domain", `${protocol}://${domain}/api/machine-built`);
 | 
				
			||||||
 | 
					    // return { message: "Machine Building" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (domain === "") {
 | 
				
			||||||
 | 
					      throw new Error("No domain");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Call remote builder
 | 
				
			||||||
 | 
					    const result = await fetch(`${process.env.MODAL_BUILDER_URL!}/create`, {
 | 
				
			||||||
 | 
					      method: "POST",
 | 
				
			||||||
 | 
					      headers: {
 | 
				
			||||||
 | 
					        "Content-Type": "application/json",
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      body: JSON.stringify({
 | 
				
			||||||
 | 
					        machine_id: b.id,
 | 
				
			||||||
 | 
					        name: b.id,
 | 
				
			||||||
 | 
					        snapshot: JSON.parse(data.snapshot as string),
 | 
				
			||||||
 | 
					        callback_url: `${protocol}://${domain}/api/machine-built`,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!result.ok) {
 | 
				
			||||||
 | 
					      const error_log = await result.text();
 | 
				
			||||||
 | 
					      await db
 | 
				
			||||||
 | 
					        .update(machinesTable)
 | 
				
			||||||
 | 
					        .set({
 | 
				
			||||||
 | 
					          ...data,
 | 
				
			||||||
 | 
					          status: "error",
 | 
				
			||||||
 | 
					          build_log: error_log,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .where(eq(machinesTable.id, b.id));
 | 
				
			||||||
 | 
					      throw new Error(`Error: ${result.statusText} ${error_log}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redirect(`/machines/${b.id}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // revalidatePath("/machines");
 | 
				
			||||||
 | 
					    return { message: "Machine Building" };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const updateMachine = withServerPromise(
 | 
					export const updateMachine = withServerPromise(
 | 
				
			||||||
  async ({
 | 
					  async ({
 | 
				
			||||||
    id,
 | 
					    id,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,8 @@
 | 
				
			|||||||
 | 
					import { isRedirectError } from "next/dist/client/components/redirect";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function wrapServerPromise<T>(result: Promise<T>) {
 | 
					export async function wrapServerPromise<T>(result: Promise<T>) {
 | 
				
			||||||
  return result.catch((error) => {
 | 
					  return result.catch((error) => {
 | 
				
			||||||
 | 
					    if (isRedirectError(error)) throw error;
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      error: error.message,
 | 
					      error: error.message,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user