← All @molecule/* packages · App templates
@molecule/api-resource-firmwareAPI resource · resource-firmware · API (Node) · v1.0.1 · Apache-2.0
Firmware versions + OTA rollouts
npm install @molecule/api-resource-firmware@molecule/api-resource-firmware is an API resource: the routes, validation and storage for resource-firmware, built on the database and auth cores so it runs on whichever providers your app has bonded.
import express from 'express'
import { createFirmwareRouter, type DeviceTokenMiddleware } from '@molecule/api-resource-firmware'
// Device-auth implementations vary per deployment (token, mTLS, JWT, …),
// so the status-report endpoint takes a caller-supplied authorizer. On
// success it MUST set `res.locals.deviceAuth = { deviceId, ownerId }`;
// on failure it responds 401.
const requireDeviceToken: DeviceTokenMiddleware = async (req, res, next) => {
const device = await verifyDeviceToken(req.header('authorization'))
if (!device) {
res.sendStatus(401)
return
}
res.locals.deviceAuth = { deviceId: device.id, ownerId: device.ownerId }
next()
}
const app = express()
app.use('/api/firmware', createFirmwareRouter({ requireDeviceToken }))Works with: @molecule/api-bonds-default-express, @molecule/api-database, @molecule/api-i18n, @molecule/api-logger, @molecule/api-middleware-validation, @molecule/api-realtime
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
@molecule/api-resource-firmware — owner-scoped firmware versions
and OTA rollouts.
device_ids[] list, a fleet_id, or
both. The intersection with owner-scoped devices is what actually
gets enrolled.firmware_update_tasks rows are materialized and a
matching device_commands row with firmware_update payload is
created. Best-effort realtime broadcasts go out on
firmware:{deviceId} and commands:{deviceId}.firmware_version on success.Extracted from the iot-device-manager flagship.
import express from 'express'
import { createFirmwareRouter, type DeviceTokenMiddleware } from '@molecule/api-resource-firmware'
// Device-auth implementations vary per deployment (token, mTLS, JWT, …),
// so the status-report endpoint takes a caller-supplied authorizer. On
// success it MUST set `res.locals.deviceAuth = { deviceId, ownerId }`;
// on failure it responds 401.
const requireDeviceToken: DeviceTokenMiddleware = async (req, res, next) => {
const device = await verifyDeviceToken(req.header('authorization'))
if (!device) {
res.sendStatus(401)
return
}
res.locals.deviceAuth = { deviceId: device.id, ownerId: device.ownerId }
next()
}
const app = express()
app.use('/api/firmware', createFirmwareRouter({ requireDeviceToken }))
resource
npm install @molecule/api-resource-firmware @molecule/api-bonds-default-express @molecule/api-database @molecule/api-i18n @molecule/api-logger @molecule/api-middleware-validation @molecule/api-realtime express zod
npm install -D @types/express
FirmwareRolloutRowDatabase row representing a firmware rollout targeting a fleet or set of devices.
interface FirmwareRolloutRow {
id: string
owner_id: string
firmware_id: string
fleet_id: string | null
device_ids: unknown
strategy: RolloutStrategy
status: RolloutStatus
target_count: number
completed_count: number
failed_count: number
progress_percent: number
created_at: string | Date
updated_at: string | Date
}
FirmwareUpdateTaskRowDatabase row representing a single device's update task within a rollout.
interface FirmwareUpdateTaskRow {
id: string
rollout_id: string
firmware_id: string
device_id: string
status: RolloutTaskStatus
error_message: string | null
completed_at: string | Date | null
created_at: string | Date
updated_at: string | Date
}
FirmwareVersionRowDatabase row representing a firmware version artifact and its metadata.
interface FirmwareVersionRow {
id: string
owner_id: string
version: string
device_type: string
release_notes: string
download_url: string | null
checksum: string | null
file_size: number
status: FirmwareStatus
released_at: string | Date | null
created_at: string | Date
updated_at: string | Date
}
DeviceTokenMiddlewareCaller-supplied device-token authorization. Should set
res.locals.deviceAuth = { deviceId, ownerId } on success or 401 on
failure.
type DeviceTokenMiddleware = RequestHandler
FirmwareStatusLifecycle state of a firmware version.
type FirmwareStatus = 'draft' | 'published' | 'deprecated'
RolloutStatusCurrent state of a firmware rollout operation.
type RolloutStatus = 'pending' | 'active' | 'completed' | 'failed' | 'canceled'
RolloutStrategyDeployment strategy used when rolling out a firmware version to devices.
type RolloutStrategy = 'immediate' | 'canary' | 'gradual'
RolloutTaskStatusCurrent state of an individual device update task within a rollout.
type RolloutTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed'
createFirmwareForOwner(userId, input)Create a draft firmware version.
function createFirmwareForOwner(
userId: string,
input: {
version: string
device_type: string
release_notes?: string
download_url?: string | null
checksum?: string | null
file_size?: number
},
): Promise<FirmwareVersionRow | null>
createFirmwareRouter(opts)Build the firmware router.
function createFirmwareRouter(opts: { requireDeviceToken: DeviceTokenMiddleware }): Router
createRolloutForOwner(userId, input)Create a rollout, materialize per-device tasks + firmware_update
device commands, and best-effort broadcast realtime notifications.
function createRolloutForOwner(
userId: string,
input: {
firmware_id: string
device_ids?: string[]
fleet_id?: string | null
strategy?: RolloutStrategy
},
): Promise<
| { ok: true; rollout: FirmwareRolloutRow; targets: string[] }
| { ok: false; reason: 'not_found' | 'not_published' | 'no_targets' }
>
getFirmwareForOwner(userId, id)Owner-scoped firmware read — null when missing or not owned.
function getFirmwareForOwner(userId: string, id: string): Promise<FirmwareVersionRow | null>
isUuid(value)Whether a string is a syntactically valid UUID.
function isUuid(value: string): boolean
listFirmwareForOwner(userId, filters?)Owner-scoped firmware list.
function listFirmwareForOwner(
userId: string,
filters?: { device_type?: string; status?: string; page?: number; limit?: number },
): Promise<FirmwareVersionRow[]>
listRolloutsForOwner(userId, filters?)Owner-scoped rollout list.
function listRolloutsForOwner(
userId: string,
filters?: { firmware_id?: string; status?: string; page?: number; limit?: number },
): Promise<FirmwareRolloutRow[]>
publishFirmwareForOwner(userId, id)Flip a firmware version to published + stamp released_at.
function publishFirmwareForOwner(userId: string, id: string): Promise<FirmwareVersionRow | null>
recordRolloutDeviceStatus(opts)Record a per-device task status report. Updates the rollout's
completed/failed counters + progress percent; on success bumps the
device's firmware_version to the new release.
function recordRolloutDeviceStatus(opts: {
rolloutId: string
deviceId: string
ownerId: string
status: RolloutTaskStatus
errorMessage?: string | null
}): Promise<{ ok: true } | { ok: false; reason: 'task_not_found' }>
updateFirmwareForOwner(userId, id, patch)Patch a firmware version owned by the user.
function updateFirmwareForOwner(
userId: string,
id: string,
patch: Record<string, unknown>,
): Promise<FirmwareVersionRow | null>
createFirmwareSchemaValidator for creating a draft firmware version.
const createFirmwareSchema: z.ZodObject<
{
version: z.ZodString
device_type: z.ZodString
release_notes: z.ZodOptional<z.ZodString>
download_url: z.ZodOptional<z.ZodNullable<z.ZodString>>
checksum: z.ZodOptional<z.ZodNullable<z.ZodString>>
file_size: z.ZodOptional<z.ZodCoercedNumber<unknown>>
},
z.core.$strip
>
createRolloutSchemaValidator for creating a rollout.
const createRolloutSchema: z.ZodObject<
{
firmware_id: z.ZodString
device_ids: z.ZodOptional<z.ZodArray<z.ZodString>>
fleet_id: z.ZodOptional<z.ZodNullable<z.ZodString>>
strategy: z.ZodOptional<
z.ZodEnum<{ immediate: 'immediate'; canary: 'canary'; gradual: 'gradual' }>
>
},
z.core.$strip
>
firmwareStatusSchemaAllowed lifecycle states for a firmware version.
const firmwareStatusSchema: z.ZodEnum<{
draft: 'draft'
published: 'published'
deprecated: 'deprecated'
}>
listFirmwareQuerySchemaValidator for the firmware-version list query params.
const listFirmwareQuerySchema: z.ZodObject<
{
device_type: z.ZodOptional<z.ZodString>
status: z.ZodOptional<
z.ZodEnum<{ draft: 'draft'; published: 'published'; deprecated: 'deprecated' }>
>
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>
},
z.core.$strip
>
listRolloutsQuerySchemaValidator for the rollout-list query params.
const listRolloutsQuerySchema: z.ZodObject<
{
firmware_id: z.ZodOptional<z.ZodString>
status: z.ZodOptional<
z.ZodEnum<{
pending: 'pending'
completed: 'completed'
failed: 'failed'
active: 'active'
canceled: 'canceled'
}>
>
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>
},
z.core.$strip
>
rolloutDeviceStatusSchemaValidator for a per-device rollout status report.
const rolloutDeviceStatusSchema: z.ZodObject<
{
status: z.ZodEnum<{
pending: 'pending'
in_progress: 'in_progress'
completed: 'completed'
failed: 'failed'
}>
error_message: z.ZodOptional<z.ZodNullable<z.ZodString>>
},
z.core.$strip
>
rolloutStatusSchemaAllowed progress states for a firmware rollout.
const rolloutStatusSchema: z.ZodEnum<{
pending: 'pending'
completed: 'completed'
failed: 'failed'
active: 'active'
canceled: 'canceled'
}>
rolloutStrategySchemaAllowed rollout delivery strategies.
const rolloutStrategySchema: z.ZodEnum<{
immediate: 'immediate'
canary: 'canary'
gradual: 'gradual'
}>
updateFirmwareSchemaValidator for patching a firmware version (release notes, status, etc).
const updateFirmwareSchema: z.ZodObject<
{
release_notes: z.ZodOptional<z.ZodString>
download_url: z.ZodOptional<z.ZodNullable<z.ZodString>>
checksum: z.ZodOptional<z.ZodNullable<z.ZodString>>
file_size: z.ZodOptional<z.ZodCoercedNumber<unknown>>
status: z.ZodOptional<
z.ZodEnum<{ draft: 'draft'; published: 'published'; deprecated: 'deprecated' }>
>
},
z.core.$strip
>
Peer dependencies:
@molecule/api-bonds-default-express ^1.0.1@molecule/api-database ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-logger ^1.0.1@molecule/api-middleware-validation ^1.0.1@molecule/api-realtime ^1.0.1express ^5.0.0zod ^4.0.0@molecule/api-bonds-default-express@molecule/api-database@molecule/api-i18n@molecule/api-logger@molecule/api-middleware-validation@molecule/api-realtimeexpresszodThe schema in __setup__/firmware.sql creates firmware_versions,
firmware_rollouts, and firmware_update_tasks. The resource also
reads/writes iot_devices, fleets, fleet_memberships,
device_commands, and device_alerts — those tables are owned by
the iot-device-manager template.