import { flags } from "@oclif/command"; import { ux } from "cli-ux"; import { capitalize } from "lodash"; import { FindConditions } from "typeorm"; import ManageCommand from "../ManageCommand"; import { Input } from "@oclif/parser/lib/flags"; import { SprinklersDevice, User } from "@server/entities"; type DeviceFlags = (typeof DeviceCommand)["flags"] extends Input ? F : never; type Action = "show" | "delete" | "add-user" | "remove-user"; const VALID_ACTIONS: Action[] = [ "show", "delete", "add-user", "remove-user" ]; // tslint:disable:no-shadowed-variable export default class DeviceCommand extends ManageCommand { static description = "Manage devices"; static flags = { show: flags.boolean({ char: "s", exclusive: ["add-user", "delete"], description: "Show devices(s)", }), "add-user": flags.boolean({ char: "a", exclusive: ["show", "delete"], description: "Add a user as owning this device (specify --username)" }), "remove-user": flags.boolean({ char: "r", exclusive: ["add-user", "show", "delete"], description: "Remove a user as owning this device (specify --username)" }), delete: flags.boolean({ char: "d", exclusive: ["show", "add-user"], description: "Delete a user (by --id or --username)" }), id: flags.integer({ description: "The id of the device to update or delete", }), name: flags.string({ description: "The name of the device, when creating or updating" }), deviceId: flags.string({ description: "The deviceId of the device, when creating or updating" }), username: flags.string({ description: "Specify a username for --show or --add-user" }), }; getAction(flags: DeviceFlags): Action { for (const action of VALID_ACTIONS) { if (flags[action]) { return action; } } const actionFlags = VALID_ACTIONS.map(action => `--${action}`); this.error(`Must specify an action (${actionFlags.join(', ')})`, { exit: false, }); return this._help(); } getFindConditions(flags: DeviceFlags, action: Action): FindConditions { const whereClause: FindConditions = {}; if (flags.id) { whereClause.id = flags.id; } if (flags.name) { whereClause.name = flags.name; } if (flags.deviceId) { whereClause.deviceId = flags.deviceId; } if (false) { this.error(`Must specify --id to ${action}`, { exit: false }); return this._help(); } return whereClause; } async getOrDeleteDevice(flags: DeviceFlags, action: Action): Promise { const findConditions = this.getFindConditions(flags, action); if (action === "delete") { const result = await this.database.sprinklersDevices.delete(findConditions); if (result.raw[1] > 0) { this.log(`Deleted device`); } else { this.error("Did not find device to delete"); } return this.exit(); } else { const device = await this.database.sprinklersDevices.findOne(findConditions); if (!device) { return this.error(`The specified device does not exist`); } return device; } } async run() { const parseResult = this.parse(DeviceCommand); const flags = parseResult.flags; const action = this.getAction(flags); await this.connect(); if (flags.show) { const findConditions = this.getFindConditions(flags, action); let query = this.database.sprinklersDevices.createQueryBuilder("device") .leftJoinAndSelect("device.users", "user") .where(findConditions); if (flags.username) { query = query.where("user.username = :username", { username: flags.username }); } const devices = await query.getMany(); if (devices.length === 0) { this.log("No sprinklers devices found"); return 1; } this.log("Devices: ") for (const device of devices) { this.log(JSON.stringify(device, null, " ")); } return; } const device = await this.getOrDeleteDevice(flags, action); if (flags["add-user"] || flags["remove-user"]) { if (!flags.username) { return this.error("Must specify --username for --add-user") } const user = await this.database.users.findByUsername(flags.username); if (!user) { return this.error(`Could not find user with username '${flags.username}'`); } const query = this.database.sprinklersDevices.createQueryBuilder() .relation("users") .of(device); if (flags["add-user"]) { await query.add(user); this.log(`Added user '${user.username}' to device '${device.name}`); } else { await query.remove(user); this.log(`Removed user '${user.username}' from device '${device.name}`); } } } }