@openmdm/hono 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -99,9 +99,15 @@ function honoAdapter(mdm, options = {}) {
99
99
  timestamp: new Date(body.timestamp || Date.now())
100
100
  });
101
101
  const pendingCommands = await mdm.commands.getPending(deviceId);
102
+ const device = await mdm.devices.get(deviceId);
103
+ let policyUpdate = null;
104
+ if (device?.policyId) {
105
+ policyUpdate = await mdm.policies.get(device.policyId);
106
+ }
102
107
  return c.json({
103
- status: "ok",
104
- commands: pendingCommands
108
+ success: true,
109
+ pendingCommands,
110
+ policyUpdate
105
111
  });
106
112
  });
107
113
  enrollment.get("/config", deviceAuth, async (c) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * OpenMDM Hono Adapter\n *\n * HTTP routes adapter for Hono framework.\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { createMDM } from '@openmdm/core';\n * import { honoAdapter } from '@openmdm/hono';\n *\n * const mdm = createMDM({ ... });\n * const app = new Hono<MDMEnv>();\n *\n * // Mount MDM routes\n * app.route('/mdm', honoAdapter(mdm));\n * ```\n */\n\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport type { Context, MiddlewareHandler, Env } from 'hono';\nimport type {\n MDMInstance,\n EnrollmentRequest,\n Heartbeat,\n DeviceFilter,\n CommandFilter,\n CreatePolicyInput,\n UpdatePolicyInput,\n CreateApplicationInput,\n UpdateApplicationInput,\n CreateGroupInput,\n UpdateGroupInput,\n SendCommandInput,\n MDMError,\n AuthenticationError,\n AuthorizationError,\n} from '@openmdm/core';\n\n/**\n * Context variables set by OpenMDM middlewares\n */\ninterface MDMVariables {\n deviceId?: string;\n user?: unknown;\n}\n\n/**\n * Hono environment type for OpenMDM routes\n */\ntype MDMEnv = {\n Variables: MDMVariables;\n};\n\nexport interface HonoAdapterOptions {\n /**\n * Base path prefix for all routes (default: '')\n */\n basePath?: string;\n\n /**\n * Enable authentication middleware for admin routes\n */\n enableAuth?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Error, c: Context) => Response | Promise<Response>;\n\n /**\n * Routes to expose (default: all)\n */\n routes?: {\n enrollment?: boolean;\n devices?: boolean;\n policies?: boolean;\n applications?: boolean;\n groups?: boolean;\n commands?: boolean;\n events?: boolean;\n };\n}\n\n/**\n * Create a Hono router with OpenMDM API routes\n */\nexport function honoAdapter(\n mdm: MDMInstance,\n options: HonoAdapterOptions = {}\n): Hono<MDMEnv> {\n const app = new Hono<MDMEnv>();\n\n const routes = {\n enrollment: true,\n devices: true,\n policies: true,\n applications: true,\n groups: true,\n commands: true,\n events: true,\n ...options.routes,\n };\n\n // Error handling middleware\n app.onError((error, c) => {\n if (options.onError) {\n return options.onError(error, c);\n }\n\n console.error('[OpenMDM] Error:', error);\n\n if (error instanceof HTTPException) {\n return c.json({ error: error.message }, error.status);\n }\n\n const mdmError = error as MDMError;\n if (mdmError.code && mdmError.statusCode) {\n return c.json(\n {\n error: mdmError.message,\n code: mdmError.code,\n details: mdmError.details,\n },\n mdmError.statusCode as any\n );\n }\n\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n // Device authentication middleware\n const deviceAuth: MiddlewareHandler = async (c, next) => {\n const token = c.req.header('Authorization')?.replace('Bearer ', '');\n const deviceId = c.req.header('X-Device-Id');\n\n if (!token && !deviceId) {\n throw new HTTPException(401, { message: 'Device authentication required' });\n }\n\n if (token) {\n const result = await mdm.verifyDeviceToken(token);\n if (!result) {\n throw new HTTPException(401, { message: 'Invalid device token' });\n }\n c.set('deviceId', result.deviceId);\n } else if (deviceId) {\n c.set('deviceId', deviceId);\n }\n\n await next();\n };\n\n // Admin authentication middleware\n const adminAuth: MiddlewareHandler = async (c, next) => {\n if (!mdm.config.auth) {\n await next();\n return;\n }\n\n const user = await mdm.config.auth.getUser(c);\n if (!user) {\n throw new HTTPException(401, { message: 'Authentication required' });\n }\n\n if (mdm.config.auth.isAdmin) {\n const isAdmin = await mdm.config.auth.isAdmin(user);\n if (!isAdmin) {\n throw new HTTPException(403, { message: 'Admin access required' });\n }\n }\n\n c.set('user', user);\n await next();\n };\n\n // ============================================\n // Enrollment Routes (Device-facing)\n // ============================================\n\n if (routes.enrollment) {\n const enrollment = new Hono<MDMEnv>();\n\n // Enroll device\n enrollment.post('/enroll', async (c) => {\n const body = await c.req.json<EnrollmentRequest>();\n\n // Validate required fields\n if (!body.model || !body.manufacturer || !body.osVersion) {\n throw new HTTPException(400, {\n message: 'Missing required fields: model, manufacturer, osVersion',\n });\n }\n\n if (!body.macAddress && !body.serialNumber && !body.imei && !body.androidId) {\n throw new HTTPException(400, {\n message: 'At least one device identifier required',\n });\n }\n\n const result = await mdm.enroll(body);\n\n // Add server URL from request if not configured\n if (!result.serverUrl) {\n const url = new URL(c.req.url);\n result.serverUrl = `${url.protocol}//${url.host}`;\n }\n\n return c.json(result, 201);\n });\n\n // Device heartbeat\n enrollment.post('/heartbeat', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const body = await c.req.json<Omit<Heartbeat, 'deviceId'>>();\n\n await mdm.processHeartbeat(deviceId, {\n ...body,\n deviceId,\n timestamp: new Date(body.timestamp || Date.now()),\n });\n\n // Return pending commands for the device\n const pendingCommands = await mdm.commands.getPending(deviceId);\n\n return c.json({\n status: 'ok',\n commands: pendingCommands,\n });\n });\n\n // Get device config/policy\n enrollment.get('/config', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const device = await mdm.devices.get(deviceId);\n\n if (!device) {\n throw new HTTPException(404, { message: 'Device not found' });\n }\n\n let policy = null;\n if (device.policyId) {\n policy = await mdm.policies.get(device.policyId);\n } else {\n policy = await mdm.policies.getDefault();\n }\n\n return c.json({\n device: {\n id: device.id,\n enrollmentId: device.enrollmentId,\n status: device.status,\n },\n policy,\n });\n });\n\n // Register push token\n enrollment.post('/push-token', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const body = await c.req.json<{ provider: string; token: string }>();\n\n await mdm.db.upsertPushToken({\n deviceId,\n provider: body.provider as any,\n token: body.token,\n });\n\n return c.json({ status: 'ok' });\n });\n\n // Acknowledge command\n enrollment.post('/commands/:id/ack', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const command = await mdm.commands.acknowledge(commandId);\n return c.json(command);\n });\n\n // Complete command\n enrollment.post('/commands/:id/complete', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const body = await c.req.json<{ success: boolean; message?: string; data?: unknown }>();\n const command = await mdm.commands.complete(commandId, body);\n return c.json(command);\n });\n\n // Fail command\n enrollment.post('/commands/:id/fail', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const body = await c.req.json<{ error: string }>();\n const command = await mdm.commands.fail(commandId, body.error);\n return c.json(command);\n });\n\n app.route('/agent', enrollment);\n }\n\n // ============================================\n // Device Routes (Admin-facing)\n // ============================================\n\n if (routes.devices) {\n const devices = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n devices.use('/*', adminAuth);\n }\n\n // List devices\n devices.get('/', async (c) => {\n const filter: DeviceFilter = {\n status: c.req.query('status') as any,\n policyId: c.req.query('policyId'),\n groupId: c.req.query('groupId'),\n search: c.req.query('search'),\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.devices.list(filter);\n return c.json(result);\n });\n\n // Get device\n devices.get('/:id', async (c) => {\n const device = await mdm.devices.get(c.req.param('id'));\n if (!device) {\n throw new HTTPException(404, { message: 'Device not found' });\n }\n return c.json(device);\n });\n\n // Update device\n devices.patch('/:id', async (c) => {\n const body = await c.req.json();\n const device = await mdm.devices.update(c.req.param('id'), body);\n return c.json(device);\n });\n\n // Delete device\n devices.delete('/:id', async (c) => {\n await mdm.devices.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Assign policy to device\n devices.post('/:id/policy', async (c) => {\n const { policyId } = await c.req.json<{ policyId: string | null }>();\n const device = await mdm.devices.assignPolicy(c.req.param('id'), policyId);\n return c.json(device);\n });\n\n // Get device groups\n devices.get('/:id/groups', async (c) => {\n const groups = await mdm.devices.getGroups(c.req.param('id'));\n return c.json({ groups });\n });\n\n // Add device to group\n devices.post('/:id/groups', async (c) => {\n const { groupId } = await c.req.json<{ groupId: string }>();\n await mdm.devices.addToGroup(c.req.param('id'), groupId);\n return c.json({ status: 'ok' });\n });\n\n // Remove device from group\n devices.delete('/:id/groups/:groupId', async (c) => {\n await mdm.devices.removeFromGroup(c.req.param('id'), c.req.param('groupId'));\n return c.json({ status: 'ok' });\n });\n\n // Send command to device\n devices.post('/:id/commands', async (c) => {\n const body = await c.req.json<Omit<SendCommandInput, 'deviceId'>>();\n const command = await mdm.devices.sendCommand(c.req.param('id'), body);\n return c.json(command, 201);\n });\n\n // Convenience: Sync device\n devices.post('/:id/sync', async (c) => {\n const command = await mdm.devices.sync(c.req.param('id'));\n return c.json(command, 201);\n });\n\n // Convenience: Reboot device\n devices.post('/:id/reboot', async (c) => {\n const command = await mdm.devices.reboot(c.req.param('id'));\n return c.json(command, 201);\n });\n\n // Convenience: Lock device\n devices.post('/:id/lock', async (c) => {\n const body = await c.req.json<{ message?: string }>().catch(() => ({ message: undefined }));\n const command = await mdm.devices.lock(c.req.param('id'), body.message);\n return c.json(command, 201);\n });\n\n // Convenience: Wipe device\n devices.post('/:id/wipe', async (c) => {\n const body = await c.req.json<{ preserveData?: boolean }>().catch(() => ({ preserveData: undefined }));\n const command = await mdm.devices.wipe(c.req.param('id'), body.preserveData);\n return c.json(command, 201);\n });\n\n app.route('/devices', devices);\n }\n\n // ============================================\n // Policy Routes\n // ============================================\n\n if (routes.policies) {\n const policies = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n policies.use('/*', adminAuth);\n }\n\n // List policies\n policies.get('/', async (c) => {\n const result = await mdm.policies.list();\n return c.json({ policies: result });\n });\n\n // Get default policy\n policies.get('/default', async (c) => {\n const policy = await mdm.policies.getDefault();\n if (!policy) {\n throw new HTTPException(404, { message: 'No default policy set' });\n }\n return c.json(policy);\n });\n\n // Get policy\n policies.get('/:id', async (c) => {\n const policy = await mdm.policies.get(c.req.param('id'));\n if (!policy) {\n throw new HTTPException(404, { message: 'Policy not found' });\n }\n return c.json(policy);\n });\n\n // Create policy\n policies.post('/', async (c) => {\n const body = await c.req.json<CreatePolicyInput>();\n const policy = await mdm.policies.create(body);\n return c.json(policy, 201);\n });\n\n // Update policy\n policies.patch('/:id', async (c) => {\n const body = await c.req.json<UpdatePolicyInput>();\n const policy = await mdm.policies.update(c.req.param('id'), body);\n return c.json(policy);\n });\n\n // Delete policy\n policies.delete('/:id', async (c) => {\n await mdm.policies.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Set default policy\n policies.post('/:id/default', async (c) => {\n const policy = await mdm.policies.setDefault(c.req.param('id'));\n return c.json(policy);\n });\n\n // Get devices with this policy\n policies.get('/:id/devices', async (c) => {\n const devices = await mdm.policies.getDevices(c.req.param('id'));\n return c.json({ devices });\n });\n\n app.route('/policies', policies);\n }\n\n // ============================================\n // Application Routes\n // ============================================\n\n if (routes.applications) {\n const applications = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n applications.use('/*', adminAuth);\n }\n\n // List applications\n applications.get('/', async (c) => {\n const activeOnly = c.req.query('active') === 'true';\n const result = await mdm.apps.list(activeOnly);\n return c.json({ applications: result });\n });\n\n // Get application by ID\n applications.get('/:id', async (c) => {\n const app = await mdm.apps.get(c.req.param('id'));\n if (!app) {\n throw new HTTPException(404, { message: 'Application not found' });\n }\n return c.json(app);\n });\n\n // Get application by package name\n applications.get('/package/:packageName', async (c) => {\n const version = c.req.query('version');\n const app = await mdm.apps.getByPackage(c.req.param('packageName'), version);\n if (!app) {\n throw new HTTPException(404, { message: 'Application not found' });\n }\n return c.json(app);\n });\n\n // Register application\n applications.post('/', async (c) => {\n const body = await c.req.json<CreateApplicationInput>();\n const app = await mdm.apps.register(body);\n return c.json(app, 201);\n });\n\n // Update application\n applications.patch('/:id', async (c) => {\n const body = await c.req.json<UpdateApplicationInput>();\n const app = await mdm.apps.update(c.req.param('id'), body);\n return c.json(app);\n });\n\n // Delete application\n applications.delete('/:id', async (c) => {\n await mdm.apps.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Activate application\n applications.post('/:id/activate', async (c) => {\n const app = await mdm.apps.activate(c.req.param('id'));\n return c.json(app);\n });\n\n // Deactivate application\n applications.post('/:id/deactivate', async (c) => {\n const app = await mdm.apps.deactivate(c.req.param('id'));\n return c.json(app);\n });\n\n // Deploy application\n applications.post('/:packageName/deploy', async (c) => {\n const body = await c.req.json<{\n devices?: string[];\n policies?: string[];\n groups?: string[];\n }>();\n await mdm.apps.deploy(c.req.param('packageName'), body);\n return c.json({ status: 'ok', message: 'Deployment initiated' });\n });\n\n // Install app on device\n applications.post('/:packageName/install/:deviceId', async (c) => {\n const version = c.req.query('version');\n const command = await mdm.apps.installOnDevice(\n c.req.param('packageName'),\n c.req.param('deviceId'),\n version\n );\n return c.json(command, 201);\n });\n\n // Uninstall app from device\n applications.post('/:packageName/uninstall/:deviceId', async (c) => {\n const command = await mdm.apps.uninstallFromDevice(\n c.req.param('packageName'),\n c.req.param('deviceId')\n );\n return c.json(command, 201);\n });\n\n app.route('/applications', applications);\n }\n\n // ============================================\n // Group Routes\n // ============================================\n\n if (routes.groups) {\n const groups = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n groups.use('/*', adminAuth);\n }\n\n // List groups\n groups.get('/', async (c) => {\n const result = await mdm.groups.list();\n return c.json({ groups: result });\n });\n\n // Get group\n groups.get('/:id', async (c) => {\n const group = await mdm.groups.get(c.req.param('id'));\n if (!group) {\n throw new HTTPException(404, { message: 'Group not found' });\n }\n return c.json(group);\n });\n\n // Create group\n groups.post('/', async (c) => {\n const body = await c.req.json<CreateGroupInput>();\n const group = await mdm.groups.create(body);\n return c.json(group, 201);\n });\n\n // Update group\n groups.patch('/:id', async (c) => {\n const body = await c.req.json<UpdateGroupInput>();\n const group = await mdm.groups.update(c.req.param('id'), body);\n return c.json(group);\n });\n\n // Delete group\n groups.delete('/:id', async (c) => {\n await mdm.groups.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Get devices in group\n groups.get('/:id/devices', async (c) => {\n const devices = await mdm.groups.getDevices(c.req.param('id'));\n return c.json({ devices });\n });\n\n // Add device to group\n groups.post('/:id/devices', async (c) => {\n const { deviceId } = await c.req.json<{ deviceId: string }>();\n await mdm.groups.addDevice(c.req.param('id'), deviceId);\n return c.json({ status: 'ok' });\n });\n\n // Remove device from group\n groups.delete('/:id/devices/:deviceId', async (c) => {\n await mdm.groups.removeDevice(c.req.param('id'), c.req.param('deviceId'));\n return c.json({ status: 'ok' });\n });\n\n // Get child groups\n groups.get('/:id/children', async (c) => {\n const children = await mdm.groups.getChildren(c.req.param('id'));\n return c.json({ groups: children });\n });\n\n app.route('/groups', groups);\n }\n\n // ============================================\n // Command Routes\n // ============================================\n\n if (routes.commands) {\n const commands = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n commands.use('/*', adminAuth);\n }\n\n // List commands\n commands.get('/', async (c) => {\n const filter: CommandFilter = {\n deviceId: c.req.query('deviceId'),\n status: c.req.query('status') as any,\n type: c.req.query('type') as any,\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.commands.list(filter);\n return c.json({ commands: result });\n });\n\n // Get command\n commands.get('/:id', async (c) => {\n const command = await mdm.commands.get(c.req.param('id'));\n if (!command) {\n throw new HTTPException(404, { message: 'Command not found' });\n }\n return c.json(command);\n });\n\n // Send command\n commands.post('/', async (c) => {\n const body = await c.req.json<SendCommandInput>();\n const command = await mdm.commands.send(body);\n return c.json(command, 201);\n });\n\n // Cancel command\n commands.post('/:id/cancel', async (c) => {\n const command = await mdm.commands.cancel(c.req.param('id'));\n return c.json(command);\n });\n\n app.route('/commands', commands);\n }\n\n // ============================================\n // Event Routes\n // ============================================\n\n if (routes.events) {\n const events = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n events.use('/*', adminAuth);\n }\n\n // List events\n events.get('/', async (c) => {\n const filter = {\n deviceId: c.req.query('deviceId'),\n type: c.req.query('type') as any,\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.db.listEvents(filter);\n return c.json({ events: result });\n });\n\n app.route('/events', events);\n }\n\n // ============================================\n // Health Check\n // ============================================\n\n app.get('/health', (c) => {\n return c.json({\n status: 'ok',\n version: '0.1.0',\n timestamp: new Date().toISOString(),\n });\n });\n\n return app;\n}\n"],"mappings":"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","names":["app"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * OpenMDM Hono Adapter\n *\n * HTTP routes adapter for Hono framework.\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { createMDM } from '@openmdm/core';\n * import { honoAdapter } from '@openmdm/hono';\n *\n * const mdm = createMDM({ ... });\n * const app = new Hono<MDMEnv>();\n *\n * // Mount MDM routes\n * app.route('/mdm', honoAdapter(mdm));\n * ```\n */\n\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport type { Context, MiddlewareHandler, Env } from 'hono';\nimport type {\n MDMInstance,\n EnrollmentRequest,\n Heartbeat,\n DeviceFilter,\n CommandFilter,\n CreatePolicyInput,\n UpdatePolicyInput,\n CreateApplicationInput,\n UpdateApplicationInput,\n CreateGroupInput,\n UpdateGroupInput,\n SendCommandInput,\n MDMError,\n AuthenticationError,\n AuthorizationError,\n} from '@openmdm/core';\n\n/**\n * Context variables set by OpenMDM middlewares\n */\ninterface MDMVariables {\n deviceId?: string;\n user?: unknown;\n}\n\n/**\n * Hono environment type for OpenMDM routes\n */\ntype MDMEnv = {\n Variables: MDMVariables;\n};\n\nexport interface HonoAdapterOptions {\n /**\n * Base path prefix for all routes (default: '')\n */\n basePath?: string;\n\n /**\n * Enable authentication middleware for admin routes\n */\n enableAuth?: boolean;\n\n /**\n * Custom error handler\n */\n onError?: (error: Error, c: Context) => Response | Promise<Response>;\n\n /**\n * Routes to expose (default: all)\n */\n routes?: {\n enrollment?: boolean;\n devices?: boolean;\n policies?: boolean;\n applications?: boolean;\n groups?: boolean;\n commands?: boolean;\n events?: boolean;\n };\n}\n\n/**\n * Create a Hono router with OpenMDM API routes\n */\nexport function honoAdapter(\n mdm: MDMInstance,\n options: HonoAdapterOptions = {}\n): Hono<MDMEnv> {\n const app = new Hono<MDMEnv>();\n\n const routes = {\n enrollment: true,\n devices: true,\n policies: true,\n applications: true,\n groups: true,\n commands: true,\n events: true,\n ...options.routes,\n };\n\n // Error handling middleware\n app.onError((error, c) => {\n if (options.onError) {\n return options.onError(error, c);\n }\n\n console.error('[OpenMDM] Error:', error);\n\n if (error instanceof HTTPException) {\n return c.json({ error: error.message }, error.status);\n }\n\n const mdmError = error as MDMError;\n if (mdmError.code && mdmError.statusCode) {\n return c.json(\n {\n error: mdmError.message,\n code: mdmError.code,\n details: mdmError.details,\n },\n mdmError.statusCode as any\n );\n }\n\n return c.json({ error: 'Internal server error' }, 500);\n });\n\n // Device authentication middleware\n const deviceAuth: MiddlewareHandler = async (c, next) => {\n const token = c.req.header('Authorization')?.replace('Bearer ', '');\n const deviceId = c.req.header('X-Device-Id');\n\n if (!token && !deviceId) {\n throw new HTTPException(401, { message: 'Device authentication required' });\n }\n\n if (token) {\n const result = await mdm.verifyDeviceToken(token);\n if (!result) {\n throw new HTTPException(401, { message: 'Invalid device token' });\n }\n c.set('deviceId', result.deviceId);\n } else if (deviceId) {\n c.set('deviceId', deviceId);\n }\n\n await next();\n };\n\n // Admin authentication middleware\n const adminAuth: MiddlewareHandler = async (c, next) => {\n if (!mdm.config.auth) {\n await next();\n return;\n }\n\n const user = await mdm.config.auth.getUser(c);\n if (!user) {\n throw new HTTPException(401, { message: 'Authentication required' });\n }\n\n if (mdm.config.auth.isAdmin) {\n const isAdmin = await mdm.config.auth.isAdmin(user);\n if (!isAdmin) {\n throw new HTTPException(403, { message: 'Admin access required' });\n }\n }\n\n c.set('user', user);\n await next();\n };\n\n // ============================================\n // Enrollment Routes (Device-facing)\n // ============================================\n\n if (routes.enrollment) {\n const enrollment = new Hono<MDMEnv>();\n\n // Enroll device\n enrollment.post('/enroll', async (c) => {\n const body = await c.req.json<EnrollmentRequest>();\n\n // Validate required fields\n if (!body.model || !body.manufacturer || !body.osVersion) {\n throw new HTTPException(400, {\n message: 'Missing required fields: model, manufacturer, osVersion',\n });\n }\n\n if (!body.macAddress && !body.serialNumber && !body.imei && !body.androidId) {\n throw new HTTPException(400, {\n message: 'At least one device identifier required',\n });\n }\n\n const result = await mdm.enroll(body);\n\n // Add server URL from request if not configured\n if (!result.serverUrl) {\n const url = new URL(c.req.url);\n result.serverUrl = `${url.protocol}//${url.host}`;\n }\n\n return c.json(result, 201);\n });\n\n // Device heartbeat\n enrollment.post('/heartbeat', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const body = await c.req.json<Omit<Heartbeat, 'deviceId'>>();\n\n await mdm.processHeartbeat(deviceId, {\n ...body,\n deviceId,\n timestamp: new Date(body.timestamp || Date.now()),\n });\n\n // Return pending commands for the device\n const pendingCommands = await mdm.commands.getPending(deviceId);\n\n // Get current policy if device has one\n const device = await mdm.devices.get(deviceId);\n let policyUpdate = null;\n if (device?.policyId) {\n policyUpdate = await mdm.policies.get(device.policyId);\n }\n\n return c.json({\n success: true,\n pendingCommands: pendingCommands,\n policyUpdate: policyUpdate,\n });\n });\n\n // Get device config/policy\n enrollment.get('/config', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const device = await mdm.devices.get(deviceId);\n\n if (!device) {\n throw new HTTPException(404, { message: 'Device not found' });\n }\n\n let policy = null;\n if (device.policyId) {\n policy = await mdm.policies.get(device.policyId);\n } else {\n policy = await mdm.policies.getDefault();\n }\n\n return c.json({\n device: {\n id: device.id,\n enrollmentId: device.enrollmentId,\n status: device.status,\n },\n policy,\n });\n });\n\n // Register push token\n enrollment.post('/push-token', deviceAuth, async (c) => {\n const deviceId = c.get('deviceId') as string;\n const body = await c.req.json<{ provider: string; token: string }>();\n\n await mdm.db.upsertPushToken({\n deviceId,\n provider: body.provider as any,\n token: body.token,\n });\n\n return c.json({ status: 'ok' });\n });\n\n // Acknowledge command\n enrollment.post('/commands/:id/ack', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const command = await mdm.commands.acknowledge(commandId);\n return c.json(command);\n });\n\n // Complete command\n enrollment.post('/commands/:id/complete', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const body = await c.req.json<{ success: boolean; message?: string; data?: unknown }>();\n const command = await mdm.commands.complete(commandId, body);\n return c.json(command);\n });\n\n // Fail command\n enrollment.post('/commands/:id/fail', deviceAuth, async (c) => {\n const commandId = c.req.param('id');\n const body = await c.req.json<{ error: string }>();\n const command = await mdm.commands.fail(commandId, body.error);\n return c.json(command);\n });\n\n app.route('/agent', enrollment);\n }\n\n // ============================================\n // Device Routes (Admin-facing)\n // ============================================\n\n if (routes.devices) {\n const devices = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n devices.use('/*', adminAuth);\n }\n\n // List devices\n devices.get('/', async (c) => {\n const filter: DeviceFilter = {\n status: c.req.query('status') as any,\n policyId: c.req.query('policyId'),\n groupId: c.req.query('groupId'),\n search: c.req.query('search'),\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.devices.list(filter);\n return c.json(result);\n });\n\n // Get device\n devices.get('/:id', async (c) => {\n const device = await mdm.devices.get(c.req.param('id'));\n if (!device) {\n throw new HTTPException(404, { message: 'Device not found' });\n }\n return c.json(device);\n });\n\n // Update device\n devices.patch('/:id', async (c) => {\n const body = await c.req.json();\n const device = await mdm.devices.update(c.req.param('id'), body);\n return c.json(device);\n });\n\n // Delete device\n devices.delete('/:id', async (c) => {\n await mdm.devices.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Assign policy to device\n devices.post('/:id/policy', async (c) => {\n const { policyId } = await c.req.json<{ policyId: string | null }>();\n const device = await mdm.devices.assignPolicy(c.req.param('id'), policyId);\n return c.json(device);\n });\n\n // Get device groups\n devices.get('/:id/groups', async (c) => {\n const groups = await mdm.devices.getGroups(c.req.param('id'));\n return c.json({ groups });\n });\n\n // Add device to group\n devices.post('/:id/groups', async (c) => {\n const { groupId } = await c.req.json<{ groupId: string }>();\n await mdm.devices.addToGroup(c.req.param('id'), groupId);\n return c.json({ status: 'ok' });\n });\n\n // Remove device from group\n devices.delete('/:id/groups/:groupId', async (c) => {\n await mdm.devices.removeFromGroup(c.req.param('id'), c.req.param('groupId'));\n return c.json({ status: 'ok' });\n });\n\n // Send command to device\n devices.post('/:id/commands', async (c) => {\n const body = await c.req.json<Omit<SendCommandInput, 'deviceId'>>();\n const command = await mdm.devices.sendCommand(c.req.param('id'), body);\n return c.json(command, 201);\n });\n\n // Convenience: Sync device\n devices.post('/:id/sync', async (c) => {\n const command = await mdm.devices.sync(c.req.param('id'));\n return c.json(command, 201);\n });\n\n // Convenience: Reboot device\n devices.post('/:id/reboot', async (c) => {\n const command = await mdm.devices.reboot(c.req.param('id'));\n return c.json(command, 201);\n });\n\n // Convenience: Lock device\n devices.post('/:id/lock', async (c) => {\n const body = await c.req.json<{ message?: string }>().catch(() => ({ message: undefined }));\n const command = await mdm.devices.lock(c.req.param('id'), body.message);\n return c.json(command, 201);\n });\n\n // Convenience: Wipe device\n devices.post('/:id/wipe', async (c) => {\n const body = await c.req.json<{ preserveData?: boolean }>().catch(() => ({ preserveData: undefined }));\n const command = await mdm.devices.wipe(c.req.param('id'), body.preserveData);\n return c.json(command, 201);\n });\n\n app.route('/devices', devices);\n }\n\n // ============================================\n // Policy Routes\n // ============================================\n\n if (routes.policies) {\n const policies = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n policies.use('/*', adminAuth);\n }\n\n // List policies\n policies.get('/', async (c) => {\n const result = await mdm.policies.list();\n return c.json({ policies: result });\n });\n\n // Get default policy\n policies.get('/default', async (c) => {\n const policy = await mdm.policies.getDefault();\n if (!policy) {\n throw new HTTPException(404, { message: 'No default policy set' });\n }\n return c.json(policy);\n });\n\n // Get policy\n policies.get('/:id', async (c) => {\n const policy = await mdm.policies.get(c.req.param('id'));\n if (!policy) {\n throw new HTTPException(404, { message: 'Policy not found' });\n }\n return c.json(policy);\n });\n\n // Create policy\n policies.post('/', async (c) => {\n const body = await c.req.json<CreatePolicyInput>();\n const policy = await mdm.policies.create(body);\n return c.json(policy, 201);\n });\n\n // Update policy\n policies.patch('/:id', async (c) => {\n const body = await c.req.json<UpdatePolicyInput>();\n const policy = await mdm.policies.update(c.req.param('id'), body);\n return c.json(policy);\n });\n\n // Delete policy\n policies.delete('/:id', async (c) => {\n await mdm.policies.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Set default policy\n policies.post('/:id/default', async (c) => {\n const policy = await mdm.policies.setDefault(c.req.param('id'));\n return c.json(policy);\n });\n\n // Get devices with this policy\n policies.get('/:id/devices', async (c) => {\n const devices = await mdm.policies.getDevices(c.req.param('id'));\n return c.json({ devices });\n });\n\n app.route('/policies', policies);\n }\n\n // ============================================\n // Application Routes\n // ============================================\n\n if (routes.applications) {\n const applications = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n applications.use('/*', adminAuth);\n }\n\n // List applications\n applications.get('/', async (c) => {\n const activeOnly = c.req.query('active') === 'true';\n const result = await mdm.apps.list(activeOnly);\n return c.json({ applications: result });\n });\n\n // Get application by ID\n applications.get('/:id', async (c) => {\n const app = await mdm.apps.get(c.req.param('id'));\n if (!app) {\n throw new HTTPException(404, { message: 'Application not found' });\n }\n return c.json(app);\n });\n\n // Get application by package name\n applications.get('/package/:packageName', async (c) => {\n const version = c.req.query('version');\n const app = await mdm.apps.getByPackage(c.req.param('packageName'), version);\n if (!app) {\n throw new HTTPException(404, { message: 'Application not found' });\n }\n return c.json(app);\n });\n\n // Register application\n applications.post('/', async (c) => {\n const body = await c.req.json<CreateApplicationInput>();\n const app = await mdm.apps.register(body);\n return c.json(app, 201);\n });\n\n // Update application\n applications.patch('/:id', async (c) => {\n const body = await c.req.json<UpdateApplicationInput>();\n const app = await mdm.apps.update(c.req.param('id'), body);\n return c.json(app);\n });\n\n // Delete application\n applications.delete('/:id', async (c) => {\n await mdm.apps.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Activate application\n applications.post('/:id/activate', async (c) => {\n const app = await mdm.apps.activate(c.req.param('id'));\n return c.json(app);\n });\n\n // Deactivate application\n applications.post('/:id/deactivate', async (c) => {\n const app = await mdm.apps.deactivate(c.req.param('id'));\n return c.json(app);\n });\n\n // Deploy application\n applications.post('/:packageName/deploy', async (c) => {\n const body = await c.req.json<{\n devices?: string[];\n policies?: string[];\n groups?: string[];\n }>();\n await mdm.apps.deploy(c.req.param('packageName'), body);\n return c.json({ status: 'ok', message: 'Deployment initiated' });\n });\n\n // Install app on device\n applications.post('/:packageName/install/:deviceId', async (c) => {\n const version = c.req.query('version');\n const command = await mdm.apps.installOnDevice(\n c.req.param('packageName'),\n c.req.param('deviceId'),\n version\n );\n return c.json(command, 201);\n });\n\n // Uninstall app from device\n applications.post('/:packageName/uninstall/:deviceId', async (c) => {\n const command = await mdm.apps.uninstallFromDevice(\n c.req.param('packageName'),\n c.req.param('deviceId')\n );\n return c.json(command, 201);\n });\n\n app.route('/applications', applications);\n }\n\n // ============================================\n // Group Routes\n // ============================================\n\n if (routes.groups) {\n const groups = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n groups.use('/*', adminAuth);\n }\n\n // List groups\n groups.get('/', async (c) => {\n const result = await mdm.groups.list();\n return c.json({ groups: result });\n });\n\n // Get group\n groups.get('/:id', async (c) => {\n const group = await mdm.groups.get(c.req.param('id'));\n if (!group) {\n throw new HTTPException(404, { message: 'Group not found' });\n }\n return c.json(group);\n });\n\n // Create group\n groups.post('/', async (c) => {\n const body = await c.req.json<CreateGroupInput>();\n const group = await mdm.groups.create(body);\n return c.json(group, 201);\n });\n\n // Update group\n groups.patch('/:id', async (c) => {\n const body = await c.req.json<UpdateGroupInput>();\n const group = await mdm.groups.update(c.req.param('id'), body);\n return c.json(group);\n });\n\n // Delete group\n groups.delete('/:id', async (c) => {\n await mdm.groups.delete(c.req.param('id'));\n return c.json({ status: 'ok' });\n });\n\n // Get devices in group\n groups.get('/:id/devices', async (c) => {\n const devices = await mdm.groups.getDevices(c.req.param('id'));\n return c.json({ devices });\n });\n\n // Add device to group\n groups.post('/:id/devices', async (c) => {\n const { deviceId } = await c.req.json<{ deviceId: string }>();\n await mdm.groups.addDevice(c.req.param('id'), deviceId);\n return c.json({ status: 'ok' });\n });\n\n // Remove device from group\n groups.delete('/:id/devices/:deviceId', async (c) => {\n await mdm.groups.removeDevice(c.req.param('id'), c.req.param('deviceId'));\n return c.json({ status: 'ok' });\n });\n\n // Get child groups\n groups.get('/:id/children', async (c) => {\n const children = await mdm.groups.getChildren(c.req.param('id'));\n return c.json({ groups: children });\n });\n\n app.route('/groups', groups);\n }\n\n // ============================================\n // Command Routes\n // ============================================\n\n if (routes.commands) {\n const commands = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n commands.use('/*', adminAuth);\n }\n\n // List commands\n commands.get('/', async (c) => {\n const filter: CommandFilter = {\n deviceId: c.req.query('deviceId'),\n status: c.req.query('status') as any,\n type: c.req.query('type') as any,\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.commands.list(filter);\n return c.json({ commands: result });\n });\n\n // Get command\n commands.get('/:id', async (c) => {\n const command = await mdm.commands.get(c.req.param('id'));\n if (!command) {\n throw new HTTPException(404, { message: 'Command not found' });\n }\n return c.json(command);\n });\n\n // Send command\n commands.post('/', async (c) => {\n const body = await c.req.json<SendCommandInput>();\n const command = await mdm.commands.send(body);\n return c.json(command, 201);\n });\n\n // Cancel command\n commands.post('/:id/cancel', async (c) => {\n const command = await mdm.commands.cancel(c.req.param('id'));\n return c.json(command);\n });\n\n app.route('/commands', commands);\n }\n\n // ============================================\n // Event Routes\n // ============================================\n\n if (routes.events) {\n const events = new Hono<MDMEnv>();\n\n if (options.enableAuth) {\n events.use('/*', adminAuth);\n }\n\n // List events\n events.get('/', async (c) => {\n const filter = {\n deviceId: c.req.query('deviceId'),\n type: c.req.query('type') as any,\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : undefined,\n offset: c.req.query('offset') ? parseInt(c.req.query('offset')!) : undefined,\n };\n\n const result = await mdm.db.listEvents(filter);\n return c.json({ events: result });\n });\n\n app.route('/events', events);\n }\n\n // ============================================\n // Health Check\n // ============================================\n\n app.get('/health', (c) => {\n return c.json({\n status: 'ok',\n version: '0.1.0',\n timestamp: new Date().toISOString(),\n });\n });\n\n return app;\n}\n"],"mappings":"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","names":["app"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmdm/hono",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Hono framework adapter for OpenMDM",
5
5
  "author": "OpenMDM Contributors",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  "src"
20
20
  ],
21
21
  "dependencies": {
22
- "@openmdm/core": "0.2.0"
22
+ "@openmdm/core": "0.3.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "hono": "^4.0.0",
package/src/index.ts CHANGED
@@ -224,9 +224,17 @@ export function honoAdapter(
224
224
  // Return pending commands for the device
225
225
  const pendingCommands = await mdm.commands.getPending(deviceId);
226
226
 
227
+ // Get current policy if device has one
228
+ const device = await mdm.devices.get(deviceId);
229
+ let policyUpdate = null;
230
+ if (device?.policyId) {
231
+ policyUpdate = await mdm.policies.get(device.policyId);
232
+ }
233
+
227
234
  return c.json({
228
- status: 'ok',
229
- commands: pendingCommands,
235
+ success: true,
236
+ pendingCommands: pendingCommands,
237
+ policyUpdate: policyUpdate,
230
238
  });
231
239
  });
232
240