import { datetime, index, int, mysqlTable, tinyint, varchar } from 'drizzle-orm/mysql-core' import { drizzle } from 'drizzle-orm/mysql2' import { reset } from 'drizzle-seed' import mysql from 'mysql2/promise' import { type MYSQL_BOOLEAN, POWER_STATUS, type PowerStatus, toMysqlBoolean } from '@/domain/battery' type SeedRow = { userId: number mac: string devModel: string devName: string isLowPower: (typeof MYSQL_BOOLEAN)[keyof typeof MYSQL_BOOLEAN] powerStatus: PowerStatus power: number createTime: Date remark: string | null } const lsBatteryInfo = mysqlTable( 'ls_battery_info', { id: int('id').autoincrement().primaryKey(), userId: int('user_id').notNull(), mac: varchar('mac', { length: 50 }).notNull(), devModel: varchar('dev_model', { length: 20 }).notNull(), devName: varchar('dev_name', { length: 50 }).notNull(), isLowPower: varchar('is_low_power', { length: 10 }).notNull(), powerStatus: tinyint('power_status').notNull(), power: tinyint('power').notNull(), createTime: datetime('create_time').notNull(), remark: varchar('remark', { length: 500 }), }, (table) => [index('idx_ls_battery_info_mac_time_id').on(table.mac, table.createTime, table.id)], ) const databaseUrl = process.env.DATABASE_URL if (!databaseUrl) { throw new Error('DATABASE_URL is required, for example mysql://battery:battery@localhost:3306/battery_soh') } const parsedUrl = new URL(databaseUrl) const safeSeedHosts = new Set(['localhost', '127.0.0.1', '0.0.0.0', 'db', 'mysql']) if (!safeSeedHosts.has(parsedUrl.hostname) && process.env.SEED_ALLOW_REMOTE !== 'true') { throw new Error( `Refusing to seed non-local MySQL host "${parsedUrl.hostname}". Set SEED_ALLOW_REMOTE=true only for disposable test databases.`, ) } const devices = [ { mac: 'RING-A03', model: 'SR-01', name: '样机-A03', basePower: 96, status: POWER_STATUS.FULL, remark: 'v3.8.2' }, { mac: 'RING-B11', model: 'SR-01', name: '样机-B11', basePower: 91, status: POWER_STATUS.CHARGING, remark: 'v3.8.2' }, { mac: 'RING-C07', model: 'SR-02', name: '样机-C07', basePower: 88, status: POWER_STATUS.NOT_CHARGING, remark: 'v3.8.1', }, { mac: 'RING-D19', model: 'SR-02', name: '样机-D19', basePower: 84, status: POWER_STATUS.NOT_CHARGING, remark: 'v3.7.9', }, { mac: 'RING-E21', model: 'SR-03', name: '样机-E21', basePower: 79, status: POWER_STATUS.CHARGING, remark: 'v3.7.9' }, { mac: 'RING-F02', model: 'SR-03', name: '样机-F02', basePower: 73, status: POWER_STATUS.NOT_CHARGING, remark: null }, { mac: 'RING-G15', model: 'SR-04', name: '样机-G15', basePower: 93, status: POWER_STATUS.FULL, remark: 'v3.9.0' }, { mac: 'RING-H09', model: 'SR-04', name: '样机-H09', basePower: 86, status: POWER_STATUS.NOT_CHARGING, remark: 'v3.8.1', }, ] satisfies Array<{ mac: string model: string name: string basePower: number status: PowerStatus remark: string | null }> function createSeedRows(now = new Date()): SeedRow[] { return devices.flatMap((device, deviceIndex) => Array.from({ length: 8 }, (_, historyIndex) => { const createdAt = new Date(now.getTime() - (historyIndex * 24 + deviceIndex * 2) * 60 * 60 * 1000) const power = Math.max(1, Math.min(100, device.basePower - historyIndex * 2 + (deviceIndex % 3))) return { userId: 1001 + (deviceIndex % 3), mac: device.mac, devModel: device.model, devName: device.name, isLowPower: toMysqlBoolean(power <= 20 || device.basePower <= 80), powerStatus: historyIndex === 0 ? device.status : POWER_STATUS.NOT_CHARGING, power, createTime: createdAt, remark: device.remark, } }), ) } const connection = await mysql.createConnection({ uri: databaseUrl }) const db = drizzle(connection) try { await db.execute(` CREATE TABLE IF NOT EXISTS ls_battery_info ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, mac varchar(50) NOT NULL, dev_model varchar(20) NOT NULL, dev_name varchar(50) NOT NULL, is_low_power varchar(10) NOT NULL, power_status tinyint(4) NOT NULL, power tinyint(4) NOT NULL, create_time datetime NOT NULL, remark varchar(500) DEFAULT NULL, PRIMARY KEY (id), KEY idx_ls_battery_info_mac_time_id (mac, create_time, id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `) await reset(db, { lsBatteryInfo }) await db.insert(lsBatteryInfo).values(createSeedRows()) process.stdout.write(`Seeded ${devices.length} devices into ls_battery_info.\n`) } finally { await connection.end() }