Spaces:
Sleeping
Sleeping
File size: 3,038 Bytes
839aef2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | import { randomUUID } from 'crypto';
import { DataTypes } from 'sequelize';
import { sequelize } from '../db.js';
import { enumField, CommandType, CommandStatus } from '../utils/enums.js';
/**
* Build a JSONB-compatible attribute. The old Python backend's JSONB type stored
* JSON as TEXT on SQLite and native JSON/JSONB on Postgres/MySQL. We mirror that:
* always (de)serialize through getters/setters so a TEXT column round-trips, and
* native JSON columns also work (object passes through).
*/
function jsonbField(field, defaultValue) {
return {
type: DataTypes.TEXT,
field,
defaultValue: defaultValue === undefined ? undefined : JSON.stringify(defaultValue),
get() {
const raw = this.getDataValue(field);
if (raw === null || raw === undefined) return raw;
if (typeof raw === 'object') return raw; // native JSON column
try {
return JSON.parse(raw);
} catch {
return raw;
}
},
set(val) {
if (val === null || val === undefined) {
this.setDataValue(field, val);
} else if (typeof val === 'string') {
this.setDataValue(field, val);
} else {
this.setDataValue(field, JSON.stringify(val));
}
},
};
}
export const DeviceCommand = sequelize.define(
'DeviceCommand',
{
id: { type: DataTypes.STRING(36), primaryKey: true, defaultValue: randomUUID },
device_id: { type: DataTypes.STRING(36), allowNull: false },
command_type: enumField({ field: 'command_type', allowNull: false }),
payload: jsonbField('payload', {}),
status: enumField({ field: 'status', defaultValue: 'pending' }),
retry_count: { type: DataTypes.STRING(10), defaultValue: '0' },
max_retries: { type: DataTypes.STRING(10), defaultValue: '3' },
fcm_message_id: { type: DataTypes.STRING(255) },
created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
sent_at: { type: DataTypes.DATE },
delivered_at: { type: DataTypes.DATE },
executed_at: { type: DataTypes.DATE },
error_message: { type: DataTypes.TEXT },
issued_by: { type: DataTypes.STRING(36) },
reason: { type: DataTypes.TEXT },
},
{ tableName: 'device_commands', timestamps: false },
);
export const AuditLog = sequelize.define(
'AuditLog',
{
id: { type: DataTypes.STRING(36), primaryKey: true, defaultValue: randomUUID },
entity_type: { type: DataTypes.STRING(50), allowNull: false },
entity_id: { type: DataTypes.STRING(36) },
action: { type: DataTypes.STRING(100), allowNull: false },
old_value: jsonbField('old_value'),
new_value: jsonbField('new_value'),
performed_by: { type: DataTypes.STRING(36) },
ip_address: { type: DataTypes.STRING(50) },
user_agent: { type: DataTypes.TEXT },
created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
},
{ tableName: 'audit_logs', timestamps: false },
);
export { CommandType, CommandStatus };
export default DeviceCommand;
|