feat(db): add phase1 device role, links, and commands schema
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { pgTable, timestamp, uuid, varchar, text, boolean } from 'drizzle-orm/pg-core';
|
||||
import { pgTable, timestamp, uuid, varchar, text, boolean, integer, jsonb, unique } from 'drizzle-orm/pg-core';
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
@@ -15,11 +15,49 @@ export const devices = pgTable('devices', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
userId: uuid('user_id').notNull().references(() => users.id),
|
||||
name: varchar('name', { length: 255 }),
|
||||
role: varchar('role', { length: 32 }).default('client').notNull(),
|
||||
platform: varchar('platform', { length: 32 }),
|
||||
appVersion: varchar('app_version', { length: 64 }),
|
||||
pushToken: text('push_token'),
|
||||
status: varchar('status', { length: 32 }).default('offline').notNull(),
|
||||
isCamera: boolean('is_camera').default(false).notNull(),
|
||||
lastSeenAt: timestamp('last_seen_at', { withTimezone: true }),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export const deviceLinks = pgTable(
|
||||
'device_links',
|
||||
{
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
|
||||
cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
|
||||
clientDeviceId: uuid('client_device_id').notNull().references(() => devices.id),
|
||||
status: varchar('status', { length: 32 }).default('active').notNull(),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
uniqueDevicePair: unique('device_links_camera_client_unique').on(table.cameraDeviceId, table.clientDeviceId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const deviceCommands = pgTable('device_commands', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
|
||||
sourceDeviceId: uuid('source_device_id').notNull().references(() => devices.id),
|
||||
targetDeviceId: uuid('target_device_id').notNull().references(() => devices.id),
|
||||
commandType: varchar('command_type', { length: 64 }).notNull(),
|
||||
payload: jsonb('payload').$type<Record<string, unknown> | null>().default(null),
|
||||
status: varchar('status', { length: 32 }).default('queued').notNull(),
|
||||
retryCount: integer('retry_count').default(0).notNull(),
|
||||
lastDispatchedAt: timestamp('last_dispatched_at', { withTimezone: true }),
|
||||
acknowledgedAt: timestamp('acknowledged_at', { withTimezone: true }),
|
||||
error: text('error'),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export const events = pgTable('events', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
userId: uuid('user_id').notNull().references(() => users.id),
|
||||
@@ -99,6 +137,8 @@ export const verifications = pgTable('verification', {
|
||||
export const schema = {
|
||||
users,
|
||||
devices,
|
||||
deviceLinks,
|
||||
deviceCommands,
|
||||
events,
|
||||
videos,
|
||||
notifications,
|
||||
|
||||
@@ -405,8 +405,7 @@ registry.registerPath({
|
||||
|
||||
export function buildOpenApiDocument() {
|
||||
const generator = new OpenApiGeneratorV3(registry.definitions);
|
||||
|
||||
return generator.generateDocument({
|
||||
const document = generator.generateDocument({
|
||||
openapi: '3.0.3',
|
||||
info: {
|
||||
title: 'Backend API',
|
||||
@@ -419,19 +418,23 @@ export function buildOpenApiDocument() {
|
||||
{ name: 'Videos', description: 'Authenticated video object operations' },
|
||||
{ name: 'Admin', description: 'Basic-auth protected admin operations' },
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
cookieAuth: {
|
||||
type: 'apiKey',
|
||||
in: 'cookie',
|
||||
name: 'better-auth.session_token',
|
||||
description: 'Better Auth session cookie',
|
||||
},
|
||||
basicAuth: {
|
||||
type: 'http',
|
||||
scheme: 'basic',
|
||||
},
|
||||
});
|
||||
|
||||
document.components = {
|
||||
...(document.components ?? {}),
|
||||
securitySchemes: {
|
||||
cookieAuth: {
|
||||
type: 'apiKey',
|
||||
in: 'cookie',
|
||||
name: 'better-auth.session_token',
|
||||
description: 'Better Auth session cookie',
|
||||
},
|
||||
basicAuth: {
|
||||
type: 'http',
|
||||
scheme: 'basic',
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
40
Backend/drizzle/0006_steady_control_plane.sql
Normal file
40
Backend/drizzle/0006_steady_control_plane.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
ALTER TABLE "devices" ADD COLUMN "role" varchar(32) DEFAULT 'client' NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "platform" varchar(32);--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "app_version" varchar(64);--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "push_token" text;--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "status" varchar(32) DEFAULT 'offline' NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "devices" ADD COLUMN "updated_at" timestamp with time zone DEFAULT now() NOT NULL;--> statement-breakpoint
|
||||
UPDATE "devices" SET "role" = CASE WHEN "is_camera" THEN 'camera' ELSE 'client' END;--> statement-breakpoint
|
||||
CREATE TABLE "device_links" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"owner_user_id" uuid NOT NULL,
|
||||
"camera_device_id" uuid NOT NULL,
|
||||
"client_device_id" uuid NOT NULL,
|
||||
"status" varchar(32) DEFAULT 'active' NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "device_links_camera_client_unique" UNIQUE("camera_device_id","client_device_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "device_commands" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"owner_user_id" uuid NOT NULL,
|
||||
"source_device_id" uuid NOT NULL,
|
||||
"target_device_id" uuid NOT NULL,
|
||||
"command_type" varchar(64) NOT NULL,
|
||||
"payload" jsonb DEFAULT 'null'::jsonb,
|
||||
"status" varchar(32) DEFAULT 'queued' NOT NULL,
|
||||
"retry_count" integer DEFAULT 0 NOT NULL,
|
||||
"last_dispatched_at" timestamp with time zone,
|
||||
"acknowledged_at" timestamp with time zone,
|
||||
"error" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "device_links" ADD CONSTRAINT "device_links_owner_user_id_users_id_fk" FOREIGN KEY ("owner_user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "device_links" ADD CONSTRAINT "device_links_camera_device_id_devices_id_fk" FOREIGN KEY ("camera_device_id") REFERENCES "public"."devices"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "device_links" ADD CONSTRAINT "device_links_client_device_id_devices_id_fk" FOREIGN KEY ("client_device_id") REFERENCES "public"."devices"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "device_commands" ADD CONSTRAINT "device_commands_owner_user_id_users_id_fk" FOREIGN KEY ("owner_user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "device_commands" ADD CONSTRAINT "device_commands_source_device_id_devices_id_fk" FOREIGN KEY ("source_device_id") REFERENCES "public"."devices"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "device_commands" ADD CONSTRAINT "device_commands_target_device_id_devices_id_fk" FOREIGN KEY ("target_device_id") REFERENCES "public"."devices"("id") ON DELETE no action ON UPDATE no action;
|
||||
@@ -43,6 +43,13 @@
|
||||
"when": 1770412956419,
|
||||
"tag": "0005_sudden_corsair",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1770413956419,
|
||||
"tag": "0006_steady_control_plane",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user