diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6173e1ac..207d6ddc 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -11,6 +11,7 @@ model device { id String @id @default(uuid()) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") + discoveredAt DateTime? name String role String? managementIp String? @map("management_ip") diff --git a/src/schema/api.graphql b/src/schema/api.graphql index c07fc17c..cf24e687 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -239,6 +239,7 @@ type Device implements Node { blueprint: Blueprint createdAt: String! deviceSize: DeviceSize! + discoveredAt: String id: ID! isInstalled: Boolean! labels(after: String, before: String, first: Int, last: Int): LabelConnection! @@ -262,6 +263,11 @@ type DeviceConnection { totalCount: Int! } +type DeviceDiscoveryPayload { + deviceId: String! + discoveredAt: String +} + type DeviceEdge { cursor: String! node: Device! @@ -475,6 +481,7 @@ type Mutation { updateBlueprint(id: String!, input: UpdateBlueprintInput!): UpdateBlueprintPayload! updateDataStore(deviceId: String!, input: UpdateDataStoreInput!, transactionId: String!): UpdateDataStorePayload! updateDevice(id: String!, input: UpdateDeviceInput!): UpdateDevicePayload! + updateDiscoveredAt(deviceIds: [String!]!): [DeviceDiscoveryPayload!]! updateGraphNodeCoordinates(input: UpdateGraphNodeCoordinatesInput!): UpdateGraphNodeCoordinatesPayload! updateStream(id: String!, input: UpdateStreamInput!): UpdateStreamPayload! } diff --git a/src/schema/device.ts b/src/schema/device.ts index 7d53829e..3dba97f1 100644 --- a/src/schema/device.ts +++ b/src/schema/device.ts @@ -10,6 +10,7 @@ import { extendType, inputObjectType, intArg, + list, nonNull, nullable, objectType, @@ -70,6 +71,14 @@ export const Device = objectType({ t.nonNull.string('updatedAt', { resolve: (device) => device.updatedAt.toISOString(), }); + t.string('discoveredAt', { + resolve: (device) => { + if (device.discoveredAt == null) { + return null; + } + return device.discoveredAt.toISOString(); + }, + }); t.string('model', { resolve: (root) => (root.model == null || root.model.trim().length === 0 ? null : root.model), }); @@ -458,6 +467,57 @@ export const UpdateDeviceMetadataPayload = objectType({ }, }); +export const DeviceDiscoveryPayload = objectType({ + name: 'DeviceDiscoveryPayload', + definition(t) { + t.nonNull.string('deviceId'); + t.string('discoveredAt'); + }, +}); + +export const UpdateDiscoveredAtMutation = extendType({ + type: 'Mutation', + definition(t) { + t.field('updateDiscoveredAt', { + type: nonNull(list(nonNull('DeviceDiscoveryPayload'))), + args: { + deviceIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { deviceIds }, { prisma }) => { + const currentTimestamp = new Date(); + const nativeIds = deviceIds.map((id) => fromGraphId('Device', id)); + await prisma.device.updateMany({ + where: { + id: { + in: nativeIds, + }, + }, + data: { + discoveredAt: currentTimestamp, + }, + }); + + const updatedDevices = await prisma.device.findMany({ + where: { + id: { + in: nativeIds, + }, + }, + select: { + id: true, + discoveredAt: true, + }, + }); + + return updatedDevices.map((device) => ({ + deviceId: toGraphId('Device', device.id), + discoveredAt: device.discoveredAt ? device.discoveredAt.toISOString() : null, + })); + }, + }); + }, +}); + export const DeleteDevicePayload = objectType({ name: 'DeleteDevicePayload', definition: (t) => { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 70aabb50..ebd0f0ac 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -344,6 +344,11 @@ export interface NexusGenObjects { pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! totalCount: number; // Int! }; + DeviceDiscoveryPayload: { + // root type + deviceId: string; // String! + discoveredAt?: string | null; // String + }; DeviceEdge: { // root type cursor: string; // String! @@ -884,6 +889,7 @@ export interface NexusGenFieldTypes { blueprint: NexusGenRootTypes['Blueprint'] | null; // Blueprint createdAt: string; // String! deviceSize: NexusGenEnums['DeviceSize']; // DeviceSize! + discoveredAt: string | null; // String id: string; // ID! isInstalled: boolean; // Boolean! labels: NexusGenRootTypes['LabelConnection']; // LabelConnection! @@ -906,6 +912,11 @@ export interface NexusGenFieldTypes { pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! totalCount: number; // Int! }; + DeviceDiscoveryPayload: { + // field return type + deviceId: string; // String! + discoveredAt: string | null; // String + }; DeviceEdge: { // field return type cursor: string; // String! @@ -1065,6 +1076,7 @@ export interface NexusGenFieldTypes { updateBlueprint: NexusGenRootTypes['UpdateBlueprintPayload']; // UpdateBlueprintPayload! updateDataStore: NexusGenRootTypes['UpdateDataStorePayload']; // UpdateDataStorePayload! updateDevice: NexusGenRootTypes['UpdateDevicePayload']; // UpdateDevicePayload! + updateDiscoveredAt: NexusGenRootTypes['DeviceDiscoveryPayload'][]; // [DeviceDiscoveryPayload!]! updateGraphNodeCoordinates: NexusGenRootTypes['UpdateGraphNodeCoordinatesPayload']; // UpdateGraphNodeCoordinatesPayload! updateStream: NexusGenRootTypes['UpdateStreamPayload']; // UpdateStreamPayload! }; @@ -1538,6 +1550,7 @@ export interface NexusGenFieldTypeNames { blueprint: 'Blueprint'; createdAt: 'String'; deviceSize: 'DeviceSize'; + discoveredAt: 'String'; id: 'ID'; isInstalled: 'Boolean'; labels: 'LabelConnection'; @@ -1560,6 +1573,11 @@ export interface NexusGenFieldTypeNames { pageInfo: 'PageInfo'; totalCount: 'Int'; }; + DeviceDiscoveryPayload: { + // field return type name + deviceId: 'String'; + discoveredAt: 'String'; + }; DeviceEdge: { // field return type name cursor: 'String'; @@ -1719,6 +1737,7 @@ export interface NexusGenFieldTypeNames { updateBlueprint: 'UpdateBlueprintPayload'; updateDataStore: 'UpdateDataStorePayload'; updateDevice: 'UpdateDevicePayload'; + updateDiscoveredAt: 'DeviceDiscoveryPayload'; updateGraphNodeCoordinates: 'UpdateGraphNodeCoordinatesPayload'; updateStream: 'UpdateStreamPayload'; }; @@ -2174,6 +2193,10 @@ export interface NexusGenArgTypes { id: string; // String! input: NexusGenInputs['UpdateDeviceInput']; // UpdateDeviceInput! }; + updateDiscoveredAt: { + // args + deviceIds: string[]; // [String!]! + }; updateGraphNodeCoordinates: { // args input: NexusGenInputs['UpdateGraphNodeCoordinatesInput']; // UpdateGraphNodeCoordinatesInput!