@molecule/api-resource-firmware 1.0.0 → 1.0.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/README.md +484 -0
- package/package.json +14 -8
package/README.md
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:49:12.273Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/api-resource-firmware
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
`@molecule/api-resource-firmware` — owner-scoped firmware versions
|
|
16
|
+
and OTA rollouts.
|
|
17
|
+
|
|
18
|
+
- Versions follow a draft → published → deprecated lifecycle.
|
|
19
|
+
- Rollouts target an explicit `device_ids[]` list, a `fleet_id`, or
|
|
20
|
+
both. The intersection with owner-scoped devices is what actually
|
|
21
|
+
gets enrolled.
|
|
22
|
+
- Per-device `firmware_update_tasks` rows are materialized and a
|
|
23
|
+
matching `device_commands` row with `firmware_update` payload is
|
|
24
|
+
created. Best-effort realtime broadcasts go out on
|
|
25
|
+
`firmware:{deviceId}` and `commands:{deviceId}`.
|
|
26
|
+
- The device reports back via a token-authenticated status endpoint;
|
|
27
|
+
the resource updates the rollout's completed/failed counters and
|
|
28
|
+
bumps the device's `firmware_version` on success.
|
|
29
|
+
|
|
30
|
+
Extracted from the iot-device-manager flagship.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import express from 'express'
|
|
36
|
+
import { createFirmwareRouter, type DeviceTokenMiddleware } from '@molecule/api-resource-firmware'
|
|
37
|
+
|
|
38
|
+
// Device-auth implementations vary per deployment (token, mTLS, JWT, …),
|
|
39
|
+
// so the status-report endpoint takes a caller-supplied authorizer. On
|
|
40
|
+
// success it MUST set `res.locals.deviceAuth = { deviceId, ownerId }`;
|
|
41
|
+
// on failure it responds 401.
|
|
42
|
+
const requireDeviceToken: DeviceTokenMiddleware = async (req, res, next) => {
|
|
43
|
+
const device = await verifyDeviceToken(req.header('authorization'))
|
|
44
|
+
if (!device) {
|
|
45
|
+
res.sendStatus(401)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
res.locals.deviceAuth = { deviceId: device.id, ownerId: device.ownerId }
|
|
49
|
+
next()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const app = express()
|
|
53
|
+
app.use('/api/firmware', createFirmwareRouter({ requireDeviceToken }))
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Type
|
|
57
|
+
|
|
58
|
+
`resource`
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
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
|
|
64
|
+
npm install -D @types/express
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
### Interfaces
|
|
70
|
+
|
|
71
|
+
#### `FirmwareRolloutRow`
|
|
72
|
+
|
|
73
|
+
Database row representing a firmware rollout targeting a fleet or set of devices.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
interface FirmwareRolloutRow {
|
|
77
|
+
id: string
|
|
78
|
+
owner_id: string
|
|
79
|
+
firmware_id: string
|
|
80
|
+
fleet_id: string | null
|
|
81
|
+
device_ids: unknown
|
|
82
|
+
strategy: RolloutStrategy
|
|
83
|
+
status: RolloutStatus
|
|
84
|
+
target_count: number
|
|
85
|
+
completed_count: number
|
|
86
|
+
failed_count: number
|
|
87
|
+
progress_percent: number
|
|
88
|
+
created_at: string | Date
|
|
89
|
+
updated_at: string | Date
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `FirmwareUpdateTaskRow`
|
|
94
|
+
|
|
95
|
+
Database row representing a single device's update task within a rollout.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface FirmwareUpdateTaskRow {
|
|
99
|
+
id: string
|
|
100
|
+
rollout_id: string
|
|
101
|
+
firmware_id: string
|
|
102
|
+
device_id: string
|
|
103
|
+
status: RolloutTaskStatus
|
|
104
|
+
error_message: string | null
|
|
105
|
+
completed_at: string | Date | null
|
|
106
|
+
created_at: string | Date
|
|
107
|
+
updated_at: string | Date
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `FirmwareVersionRow`
|
|
112
|
+
|
|
113
|
+
Database row representing a firmware version artifact and its metadata.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface FirmwareVersionRow {
|
|
117
|
+
id: string
|
|
118
|
+
owner_id: string
|
|
119
|
+
version: string
|
|
120
|
+
device_type: string
|
|
121
|
+
release_notes: string
|
|
122
|
+
download_url: string | null
|
|
123
|
+
checksum: string | null
|
|
124
|
+
file_size: number
|
|
125
|
+
status: FirmwareStatus
|
|
126
|
+
released_at: string | Date | null
|
|
127
|
+
created_at: string | Date
|
|
128
|
+
updated_at: string | Date
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Types
|
|
133
|
+
|
|
134
|
+
#### `DeviceTokenMiddleware`
|
|
135
|
+
|
|
136
|
+
Caller-supplied device-token authorization. Should set
|
|
137
|
+
`res.locals.deviceAuth = { deviceId, ownerId }` on success or 401 on
|
|
138
|
+
failure.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
type DeviceTokenMiddleware = RequestHandler
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### `FirmwareStatus`
|
|
145
|
+
|
|
146
|
+
Lifecycle state of a firmware version.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
type FirmwareStatus = 'draft' | 'published' | 'deprecated'
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### `RolloutStatus`
|
|
153
|
+
|
|
154
|
+
Current state of a firmware rollout operation.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
type RolloutStatus = 'pending' | 'active' | 'completed' | 'failed' | 'canceled'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### `RolloutStrategy`
|
|
161
|
+
|
|
162
|
+
Deployment strategy used when rolling out a firmware version to devices.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
type RolloutStrategy = 'immediate' | 'canary' | 'gradual'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `RolloutTaskStatus`
|
|
169
|
+
|
|
170
|
+
Current state of an individual device update task within a rollout.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
type RolloutTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Functions
|
|
177
|
+
|
|
178
|
+
#### `createFirmwareForOwner(userId, input)`
|
|
179
|
+
|
|
180
|
+
Create a draft firmware version.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
function createFirmwareForOwner(
|
|
184
|
+
userId: string,
|
|
185
|
+
input: {
|
|
186
|
+
version: string
|
|
187
|
+
device_type: string
|
|
188
|
+
release_notes?: string
|
|
189
|
+
download_url?: string | null
|
|
190
|
+
checksum?: string | null
|
|
191
|
+
file_size?: number
|
|
192
|
+
},
|
|
193
|
+
): Promise<FirmwareVersionRow | null>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### `createFirmwareRouter(opts)`
|
|
197
|
+
|
|
198
|
+
Build the firmware router.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
function createFirmwareRouter(opts: { requireDeviceToken: DeviceTokenMiddleware }): Router
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### `createRolloutForOwner(userId, input)`
|
|
205
|
+
|
|
206
|
+
Create a rollout, materialize per-device tasks + `firmware_update`
|
|
207
|
+
device commands, and best-effort broadcast realtime notifications.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
function createRolloutForOwner(
|
|
211
|
+
userId: string,
|
|
212
|
+
input: {
|
|
213
|
+
firmware_id: string
|
|
214
|
+
device_ids?: string[]
|
|
215
|
+
fleet_id?: string | null
|
|
216
|
+
strategy?: RolloutStrategy
|
|
217
|
+
},
|
|
218
|
+
): Promise<
|
|
219
|
+
| { ok: true; rollout: FirmwareRolloutRow; targets: string[] }
|
|
220
|
+
| { ok: false; reason: 'not_found' | 'not_published' | 'no_targets' }
|
|
221
|
+
>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### `getFirmwareForOwner(userId, id)`
|
|
225
|
+
|
|
226
|
+
Owner-scoped firmware read — null when missing or not owned.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
function getFirmwareForOwner(userId: string, id: string): Promise<FirmwareVersionRow | null>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### `isUuid(value)`
|
|
233
|
+
|
|
234
|
+
Whether a string is a syntactically valid UUID.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
function isUuid(value: string): boolean
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### `listFirmwareForOwner(userId, filters?)`
|
|
241
|
+
|
|
242
|
+
Owner-scoped firmware list.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
function listFirmwareForOwner(
|
|
246
|
+
userId: string,
|
|
247
|
+
filters?: { device_type?: string; status?: string; page?: number; limit?: number },
|
|
248
|
+
): Promise<FirmwareVersionRow[]>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### `listRolloutsForOwner(userId, filters?)`
|
|
252
|
+
|
|
253
|
+
Owner-scoped rollout list.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
function listRolloutsForOwner(
|
|
257
|
+
userId: string,
|
|
258
|
+
filters?: { firmware_id?: string; status?: string; page?: number; limit?: number },
|
|
259
|
+
): Promise<FirmwareRolloutRow[]>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### `publishFirmwareForOwner(userId, id)`
|
|
263
|
+
|
|
264
|
+
Flip a firmware version to published + stamp `released_at`.
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
function publishFirmwareForOwner(userId: string, id: string): Promise<FirmwareVersionRow | null>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### `recordRolloutDeviceStatus(opts)`
|
|
271
|
+
|
|
272
|
+
Record a per-device task status report. Updates the rollout's
|
|
273
|
+
completed/failed counters + progress percent; on success bumps the
|
|
274
|
+
device's `firmware_version` to the new release.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
function recordRolloutDeviceStatus(opts: {
|
|
278
|
+
rolloutId: string
|
|
279
|
+
deviceId: string
|
|
280
|
+
ownerId: string
|
|
281
|
+
status: RolloutTaskStatus
|
|
282
|
+
errorMessage?: string | null
|
|
283
|
+
}): Promise<{ ok: true } | { ok: false; reason: 'task_not_found' }>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### `updateFirmwareForOwner(userId, id, patch)`
|
|
287
|
+
|
|
288
|
+
Patch a firmware version owned by the user.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
function updateFirmwareForOwner(
|
|
292
|
+
userId: string,
|
|
293
|
+
id: string,
|
|
294
|
+
patch: Record<string, unknown>,
|
|
295
|
+
): Promise<FirmwareVersionRow | null>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Constants
|
|
299
|
+
|
|
300
|
+
#### `createFirmwareSchema`
|
|
301
|
+
|
|
302
|
+
Validator for creating a draft firmware version.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const createFirmwareSchema: z.ZodObject<
|
|
306
|
+
{
|
|
307
|
+
version: z.ZodString
|
|
308
|
+
device_type: z.ZodString
|
|
309
|
+
release_notes: z.ZodOptional<z.ZodString>
|
|
310
|
+
download_url: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
311
|
+
checksum: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
312
|
+
file_size: z.ZodOptional<z.ZodCoercedNumber<unknown>>
|
|
313
|
+
},
|
|
314
|
+
z.core.$strip
|
|
315
|
+
>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `createRolloutSchema`
|
|
319
|
+
|
|
320
|
+
Validator for creating a rollout.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const createRolloutSchema: z.ZodObject<
|
|
324
|
+
{
|
|
325
|
+
firmware_id: z.ZodString
|
|
326
|
+
device_ids: z.ZodOptional<z.ZodArray<z.ZodString>>
|
|
327
|
+
fleet_id: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
328
|
+
strategy: z.ZodOptional<
|
|
329
|
+
z.ZodEnum<{ immediate: 'immediate'; canary: 'canary'; gradual: 'gradual' }>
|
|
330
|
+
>
|
|
331
|
+
},
|
|
332
|
+
z.core.$strip
|
|
333
|
+
>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### `firmwareStatusSchema`
|
|
337
|
+
|
|
338
|
+
Allowed lifecycle states for a firmware version.
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
const firmwareStatusSchema: z.ZodEnum<{
|
|
342
|
+
draft: 'draft'
|
|
343
|
+
published: 'published'
|
|
344
|
+
deprecated: 'deprecated'
|
|
345
|
+
}>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### `listFirmwareQuerySchema`
|
|
349
|
+
|
|
350
|
+
Validator for the firmware-version list query params.
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const listFirmwareQuerySchema: z.ZodObject<
|
|
354
|
+
{
|
|
355
|
+
device_type: z.ZodOptional<z.ZodString>
|
|
356
|
+
status: z.ZodOptional<
|
|
357
|
+
z.ZodEnum<{ draft: 'draft'; published: 'published'; deprecated: 'deprecated' }>
|
|
358
|
+
>
|
|
359
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>
|
|
360
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>
|
|
361
|
+
},
|
|
362
|
+
z.core.$strip
|
|
363
|
+
>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### `listRolloutsQuerySchema`
|
|
367
|
+
|
|
368
|
+
Validator for the rollout-list query params.
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const listRolloutsQuerySchema: z.ZodObject<
|
|
372
|
+
{
|
|
373
|
+
firmware_id: z.ZodOptional<z.ZodString>
|
|
374
|
+
status: z.ZodOptional<
|
|
375
|
+
z.ZodEnum<{
|
|
376
|
+
pending: 'pending'
|
|
377
|
+
completed: 'completed'
|
|
378
|
+
failed: 'failed'
|
|
379
|
+
active: 'active'
|
|
380
|
+
canceled: 'canceled'
|
|
381
|
+
}>
|
|
382
|
+
>
|
|
383
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>
|
|
384
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>
|
|
385
|
+
},
|
|
386
|
+
z.core.$strip
|
|
387
|
+
>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### `rolloutDeviceStatusSchema`
|
|
391
|
+
|
|
392
|
+
Validator for a per-device rollout status report.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
const rolloutDeviceStatusSchema: z.ZodObject<
|
|
396
|
+
{
|
|
397
|
+
status: z.ZodEnum<{
|
|
398
|
+
pending: 'pending'
|
|
399
|
+
in_progress: 'in_progress'
|
|
400
|
+
completed: 'completed'
|
|
401
|
+
failed: 'failed'
|
|
402
|
+
}>
|
|
403
|
+
error_message: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
404
|
+
},
|
|
405
|
+
z.core.$strip
|
|
406
|
+
>
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### `rolloutStatusSchema`
|
|
410
|
+
|
|
411
|
+
Allowed progress states for a firmware rollout.
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const rolloutStatusSchema: z.ZodEnum<{
|
|
415
|
+
pending: 'pending'
|
|
416
|
+
completed: 'completed'
|
|
417
|
+
failed: 'failed'
|
|
418
|
+
active: 'active'
|
|
419
|
+
canceled: 'canceled'
|
|
420
|
+
}>
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
#### `rolloutStrategySchema`
|
|
424
|
+
|
|
425
|
+
Allowed rollout delivery strategies.
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
const rolloutStrategySchema: z.ZodEnum<{
|
|
429
|
+
immediate: 'immediate'
|
|
430
|
+
canary: 'canary'
|
|
431
|
+
gradual: 'gradual'
|
|
432
|
+
}>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
#### `updateFirmwareSchema`
|
|
436
|
+
|
|
437
|
+
Validator for patching a firmware version (release notes, status, etc).
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const updateFirmwareSchema: z.ZodObject<
|
|
441
|
+
{
|
|
442
|
+
release_notes: z.ZodOptional<z.ZodString>
|
|
443
|
+
download_url: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
444
|
+
checksum: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
445
|
+
file_size: z.ZodOptional<z.ZodCoercedNumber<unknown>>
|
|
446
|
+
status: z.ZodOptional<
|
|
447
|
+
z.ZodEnum<{ draft: 'draft'; published: 'published'; deprecated: 'deprecated' }>
|
|
448
|
+
>
|
|
449
|
+
},
|
|
450
|
+
z.core.$strip
|
|
451
|
+
>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Injection Notes
|
|
455
|
+
|
|
456
|
+
### Requirements
|
|
457
|
+
|
|
458
|
+
Peer dependencies:
|
|
459
|
+
|
|
460
|
+
- `@molecule/api-bonds-default-express` ^1.0.1
|
|
461
|
+
- `@molecule/api-database` ^1.0.1
|
|
462
|
+
- `@molecule/api-i18n` ^1.0.1
|
|
463
|
+
- `@molecule/api-logger` ^1.0.1
|
|
464
|
+
- `@molecule/api-middleware-validation` ^1.0.1
|
|
465
|
+
- `@molecule/api-realtime` ^1.0.1
|
|
466
|
+
- `express` ^5.0.0
|
|
467
|
+
- `zod` ^4.0.0
|
|
468
|
+
|
|
469
|
+
### Runtime Dependencies
|
|
470
|
+
|
|
471
|
+
- `@molecule/api-bonds-default-express`
|
|
472
|
+
- `@molecule/api-database`
|
|
473
|
+
- `@molecule/api-i18n`
|
|
474
|
+
- `@molecule/api-logger`
|
|
475
|
+
- `@molecule/api-middleware-validation`
|
|
476
|
+
- `@molecule/api-realtime`
|
|
477
|
+
- `express`
|
|
478
|
+
- `zod`
|
|
479
|
+
|
|
480
|
+
The schema in `__setup__/firmware.sql` creates `firmware_versions`,
|
|
481
|
+
`firmware_rollouts`, and `firmware_update_tasks`. The resource also
|
|
482
|
+
reads/writes `iot_devices`, `fleets`, `fleet_memberships`,
|
|
483
|
+
`device_commands`, and `device_alerts` — those tables are owned by
|
|
484
|
+
the iot-device-manager template.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-resource-firmware",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Owner-scoped firmware versions + OTA rollouts: draft/publish/deprecate, per-device update tasks, realtime command dispatch, device-token-authenticated status reporting. Extracted from iot-device-manager flagship.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
23
24
|
"molecule",
|
|
@@ -28,6 +29,11 @@
|
|
|
28
29
|
"resource"
|
|
29
30
|
],
|
|
30
31
|
"license": "Apache-2.0",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/molecule-dev/molecule.git",
|
|
35
|
+
"directory": "packages/api/resources/firmware"
|
|
36
|
+
},
|
|
31
37
|
"devDependencies": {
|
|
32
38
|
"@types/express": "5.0.6",
|
|
33
39
|
"@types/node": "26.1.2",
|
|
@@ -37,12 +43,12 @@
|
|
|
37
43
|
"zod": "4.4.3"
|
|
38
44
|
},
|
|
39
45
|
"peerDependencies": {
|
|
40
|
-
"@molecule/api-bonds-default-express": "^1.0.
|
|
41
|
-
"@molecule/api-database": "^1.0.
|
|
42
|
-
"@molecule/api-i18n": "^1.0.
|
|
43
|
-
"@molecule/api-logger": "^1.0.
|
|
44
|
-
"@molecule/api-middleware-validation": "^1.0.
|
|
45
|
-
"@molecule/api-realtime": "^1.0.
|
|
46
|
+
"@molecule/api-bonds-default-express": "^1.0.1",
|
|
47
|
+
"@molecule/api-database": "^1.0.1",
|
|
48
|
+
"@molecule/api-i18n": "^1.0.1",
|
|
49
|
+
"@molecule/api-logger": "^1.0.1",
|
|
50
|
+
"@molecule/api-middleware-validation": "^1.0.1",
|
|
51
|
+
"@molecule/api-realtime": "^1.0.1",
|
|
46
52
|
"express": "^5.0.0",
|
|
47
53
|
"zod": "^4.0.0"
|
|
48
54
|
}
|