diff --git a/drizzle/migrations/0000_clear_sister_grimm.sql b/drizzle/migrations/0000_clear_sister_grimm.sql
new file mode 100644
index 0000000..a4e5f87
--- /dev/null
+++ b/drizzle/migrations/0000_clear_sister_grimm.sql
@@ -0,0 +1,327 @@
+CREATE TABLE "checklist_items" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "checklist_id" uuid NOT NULL,
+ "text" text NOT NULL,
+ "item_type" text DEFAULT 'checkbox' NOT NULL,
+ "unit" text,
+ "checked" boolean DEFAULT false NOT NULL,
+ "value" text,
+ "sort_order" integer DEFAULT 0 NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "checklist_templates" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "component_documents" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "component_id" uuid NOT NULL,
+ "file_path" text NOT NULL,
+ "original_filename" text NOT NULL,
+ "file_type" text,
+ "description" text,
+ "uploaded_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "component_images" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "component_id" uuid NOT NULL,
+ "file_path" text NOT NULL,
+ "thumbnail_path" text,
+ "caption" text,
+ "uploaded_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "component_instances" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "component_id" uuid NOT NULL,
+ "instance_number" integer DEFAULT 1 NOT NULL,
+ "serial_number" text,
+ "condition" text DEFAULT 'Working' NOT NULL,
+ "firmware_version" text,
+ "notes" text,
+ "current_device_id" uuid,
+ "location_id" uuid,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "instances_condition_check" CHECK ("component_instances"."condition" IN ('Working', 'Faulty', 'Unknown', 'Refurbished'))
+);
+--> statement-breakpoint
+CREATE TABLE "components" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "component_type" text NOT NULL,
+ "brand" text,
+ "part_number" text,
+ "specs" text,
+ "notes" text,
+ "default_condition" text DEFAULT 'Working' NOT NULL,
+ "default_firmware_version" text,
+ "default_location_id" uuid,
+ "disabled" boolean DEFAULT false NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "computer_details" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "os_version" text,
+ "firmware_version" text,
+ "installed_software" text,
+ CONSTRAINT "computer_details_device_id_unique" UNIQUE("device_id")
+);
+--> statement-breakpoint
+CREATE TABLE "device_checklists" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "title" text NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "device_documents" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "file_path" text NOT NULL,
+ "original_filename" text NOT NULL,
+ "file_type" text,
+ "description" text,
+ "uploaded_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "device_images" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "file_path" text NOT NULL,
+ "thumbnail_path" text,
+ "caption" text,
+ "sort_order" integer DEFAULT 0,
+ "uploaded_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "device_log" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "type" text NOT NULL,
+ "description" text NOT NULL,
+ "condition_after" text,
+ "performed_by" text,
+ "performed_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "device_log_type_check" CHECK ("device_log"."type" IN ('repair', 'inspection', 'cleaning', 'modification', 'diagnostic', 'recap', 'other'))
+);
+--> statement-breakpoint
+CREATE TABLE "device_tags" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "device_id" uuid NOT NULL,
+ "tag_uid" text,
+ "payload_url" text NOT NULL,
+ "written_by" text,
+ "written_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "devices" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "category" text NOT NULL,
+ "brand" text,
+ "model" text,
+ "serial_number" text,
+ "year" integer,
+ "condition" text DEFAULT 'Waiting to be Tested' NOT NULL,
+ "voltage" text,
+ "frequency" text,
+ "origin" text,
+ "fault_description" text,
+ "repair_notes" text,
+ "location_id" uuid,
+ "initial_condition" text,
+ "general_notes" text,
+ "disabled" boolean DEFAULT false NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "devices_category_check" CHECK ("devices"."category" IN ('Computer', 'Audio Equipment', 'Peripheral', 'Other')),
+ CONSTRAINT "devices_condition_check" CHECK ("devices"."condition" IN ('Working', 'In Repair', 'Waiting for Repair', 'Waiting to be Tested', 'Unrepairable'))
+);
+--> statement-breakpoint
+CREATE TABLE "feature_requests" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "status" text DEFAULT 'open' NOT NULL,
+ "votes" integer DEFAULT 0 NOT NULL,
+ "created_by" text,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "installation_log" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "instance_id" uuid NOT NULL,
+ "device_id" uuid NOT NULL,
+ "action" text NOT NULL,
+ "performed_by" text,
+ "notes" text,
+ "performed_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "install_log_action_check" CHECK ("installation_log"."action" IN ('installed', 'removed', 'swapped'))
+);
+--> statement-breakpoint
+CREATE TABLE "locations" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text NOT NULL,
+ "description" text,
+ "parent_id" uuid,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "parts" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text,
+ "category" text NOT NULL,
+ "mpn" text,
+ "value" text,
+ "voltage" text,
+ "tolerance" text,
+ "power" text,
+ "mounting" text,
+ "package" text,
+ "quantity" integer DEFAULT 0 NOT NULL,
+ "unit" text DEFAULT 'pcs' NOT NULL,
+ "location_id" uuid,
+ "notes" text,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "sessions" (
+ "id" text PRIMARY KEY NOT NULL,
+ "user_id" text NOT NULL,
+ "expires_at" timestamp with time zone NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "template_items" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "template_id" uuid NOT NULL,
+ "text" text NOT NULL,
+ "item_type" text DEFAULT 'checkbox' NOT NULL,
+ "unit" text,
+ "sort_order" integer DEFAULT 0 NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "todos" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "status" text DEFAULT 'todo' NOT NULL,
+ "priority" integer DEFAULT 2 NOT NULL,
+ "device_id" uuid,
+ "due_date" timestamp with time zone,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "todos_status_check" CHECK ("todos"."status" IN ('todo', 'in_progress', 'done')),
+ CONSTRAINT "todos_priority_check" CHECK ("todos"."priority" IN (0, 1, 2, 3))
+);
+--> statement-breakpoint
+CREATE TABLE "users" (
+ "id" text PRIMARY KEY NOT NULL,
+ "email" text NOT NULL,
+ "display_name" text,
+ "password_hash" text NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "users_email_unique" UNIQUE("email")
+);
+--> statement-breakpoint
+CREATE TABLE "wiki_categories" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text NOT NULL,
+ "slug" text NOT NULL,
+ "description" text,
+ "sort_order" integer DEFAULT 0 NOT NULL,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "wiki_categories_slug_unique" UNIQUE("slug")
+);
+--> statement-breakpoint
+CREATE TABLE "wiki_page_tags" (
+ "page_id" uuid NOT NULL,
+ "tag_id" uuid NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "wiki_pages" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "title" text NOT NULL,
+ "slug" text NOT NULL,
+ "content" text NOT NULL,
+ "category_id" uuid,
+ "created_by" text,
+ "updated_by" text,
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT "wiki_pages_slug_unique" UNIQUE("slug")
+);
+--> statement-breakpoint
+CREATE TABLE "wiki_tags" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "name" text NOT NULL,
+ CONSTRAINT "wiki_tags_name_unique" UNIQUE("name")
+);
+--> statement-breakpoint
+ALTER TABLE "checklist_items" ADD CONSTRAINT "checklist_items_checklist_id_device_checklists_id_fk" FOREIGN KEY ("checklist_id") REFERENCES "public"."device_checklists"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "component_documents" ADD CONSTRAINT "component_documents_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "component_images" ADD CONSTRAINT "component_images_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "component_instances" ADD CONSTRAINT "component_instances_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "component_instances" ADD CONSTRAINT "component_instances_current_device_id_devices_id_fk" FOREIGN KEY ("current_device_id") REFERENCES "public"."devices"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "component_instances" ADD CONSTRAINT "component_instances_location_id_locations_id_fk" FOREIGN KEY ("location_id") REFERENCES "public"."locations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "components" ADD CONSTRAINT "components_default_location_id_locations_id_fk" FOREIGN KEY ("default_location_id") REFERENCES "public"."locations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "computer_details" ADD CONSTRAINT "computer_details_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "device_checklists" ADD CONSTRAINT "device_checklists_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "device_documents" ADD CONSTRAINT "device_documents_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "device_images" ADD CONSTRAINT "device_images_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "device_log" ADD CONSTRAINT "device_log_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "device_tags" ADD CONSTRAINT "device_tags_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "devices" ADD CONSTRAINT "devices_location_id_locations_id_fk" FOREIGN KEY ("location_id") REFERENCES "public"."locations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "installation_log" ADD CONSTRAINT "installation_log_instance_id_component_instances_id_fk" FOREIGN KEY ("instance_id") REFERENCES "public"."component_instances"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "installation_log" ADD CONSTRAINT "installation_log_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "locations" ADD CONSTRAINT "locations_parent_id_locations_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."locations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "parts" ADD CONSTRAINT "parts_location_id_locations_id_fk" FOREIGN KEY ("location_id") REFERENCES "public"."locations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "template_items" ADD CONSTRAINT "template_items_template_id_checklist_templates_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."checklist_templates"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "todos" ADD CONSTRAINT "todos_device_id_devices_id_fk" FOREIGN KEY ("device_id") REFERENCES "public"."devices"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "wiki_page_tags" ADD CONSTRAINT "wiki_page_tags_page_id_wiki_pages_id_fk" FOREIGN KEY ("page_id") REFERENCES "public"."wiki_pages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "wiki_page_tags" ADD CONSTRAINT "wiki_page_tags_tag_id_wiki_tags_id_fk" FOREIGN KEY ("tag_id") REFERENCES "public"."wiki_tags"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "wiki_pages" ADD CONSTRAINT "wiki_pages_category_id_wiki_categories_id_fk" FOREIGN KEY ("category_id") REFERENCES "public"."wiki_categories"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "checklist_items_checklist_idx" ON "checklist_items" USING btree ("checklist_id");--> statement-breakpoint
+CREATE INDEX "component_documents_component_idx" ON "component_documents" USING btree ("component_id");--> statement-breakpoint
+CREATE INDEX "component_images_component_idx" ON "component_images" USING btree ("component_id");--> statement-breakpoint
+CREATE INDEX "instances_component_idx" ON "component_instances" USING btree ("component_id");--> statement-breakpoint
+CREATE INDEX "instances_device_idx" ON "component_instances" USING btree ("current_device_id");--> statement-breakpoint
+CREATE INDEX "instances_location_idx" ON "component_instances" USING btree ("location_id");--> statement-breakpoint
+CREATE INDEX "components_type_idx" ON "components" USING btree ("component_type");--> statement-breakpoint
+CREATE INDEX "device_checklists_device_idx" ON "device_checklists" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "device_documents_device_idx" ON "device_documents" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "device_images_device_idx" ON "device_images" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "device_log_device_idx" ON "device_log" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "device_log_date_idx" ON "device_log" USING btree ("performed_at");--> statement-breakpoint
+CREATE INDEX "device_tags_device_idx" ON "device_tags" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "device_tags_written_at_idx" ON "device_tags" USING btree ("written_at");--> statement-breakpoint
+CREATE INDEX "devices_category_idx" ON "devices" USING btree ("category");--> statement-breakpoint
+CREATE INDEX "devices_condition_idx" ON "devices" USING btree ("condition");--> statement-breakpoint
+CREATE INDEX "devices_location_idx" ON "devices" USING btree ("location_id");--> statement-breakpoint
+CREATE INDEX "install_log_instance_idx" ON "installation_log" USING btree ("instance_id");--> statement-breakpoint
+CREATE INDEX "install_log_device_idx" ON "installation_log" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "install_log_date_idx" ON "installation_log" USING btree ("performed_at");--> statement-breakpoint
+CREATE INDEX "parts_category_idx" ON "parts" USING btree ("category");--> statement-breakpoint
+CREATE INDEX "parts_location_idx" ON "parts" USING btree ("location_id");--> statement-breakpoint
+CREATE INDEX "template_items_template_idx" ON "template_items" USING btree ("template_id");--> statement-breakpoint
+CREATE INDEX "todos_status_idx" ON "todos" USING btree ("status");--> statement-breakpoint
+CREATE INDEX "todos_priority_idx" ON "todos" USING btree ("priority");--> statement-breakpoint
+CREATE INDEX "todos_device_idx" ON "todos" USING btree ("device_id");--> statement-breakpoint
+CREATE INDEX "wiki_page_tags_page_idx" ON "wiki_page_tags" USING btree ("page_id");--> statement-breakpoint
+CREATE INDEX "wiki_page_tags_tag_idx" ON "wiki_page_tags" USING btree ("tag_id");--> statement-breakpoint
+CREATE INDEX "wiki_pages_category_idx" ON "wiki_pages" USING btree ("category_id");--> statement-breakpoint
+CREATE INDEX "wiki_pages_slug_idx" ON "wiki_pages" USING btree ("slug");
\ No newline at end of file
diff --git a/drizzle/migrations/meta/0000_snapshot.json b/drizzle/migrations/meta/0000_snapshot.json
new file mode 100644
index 0000000..1aed8c3
--- /dev/null
+++ b/drizzle/migrations/meta/0000_snapshot.json
@@ -0,0 +1,2403 @@
+{
+ "id": "cebee925-8ad2-4acf-8d4d-7dfe0e514aa6",
+ "prevId": "00000000-0000-0000-0000-000000000000",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.checklist_items": {
+ "name": "checklist_items",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "checklist_id": {
+ "name": "checklist_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "text": {
+ "name": "text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "item_type": {
+ "name": "item_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'checkbox'"
+ },
+ "unit": {
+ "name": "unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "checked": {
+ "name": "checked",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sort_order": {
+ "name": "sort_order",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "checklist_items_checklist_idx": {
+ "name": "checklist_items_checklist_idx",
+ "columns": [
+ {
+ "expression": "checklist_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "checklist_items_checklist_id_device_checklists_id_fk": {
+ "name": "checklist_items_checklist_id_device_checklists_id_fk",
+ "tableFrom": "checklist_items",
+ "tableTo": "device_checklists",
+ "columnsFrom": [
+ "checklist_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.checklist_templates": {
+ "name": "checklist_templates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.component_documents": {
+ "name": "component_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "component_id": {
+ "name": "component_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_path": {
+ "name": "file_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "original_filename": {
+ "name": "original_filename",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_type": {
+ "name": "file_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "uploaded_at": {
+ "name": "uploaded_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "component_documents_component_idx": {
+ "name": "component_documents_component_idx",
+ "columns": [
+ {
+ "expression": "component_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "component_documents_component_id_components_id_fk": {
+ "name": "component_documents_component_id_components_id_fk",
+ "tableFrom": "component_documents",
+ "tableTo": "components",
+ "columnsFrom": [
+ "component_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.component_images": {
+ "name": "component_images",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "component_id": {
+ "name": "component_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_path": {
+ "name": "file_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "thumbnail_path": {
+ "name": "thumbnail_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "caption": {
+ "name": "caption",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "uploaded_at": {
+ "name": "uploaded_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "component_images_component_idx": {
+ "name": "component_images_component_idx",
+ "columns": [
+ {
+ "expression": "component_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "component_images_component_id_components_id_fk": {
+ "name": "component_images_component_id_components_id_fk",
+ "tableFrom": "component_images",
+ "tableTo": "components",
+ "columnsFrom": [
+ "component_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.component_instances": {
+ "name": "component_instances",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "component_id": {
+ "name": "component_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "instance_number": {
+ "name": "instance_number",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 1
+ },
+ "serial_number": {
+ "name": "serial_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "condition": {
+ "name": "condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'Working'"
+ },
+ "firmware_version": {
+ "name": "firmware_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "current_device_id": {
+ "name": "current_device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "location_id": {
+ "name": "location_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "instances_component_idx": {
+ "name": "instances_component_idx",
+ "columns": [
+ {
+ "expression": "component_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "instances_device_idx": {
+ "name": "instances_device_idx",
+ "columns": [
+ {
+ "expression": "current_device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "instances_location_idx": {
+ "name": "instances_location_idx",
+ "columns": [
+ {
+ "expression": "location_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "component_instances_component_id_components_id_fk": {
+ "name": "component_instances_component_id_components_id_fk",
+ "tableFrom": "component_instances",
+ "tableTo": "components",
+ "columnsFrom": [
+ "component_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "component_instances_current_device_id_devices_id_fk": {
+ "name": "component_instances_current_device_id_devices_id_fk",
+ "tableFrom": "component_instances",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "current_device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "component_instances_location_id_locations_id_fk": {
+ "name": "component_instances_location_id_locations_id_fk",
+ "tableFrom": "component_instances",
+ "tableTo": "locations",
+ "columnsFrom": [
+ "location_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "instances_condition_check": {
+ "name": "instances_condition_check",
+ "value": "\"component_instances\".\"condition\" IN ('Working', 'Faulty', 'Unknown', 'Refurbished')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.components": {
+ "name": "components",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "component_type": {
+ "name": "component_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "brand": {
+ "name": "brand",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "part_number": {
+ "name": "part_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "specs": {
+ "name": "specs",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "default_condition": {
+ "name": "default_condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'Working'"
+ },
+ "default_firmware_version": {
+ "name": "default_firmware_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "default_location_id": {
+ "name": "default_location_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "disabled": {
+ "name": "disabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "components_type_idx": {
+ "name": "components_type_idx",
+ "columns": [
+ {
+ "expression": "component_type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "components_default_location_id_locations_id_fk": {
+ "name": "components_default_location_id_locations_id_fk",
+ "tableFrom": "components",
+ "tableTo": "locations",
+ "columnsFrom": [
+ "default_location_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.computer_details": {
+ "name": "computer_details",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "os_version": {
+ "name": "os_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "firmware_version": {
+ "name": "firmware_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "installed_software": {
+ "name": "installed_software",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "computer_details_device_id_devices_id_fk": {
+ "name": "computer_details_device_id_devices_id_fk",
+ "tableFrom": "computer_details",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "computer_details_device_id_unique": {
+ "name": "computer_details_device_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "device_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.device_checklists": {
+ "name": "device_checklists",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "device_checklists_device_idx": {
+ "name": "device_checklists_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "device_checklists_device_id_devices_id_fk": {
+ "name": "device_checklists_device_id_devices_id_fk",
+ "tableFrom": "device_checklists",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.device_documents": {
+ "name": "device_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_path": {
+ "name": "file_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "original_filename": {
+ "name": "original_filename",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_type": {
+ "name": "file_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "uploaded_at": {
+ "name": "uploaded_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "device_documents_device_idx": {
+ "name": "device_documents_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "device_documents_device_id_devices_id_fk": {
+ "name": "device_documents_device_id_devices_id_fk",
+ "tableFrom": "device_documents",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.device_images": {
+ "name": "device_images",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "file_path": {
+ "name": "file_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "thumbnail_path": {
+ "name": "thumbnail_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "caption": {
+ "name": "caption",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sort_order": {
+ "name": "sort_order",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "default": 0
+ },
+ "uploaded_at": {
+ "name": "uploaded_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "device_images_device_idx": {
+ "name": "device_images_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "device_images_device_id_devices_id_fk": {
+ "name": "device_images_device_id_devices_id_fk",
+ "tableFrom": "device_images",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.device_log": {
+ "name": "device_log",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "condition_after": {
+ "name": "condition_after",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "performed_by": {
+ "name": "performed_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "performed_at": {
+ "name": "performed_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "device_log_device_idx": {
+ "name": "device_log_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "device_log_date_idx": {
+ "name": "device_log_date_idx",
+ "columns": [
+ {
+ "expression": "performed_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "device_log_device_id_devices_id_fk": {
+ "name": "device_log_device_id_devices_id_fk",
+ "tableFrom": "device_log",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "device_log_type_check": {
+ "name": "device_log_type_check",
+ "value": "\"device_log\".\"type\" IN ('repair', 'inspection', 'cleaning', 'modification', 'diagnostic', 'recap', 'other')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.device_tags": {
+ "name": "device_tags",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tag_uid": {
+ "name": "tag_uid",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payload_url": {
+ "name": "payload_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "written_by": {
+ "name": "written_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "written_at": {
+ "name": "written_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "device_tags_device_idx": {
+ "name": "device_tags_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "device_tags_written_at_idx": {
+ "name": "device_tags_written_at_idx",
+ "columns": [
+ {
+ "expression": "written_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "device_tags_device_id_devices_id_fk": {
+ "name": "device_tags_device_id_devices_id_fk",
+ "tableFrom": "device_tags",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.devices": {
+ "name": "devices",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "brand": {
+ "name": "brand",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "serial_number": {
+ "name": "serial_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "year": {
+ "name": "year",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "condition": {
+ "name": "condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'Waiting to be Tested'"
+ },
+ "voltage": {
+ "name": "voltage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "frequency": {
+ "name": "frequency",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "origin": {
+ "name": "origin",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "fault_description": {
+ "name": "fault_description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "repair_notes": {
+ "name": "repair_notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "location_id": {
+ "name": "location_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "initial_condition": {
+ "name": "initial_condition",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "general_notes": {
+ "name": "general_notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "disabled": {
+ "name": "disabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "devices_category_idx": {
+ "name": "devices_category_idx",
+ "columns": [
+ {
+ "expression": "category",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "devices_condition_idx": {
+ "name": "devices_condition_idx",
+ "columns": [
+ {
+ "expression": "condition",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "devices_location_idx": {
+ "name": "devices_location_idx",
+ "columns": [
+ {
+ "expression": "location_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "devices_location_id_locations_id_fk": {
+ "name": "devices_location_id_locations_id_fk",
+ "tableFrom": "devices",
+ "tableTo": "locations",
+ "columnsFrom": [
+ "location_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "devices_category_check": {
+ "name": "devices_category_check",
+ "value": "\"devices\".\"category\" IN ('Computer', 'Audio Equipment', 'Peripheral', 'Other')"
+ },
+ "devices_condition_check": {
+ "name": "devices_condition_check",
+ "value": "\"devices\".\"condition\" IN ('Working', 'In Repair', 'Waiting for Repair', 'Waiting to be Tested', 'Unrepairable')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.feature_requests": {
+ "name": "feature_requests",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'open'"
+ },
+ "votes": {
+ "name": "votes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "created_by": {
+ "name": "created_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.installation_log": {
+ "name": "installation_log",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "instance_id": {
+ "name": "instance_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "action": {
+ "name": "action",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "performed_by": {
+ "name": "performed_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "performed_at": {
+ "name": "performed_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "install_log_instance_idx": {
+ "name": "install_log_instance_idx",
+ "columns": [
+ {
+ "expression": "instance_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "install_log_device_idx": {
+ "name": "install_log_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "install_log_date_idx": {
+ "name": "install_log_date_idx",
+ "columns": [
+ {
+ "expression": "performed_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "installation_log_instance_id_component_instances_id_fk": {
+ "name": "installation_log_instance_id_component_instances_id_fk",
+ "tableFrom": "installation_log",
+ "tableTo": "component_instances",
+ "columnsFrom": [
+ "instance_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "installation_log_device_id_devices_id_fk": {
+ "name": "installation_log_device_id_devices_id_fk",
+ "tableFrom": "installation_log",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "install_log_action_check": {
+ "name": "install_log_action_check",
+ "value": "\"installation_log\".\"action\" IN ('installed', 'removed', 'swapped')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.locations": {
+ "name": "locations",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "parent_id": {
+ "name": "parent_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "locations_parent_id_locations_id_fk": {
+ "name": "locations_parent_id_locations_id_fk",
+ "tableFrom": "locations",
+ "tableTo": "locations",
+ "columnsFrom": [
+ "parent_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.parts": {
+ "name": "parts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "mpn": {
+ "name": "mpn",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "voltage": {
+ "name": "voltage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tolerance": {
+ "name": "tolerance",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "power": {
+ "name": "power",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "mounting": {
+ "name": "mounting",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "package": {
+ "name": "package",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "unit": {
+ "name": "unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pcs'"
+ },
+ "location_id": {
+ "name": "location_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "parts_category_idx": {
+ "name": "parts_category_idx",
+ "columns": [
+ {
+ "expression": "category",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "parts_location_idx": {
+ "name": "parts_location_idx",
+ "columns": [
+ {
+ "expression": "location_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "parts_location_id_locations_id_fk": {
+ "name": "parts_location_id_locations_id_fk",
+ "tableFrom": "parts",
+ "tableTo": "locations",
+ "columnsFrom": [
+ "location_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.sessions": {
+ "name": "sessions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "sessions_user_id_users_id_fk": {
+ "name": "sessions_user_id_users_id_fk",
+ "tableFrom": "sessions",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.template_items": {
+ "name": "template_items",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "text": {
+ "name": "text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "item_type": {
+ "name": "item_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'checkbox'"
+ },
+ "unit": {
+ "name": "unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sort_order": {
+ "name": "sort_order",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "template_items_template_idx": {
+ "name": "template_items_template_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "template_items_template_id_checklist_templates_id_fk": {
+ "name": "template_items_template_id_checklist_templates_id_fk",
+ "tableFrom": "template_items",
+ "tableTo": "checklist_templates",
+ "columnsFrom": [
+ "template_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.todos": {
+ "name": "todos",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'todo'"
+ },
+ "priority": {
+ "name": "priority",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 2
+ },
+ "device_id": {
+ "name": "device_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "due_date": {
+ "name": "due_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "todos_status_idx": {
+ "name": "todos_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "todos_priority_idx": {
+ "name": "todos_priority_idx",
+ "columns": [
+ {
+ "expression": "priority",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "todos_device_idx": {
+ "name": "todos_device_idx",
+ "columns": [
+ {
+ "expression": "device_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "todos_device_id_devices_id_fk": {
+ "name": "todos_device_id_devices_id_fk",
+ "tableFrom": "todos",
+ "tableTo": "devices",
+ "columnsFrom": [
+ "device_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "todos_status_check": {
+ "name": "todos_status_check",
+ "value": "\"todos\".\"status\" IN ('todo', 'in_progress', 'done')"
+ },
+ "todos_priority_check": {
+ "name": "todos_priority_check",
+ "value": "\"todos\".\"priority\" IN (0, 1, 2, 3)"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.users": {
+ "name": "users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "display_name": {
+ "name": "display_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password_hash": {
+ "name": "password_hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.wiki_categories": {
+ "name": "wiki_categories",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sort_order": {
+ "name": "sort_order",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "wiki_categories_slug_unique": {
+ "name": "wiki_categories_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.wiki_page_tags": {
+ "name": "wiki_page_tags",
+ "schema": "",
+ "columns": {
+ "page_id": {
+ "name": "page_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tag_id": {
+ "name": "tag_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "wiki_page_tags_page_idx": {
+ "name": "wiki_page_tags_page_idx",
+ "columns": [
+ {
+ "expression": "page_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "wiki_page_tags_tag_idx": {
+ "name": "wiki_page_tags_tag_idx",
+ "columns": [
+ {
+ "expression": "tag_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "wiki_page_tags_page_id_wiki_pages_id_fk": {
+ "name": "wiki_page_tags_page_id_wiki_pages_id_fk",
+ "tableFrom": "wiki_page_tags",
+ "tableTo": "wiki_pages",
+ "columnsFrom": [
+ "page_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "wiki_page_tags_tag_id_wiki_tags_id_fk": {
+ "name": "wiki_page_tags_tag_id_wiki_tags_id_fk",
+ "tableFrom": "wiki_page_tags",
+ "tableTo": "wiki_tags",
+ "columnsFrom": [
+ "tag_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.wiki_pages": {
+ "name": "wiki_pages",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "category_id": {
+ "name": "category_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_by": {
+ "name": "created_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_by": {
+ "name": "updated_by",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "wiki_pages_category_idx": {
+ "name": "wiki_pages_category_idx",
+ "columns": [
+ {
+ "expression": "category_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "wiki_pages_slug_idx": {
+ "name": "wiki_pages_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "wiki_pages_category_id_wiki_categories_id_fk": {
+ "name": "wiki_pages_category_id_wiki_categories_id_fk",
+ "tableFrom": "wiki_pages",
+ "tableTo": "wiki_categories",
+ "columnsFrom": [
+ "category_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "wiki_pages_slug_unique": {
+ "name": "wiki_pages_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.wiki_tags": {
+ "name": "wiki_tags",
+ "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": {
+ "wiki_tags_name_unique": {
+ "name": "wiki_tags_name_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "name"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/migrations/meta/_journal.json b/drizzle/migrations/meta/_journal.json
new file mode 100644
index 0000000..7af1473
--- /dev/null
+++ b/drizzle/migrations/meta/_journal.json
@@ -0,0 +1,13 @@
+{
+ "version": "7",
+ "dialect": "postgresql",
+ "entries": [
+ {
+ "idx": 0,
+ "version": "7",
+ "when": 1782725202288,
+ "tag": "0000_clear_sister_grimm",
+ "breakpoints": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte
index 3e37615..6133f39 100644
--- a/src/lib/components/layout/Sidebar.svelte
+++ b/src/lib/components/layout/Sidebar.svelte
@@ -4,7 +4,7 @@
interface Props {
open: boolean;
onToggle: () => void;
- counts: { devices: number; components: number; needsRepair: number; openTodos: number };
+ counts: { devices: number; components: number; parts: number; needsRepair: number; openTodos: number };
}
let { open, onToggle, counts }: Props = $props();
@@ -27,6 +27,12 @@
badge: counts.components,
icon: 'M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z'
},
+ {
+ href: '/parts',
+ label: 'Parts',
+ badge: counts.parts || undefined,
+ icon: 'M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4'
+ },
{
href: '/installations',
label: 'Install Log',
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index f500f16..1b7ef39 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -63,6 +63,23 @@ export const TODO_PRIORITIES = [
{ value: 3, label: 'Low', color: 'gray' }
] as const;
+export const PART_CATEGORIES = [
+ 'Capacitor',
+ 'Resistor',
+ 'Transistor',
+ 'IC / Chip',
+ 'Diode',
+ 'LED',
+ 'Button / Switch',
+ 'Connector',
+ 'Fuse',
+ 'Inductor',
+ 'Crystal / Oscillator',
+ 'Other'
+] as const;
+
+export type PartCategory = (typeof PART_CATEGORIES)[number];
+
export const VOLTAGE_OPTIONS = [
'100-120V AC',
'220-240V AC',
diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts
index 4606bc9..db08b5f 100644
--- a/src/lib/server/db/schema.ts
+++ b/src/lib/server/db/schema.ts
@@ -373,6 +373,34 @@ export const featureRequests = pgTable('feature_requests', {
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});
+// ─── Parts (consumable stock, no per-device tracking) ───────────
+
+export const parts = pgTable(
+ 'parts',
+ {
+ id: uuid('id').defaultRandom().primaryKey(),
+ name: text('name'),
+ category: text('category').notNull(),
+ mpn: text('mpn'),
+ value: text('value'),
+ voltage: text('voltage'),
+ tolerance: text('tolerance'),
+ power: text('power'),
+ mounting: text('mounting'),
+ package: text('package'),
+ quantity: integer('quantity').notNull().default(0),
+ unit: text('unit').notNull().default('pcs'),
+ locationId: uuid('location_id').references(() => locations.id),
+ notes: text('notes'),
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
+ },
+ (table) => [
+ index('parts_category_idx').on(table.category),
+ index('parts_location_idx').on(table.locationId)
+ ]
+);
+
// ─── Wiki ───────────────────────────────────────────────────────────
export const wikiCategories = pgTable('wiki_categories', {
diff --git a/src/routes/(app)/+layout.server.ts b/src/routes/(app)/+layout.server.ts
index 0d50e90..55a2634 100644
--- a/src/routes/(app)/+layout.server.ts
+++ b/src/routes/(app)/+layout.server.ts
@@ -1,7 +1,7 @@
import type { LayoutServerLoad } from './$types';
import { redirect } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
-import { devices, components, componentInstances, todos } from '$lib/server/db/schema.js';
+import { devices, components, componentInstances, todos, parts } from '$lib/server/db/schema.js';
import { count, eq, or, and, ne } from 'drizzle-orm';
export const load: LayoutServerLoad = async ({ locals }) => {
@@ -25,13 +25,16 @@ export const load: LayoutServerLoad = async ({ locals }) => {
.from(todos)
.where(ne(todos.status, 'done'));
+ const [partsCount] = await db.select({ value: count() }).from(parts);
+
return {
user: locals.user,
counts: {
devices: deviceCount?.value ?? 0,
components: componentCount?.value ?? 0,
needsRepair: repairCount?.value ?? 0,
- openTodos: openTodos?.value ?? 0
+ openTodos: openTodos?.value ?? 0,
+ parts: partsCount?.value ?? 0
}
};
};
diff --git a/src/routes/(app)/parts/+page.server.ts b/src/routes/(app)/parts/+page.server.ts
new file mode 100644
index 0000000..c0121f3
--- /dev/null
+++ b/src/routes/(app)/parts/+page.server.ts
@@ -0,0 +1,61 @@
+import type { PageServerLoad } from './$types';
+import { db } from '$lib/server/db/index.js';
+import { parts, locations } from '$lib/server/db/schema.js';
+import { eq, ilike, or, and, count } from 'drizzle-orm';
+
+export const load: PageServerLoad = async ({ url }) => {
+ const category = url.searchParams.get('category');
+ const mounting = url.searchParams.get('mounting');
+ const search = url.searchParams.get('q');
+ const page = Math.max(1, Number(url.searchParams.get('page') ?? 1));
+ const pageSize = 48;
+
+ const conditions = [];
+ if (category) conditions.push(eq(parts.category, category));
+ if (mounting) conditions.push(eq(parts.mounting, mounting));
+ if (search) {
+ conditions.push(
+ or(
+ ilike(parts.name, `%${search}%`),
+ ilike(parts.mpn, `%${search}%`),
+ ilike(parts.value, `%${search}%`),
+ ilike(parts.package, `%${search}%`)
+ )!
+ );
+ }
+
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
+
+ const [totalResult] = await db.select({ value: count() }).from(parts).where(where);
+
+ const partList = await db
+ .select({
+ id: parts.id,
+ name: parts.name,
+ category: parts.category,
+ mpn: parts.mpn,
+ value: parts.value,
+ voltage: parts.voltage,
+ tolerance: parts.tolerance,
+ power: parts.power,
+ mounting: parts.mounting,
+ package: parts.package,
+ quantity: parts.quantity,
+ unit: parts.unit,
+ locationId: parts.locationId
+ })
+ .from(parts)
+ .leftJoin(locations, eq(parts.locationId, locations.id))
+ .where(where)
+ .orderBy(parts.category, parts.value)
+ .limit(pageSize)
+ .offset((page - 1) * pageSize);
+
+ return {
+ parts: partList,
+ total: totalResult?.value ?? 0,
+ page,
+ pageSize,
+ filters: { category, mounting, search }
+ };
+};
diff --git a/src/routes/(app)/parts/+page.svelte b/src/routes/(app)/parts/+page.svelte
new file mode 100644
index 0000000..ac9e9dd
--- /dev/null
+++ b/src/routes/(app)/parts/+page.svelte
@@ -0,0 +1,150 @@
+
+
+
{data.total} part{data.total !== 1 ? 's' : ''}
+ + {#if data.parts.length === 0} +No parts found.
+ Add your first part +| Category | +Value / MPN | +Package | +Specs | +Stock | +
|---|---|---|---|---|
| + + {part.category} + + | ++ + {#if part.value} + {part.value} + {/if} + {#if part.name} + {part.name} + {/if} + {#if part.mpn} + {part.mpn} + {/if} + + | ++ + {#if part.mounting} + {part.mounting} + {/if} + {#if part.package} + {part.package} + {/if} + + | ++ + {[part.voltage, part.tolerance, part.power].filter(Boolean).join(' · ')} + + | ++ + {part.quantity} + {part.unit} + + | +
{p.category}
+{p.name}
+ {/if} +📍 {p.locationName}
+ {/if} +{p.notes}
+