/** * @type {import('node-pg-migrate').ColumnDefinitions | undefined} */ exports.shorthands = undefined; /** * @param pgm {import('node-pg-migrate').MigrationBuilder} * @param run {() => void | undefined} * @returns {Promise | void} */ exports.up = (pgm) => { // Create validated_events table for storing processed/validated event data pgm.createTable('validated_events', { id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()'), }, raw_event_id: { type: 'uuid', notNull: true, unique: true, references: 'raw_events(id)', onDelete: 'CASCADE', comment: 'Reference to the original raw event', }, device_id: { type: 'uuid', notNull: true, references: 'devices(id)', onDelete: 'CASCADE', comment: 'The device that uploaded this event', }, user_profile_id: { type: 'uuid', notNull: true, references: 'user_profiles(id)', onDelete: 'CASCADE', comment: 'Owner of the device', }, media_url: { type: 'text', notNull: true, comment: 'URL to access the media file (could be S3 signed URL or CloudFront URL)', }, file_size: { type: 'bigint', comment: 'File size in bytes', }, file_type: { type: 'varchar(100)', comment: 'MIME type of the file', }, original_filename: { type: 'varchar(255)', comment: 'Original filename from the client', }, event_type: { type: 'varchar(50)', notNull: true, comment: 'Type of event (motion, alert, meteor, etc.)', }, event_timestamp: { type: 'timestamp with time zone', notNull: true, comment: 'When the event occurred on the device', }, metadata: { type: 'jsonb', comment: 'Additional event metadata from the device', }, validation_score: { type: 'decimal(5,4)', comment: 'Validation confidence score (0.0000 to 1.0000)', }, validation_details: { type: 'jsonb', comment: 'Details from the validation process', }, is_valid: { type: 'boolean', notNull: true, default: true, comment: 'Whether the event passed validation', }, validation_algorithm: { type: 'varchar(50)', comment: 'Algorithm used for validation', }, created_at: { type: 'timestamp with time zone', notNull: true, default: pgm.func('now()'), }, updated_at: { type: 'timestamp with time zone', notNull: true, default: pgm.func('now()'), }, }); // Create indexes for better performance pgm.createIndex('validated_events', 'raw_event_id'); pgm.createIndex('validated_events', 'device_id'); pgm.createIndex('validated_events', 'user_profile_id'); pgm.createIndex('validated_events', 'event_type'); pgm.createIndex('validated_events', 'event_timestamp'); pgm.createIndex('validated_events', 'is_valid'); pgm.createIndex('validated_events', ['device_id', 'event_timestamp']); pgm.createIndex('validated_events', ['user_profile_id', 'created_at']); pgm.createIndex('validated_events', ['event_type', 'is_valid']); }; /** * @param pgm {import('node-pg-migrate').MigrationBuilder} * @param run {() => void | undefined} * @returns {Promise | void} */ exports.down = (pgm) => { pgm.dropTable('validated_events'); };