@espressif/rainmaker-admin-sdk 1.0.0 → 1.1.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/dist/cjs/entries/ESPRMAdminOTAImage.cjs +1 -0
  3. package/dist/cjs/entries/ESPRMAdminOTAJob.cjs +2 -1
  4. package/dist/cjs/index.cjs +3 -1
  5. package/dist/cjs/methods/ESPRMAdminOTAImage/ArchiveImage.cjs +10 -1
  6. package/dist/cjs/methods/ESPRMAdminOTAImage/DeleteImage.cjs +4 -3
  7. package/dist/cjs/methods/ESPRMAdminOTAImage/DeletePackage.cjs +25 -0
  8. package/dist/cjs/methods/ESPRMAdminOTAImage/deleteParams.cjs +21 -0
  9. package/dist/cjs/methods/ESPRMAdminOTAJob/ArchiveJob.cjs +24 -0
  10. package/dist/cjs/methods/ESPRMAdminOTAJob/{DeleteJob.cjs → CancelJob.cjs} +4 -4
  11. package/dist/cjs/methods/ESPRMAdminOTAJob/RetriggerJob.cjs +2 -2
  12. package/dist/cjs/services/ESPRMAPIManager.cjs +10 -2
  13. package/dist/cjs/utils/constants.cjs +2 -1
  14. package/dist/cjs/utils/error/errorMessages.cjs +1 -0
  15. package/dist/esm/entries/ESPRMAdminOTAImage.js +1 -0
  16. package/dist/esm/entries/ESPRMAdminOTAJob.js +2 -1
  17. package/dist/esm/index.js +3 -1
  18. package/dist/esm/methods/ESPRMAdminOTAImage/ArchiveImage.js +10 -1
  19. package/dist/esm/methods/ESPRMAdminOTAImage/DeleteImage.js +4 -3
  20. package/dist/esm/methods/ESPRMAdminOTAImage/DeletePackage.js +23 -0
  21. package/dist/esm/methods/ESPRMAdminOTAImage/deleteParams.js +19 -0
  22. package/dist/esm/methods/ESPRMAdminOTAJob/ArchiveJob.js +22 -0
  23. package/dist/esm/methods/ESPRMAdminOTAJob/{DeleteJob.js → CancelJob.js} +4 -4
  24. package/dist/esm/methods/ESPRMAdminOTAJob/RetriggerJob.js +2 -2
  25. package/dist/esm/services/ESPRMAPIManager.js +10 -2
  26. package/dist/esm/utils/constants.js +2 -1
  27. package/dist/esm/utils/error/errorMessages.js +1 -0
  28. package/dist/types/methods/ESPRMAdminOTAImage/ArchiveImage.d.ts +6 -3
  29. package/dist/types/methods/ESPRMAdminOTAImage/DeleteImage.d.ts +6 -2
  30. package/dist/types/methods/ESPRMAdminOTAImage/DeletePackage.d.ts +22 -0
  31. package/dist/types/methods/ESPRMAdminOTAImage/deleteParams.d.ts +13 -0
  32. package/dist/types/methods/ESPRMAdminOTAImage/index.d.ts +1 -0
  33. package/dist/types/methods/ESPRMAdminOTAJob/ArchiveJob.d.ts +22 -0
  34. package/dist/types/methods/ESPRMAdminOTAJob/CancelJob.d.ts +21 -0
  35. package/dist/types/methods/ESPRMAdminOTAJob/RetriggerJob.d.ts +9 -5
  36. package/dist/types/methods/ESPRMAdminOTAJob/index.d.ts +2 -1
  37. package/dist/types/types/input.d.ts +1 -1
  38. package/dist/types/types/ota.d.ts +95 -10
  39. package/dist/types/types/output.d.ts +1 -1
  40. package/dist/types/types/time_series.d.ts +11 -5
  41. package/dist/types/utils/constants.d.ts +2 -1
  42. package/dist/types/utils/error/errorMessages.d.ts +1 -0
  43. package/dist/types-cjs/methods/ESPRMAdminOTAImage/ArchiveImage.d.cts +6 -3
  44. package/dist/types-cjs/methods/ESPRMAdminOTAImage/DeleteImage.d.cts +6 -2
  45. package/dist/types-cjs/methods/ESPRMAdminOTAImage/DeletePackage.d.cts +22 -0
  46. package/dist/types-cjs/methods/ESPRMAdminOTAImage/deleteParams.d.cts +13 -0
  47. package/dist/types-cjs/methods/ESPRMAdminOTAImage/index.d.cts +1 -0
  48. package/dist/types-cjs/methods/ESPRMAdminOTAJob/ArchiveJob.d.cts +22 -0
  49. package/dist/types-cjs/methods/ESPRMAdminOTAJob/CancelJob.d.cts +21 -0
  50. package/dist/types-cjs/methods/ESPRMAdminOTAJob/RetriggerJob.d.cts +9 -5
  51. package/dist/types-cjs/methods/ESPRMAdminOTAJob/index.d.cts +2 -1
  52. package/dist/types-cjs/types/input.d.cts +1 -1
  53. package/dist/types-cjs/types/ota.d.cts +95 -10
  54. package/dist/types-cjs/types/output.d.cts +1 -1
  55. package/dist/types-cjs/types/time_series.d.cts +11 -5
  56. package/dist/types-cjs/utils/constants.d.cts +2 -1
  57. package/dist/types-cjs/utils/error/errorMessages.d.cts +1 -0
  58. package/package.json +1 -1
  59. package/dist/types/methods/ESPRMAdminOTAJob/DeleteJob.d.ts +0 -17
  60. package/dist/types-cjs/methods/ESPRMAdminOTAJob/DeleteJob.d.cts +0 -17
package/CHANGELOG.md CHANGED
@@ -3,7 +3,113 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and follows the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.
5
5
 
6
- ## [Unreleased]
6
+ ## [1.1.1] - 2026-09-23
7
+
8
+ Patch release for the simple time series data endpoint. The time range
9
+ becomes optional, as the backend always allowed, and optional query
10
+ parameters that are left undefined are no longer sent as the literal text
11
+ `undefined`. No breaking changes; every existing call keeps working as before.
12
+
13
+ ### Changed
14
+
15
+ - **Simple time series data**
16
+ - `start_time` and `end_time` on `GetSimpleTimeSeriesDataParams` are now
17
+ optional, matching the backend: omitting them queries from the oldest
18
+ record up to now. Existing callers that pass both are unaffected.
19
+
20
+ ### Fixed
21
+
22
+ - **Query parameter serialisation**
23
+ - `ESPRMAPIManager.request()` no longer sends optional query parameters
24
+ that are `undefined` or `null`. Previously `URLSearchParams` turned them
25
+ into the literal text `undefined` / `null`, which the backend rejected
26
+ (for example `start_time=undefined` on `/admin/nodes/simple_tsdata`).
27
+ Numbers and booleans are stringified explicitly, and a params object
28
+ with no remaining entries produces no `?` at all.
29
+
30
+ ## [1.1.0] - 2026-09-18
31
+
32
+ OTA job and OTA image lifecycle management. Adds cancel/archive for jobs and
33
+ archive/unarchive plus delete for images, and corrects several OTA request
34
+ shapes that did not match the backend.
35
+
36
+ ### Added
37
+
38
+ - **OTA job lifecycle**
39
+ - Added `cancelJob()` on `ESPRMAdminOTAJob`, marking an in-flight job and all of
40
+ its pending nodes as cancelled. Only active jobs can be cancelled.
41
+ - Added `archiveJob()` on `ESPRMAdminOTAJob`, hiding a job from the default
42
+ listing. Only finished, cancelled or expired jobs can be archived, and only
43
+ once — archiving is one-way, so `ArchiveOTAJobRequest` deliberately carries no
44
+ `archive` flag.
45
+ - Both return the job's full updated record as `OTAJobUpdateResponse`; the
46
+ backend re-reads the job after applying the update.
47
+ - Added `archived` to `OTAJobInfo`. Present and `true` once archived; absent
48
+ rather than `false` otherwise.
49
+
50
+ - **OTA image delete**
51
+ - Added `deletePackage()` on `ESPRMAdminOTAImage` for images uploaded as part of
52
+ a package. The plain delete endpoint rejects these outright, so they could not
53
+ previously be removed through the SDK.
54
+ - Added `force_delete` to the new `DeleteOTAImageParams`, for deleting an image
55
+ still referenced by non-active OTA jobs. A reference from an *active* job is
56
+ rejected regardless of the flag.
57
+
58
+ - **OTA image listing**
59
+ - Added `all` to `GetOTAImagesParams`, returning archived and unarchived images
60
+ together. Honoured by the unfiltered listing only — the `ota_image_id`,
61
+ `image_name`, `type` and `model` lookups span both states regardless.
62
+ - Added `package` to `OTAImageInfo`, naming the archive an image was extracted
63
+ from. Images carrying it can only be removed via `deletePackage()`.
64
+
65
+ - **Errors**
66
+ - Added the `MISSING_ARCHIVE_FLAG` API-call validation code.
67
+
68
+ ### Fixed
69
+
70
+ - **`archiveImage()` sent its parameters in the request body**, which this endpoint
71
+ ignores — every call failed with "OTA Image Id is missing". Parameters are now
72
+ sent as query parameters, and `archive` is serialised as the literal `"true"` /
73
+ `"false"` the backend requires. **This method could not have worked before.**
74
+ - **`retriggerJob()` targeted the wrong endpoint and method.** It sent `PUT
75
+ admin/otajob`; it now sends `POST admin/otajob/retrigger`.
76
+
77
+ ### Changed
78
+
79
+ - **`retriggerJob()`** returns `OTAJobRetriggerResponse` (`ota_job_id`, `status`)
80
+ instead of a bare success response. Delivery is dispatched asynchronously, so a
81
+ success means the retrigger was accepted, not that any node has received it.
82
+ - **`RetriggerOTAJobRequest.node_ids` was removed.** The endpoint accepts no such
83
+ field; a retrigger always covers every node still pending.
84
+ - **`deleteImage()` now takes a `DeleteOTAImageParams` object** rather than a bare
85
+ `ota_image_id` string, matching `archiveImage()` and making room for
86
+ `force_delete`.
87
+
88
+ ### Removed
89
+
90
+ - **`deleteJob()` on `ESPRMAdminOTAJob`.** OTA jobs cannot be deleted; the method
91
+ issued a `DELETE` the backend does not implement. Use `cancelJob()` to stop an
92
+ in-flight job and `archiveJob()` to remove one from the default listing.
93
+ - **`APIEndpoints.ADMIN_OTA_JOB_ACTION`**, an alias of `ADMIN_OTA_JOB`, replaced by
94
+ `ADMIN_OTA_JOB_RETRIGGER`.
95
+
96
+ ### Deprecated
97
+
98
+ Documentation-only; no runtime behaviour changed. These fields are accepted or
99
+ returned by the SDK types but are inert against the current backend.
100
+
101
+ - `GetOTAImagesParams.fw_version` — no such filter exists on this endpoint.
102
+ - `OTAImageInfo.status` and `OTAImageInfo.timestamp` — never returned for images;
103
+ they were carried over from the OTA job type. Use `upload_timestamp`.
104
+ - `GetOTAImagesResponse.total` — never sent for images.
105
+
106
+ ### Notes
107
+
108
+ - `GetOTAImagesParams.contains` is a bool-as-string flag (`"true"`) and applies to
109
+ `image_name` only. Without it, a name lookup is an exact match rather than a
110
+ search.
111
+ - `OTAImageInfo.archived` is omitted rather than set to `false` for images that
112
+ have never been archived.
7
113
 
8
114
  ## [1.0.0] - 2026-09-07
9
115
 
@@ -13,6 +13,7 @@ require('../methods/ESPRMAdminOTAImage/ConfirmPackageUpload.cjs');
13
13
  require('../methods/ESPRMAdminOTAImage/GetImages.cjs');
14
14
  require('../methods/ESPRMAdminOTAImage/ArchiveImage.cjs');
15
15
  require('../methods/ESPRMAdminOTAImage/DeleteImage.cjs');
16
+ require('../methods/ESPRMAdminOTAImage/DeletePackage.cjs');
16
17
  var ESPRMAdminOTAImage = require('../ESPRMAdminOTAImage.cjs');
17
18
 
18
19
 
@@ -8,7 +8,8 @@
8
8
  require('../methods/ESPRMAdminOTAJob/CreateJob.cjs');
9
9
  require('../methods/ESPRMAdminOTAJob/GetJob.cjs');
10
10
  require('../methods/ESPRMAdminOTAJob/UpdateJob.cjs');
11
- require('../methods/ESPRMAdminOTAJob/DeleteJob.cjs');
11
+ require('../methods/ESPRMAdminOTAJob/CancelJob.cjs');
12
+ require('../methods/ESPRMAdminOTAJob/ArchiveJob.cjs');
12
13
  require('../methods/ESPRMAdminOTAJob/GetJobStatus.cjs');
13
14
  require('../methods/ESPRMAdminOTAJob/GetJobStatusSummary.cjs');
14
15
  require('../methods/ESPRMAdminOTAJob/RetriggerJob.cjs');
@@ -90,10 +90,12 @@ require('./methods/ESPRMAdminOTAImage/ConfirmPackageUpload.cjs');
90
90
  require('./methods/ESPRMAdminOTAImage/GetImages.cjs');
91
91
  require('./methods/ESPRMAdminOTAImage/ArchiveImage.cjs');
92
92
  require('./methods/ESPRMAdminOTAImage/DeleteImage.cjs');
93
+ require('./methods/ESPRMAdminOTAImage/DeletePackage.cjs');
93
94
  require('./methods/ESPRMAdminOTAJob/CreateJob.cjs');
94
95
  require('./methods/ESPRMAdminOTAJob/GetJob.cjs');
95
96
  require('./methods/ESPRMAdminOTAJob/UpdateJob.cjs');
96
- require('./methods/ESPRMAdminOTAJob/DeleteJob.cjs');
97
+ require('./methods/ESPRMAdminOTAJob/CancelJob.cjs');
98
+ require('./methods/ESPRMAdminOTAJob/ArchiveJob.cjs');
97
99
  require('./methods/ESPRMAdminOTAJob/GetJobStatus.cjs');
98
100
  require('./methods/ESPRMAdminOTAJob/GetJobStatusSummary.cjs');
99
101
  require('./methods/ESPRMAdminOTAJob/RetriggerJob.cjs');
@@ -14,10 +14,19 @@ ESPRMAdminOTAImage.ESPRMAdminOTAImage.prototype.archiveImage = async function (p
14
14
  if (!params.ota_image_id) {
15
15
  throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
16
16
  }
17
+ if (typeof params.archive !== "boolean") {
18
+ throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_ARCHIVE_FLAG);
19
+ }
17
20
  const requestConfig = {
18
21
  url: constants.APIEndpoints.ADMIN_OTA_IMAGE,
19
22
  method: constants.HTTPMethods.PUT,
20
- data: params,
23
+ // This endpoint reads query parameters only — a JSON body is ignored and the
24
+ // request fails with "OTA Image Id is missing". `archive` is stringified
25
+ // explicitly because the backend accepts only the literals "true"/"false".
26
+ params: {
27
+ ota_image_id: params.ota_image_id,
28
+ archive: String(params.archive),
29
+ },
21
30
  };
22
31
  const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
23
32
  return response;
@@ -9,15 +9,16 @@ var ESPRMAdminOTAImage = require('../../ESPRMAdminOTAImage.cjs');
9
9
  var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
10
10
  var constants = require('../../utils/constants.cjs');
11
11
  var ESPAPICallValidationError = require('../../utils/error/ESPAPICallValidationError.cjs');
12
+ var deleteParams = require('./deleteParams.cjs');
12
13
 
13
- ESPRMAdminOTAImage.ESPRMAdminOTAImage.prototype.deleteImage = async function (otaImageId) {
14
- if (!otaImageId) {
14
+ ESPRMAdminOTAImage.ESPRMAdminOTAImage.prototype.deleteImage = async function (params) {
15
+ if (!params?.ota_image_id) {
15
16
  throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
16
17
  }
17
18
  const requestConfig = {
18
19
  url: constants.APIEndpoints.ADMIN_OTA_IMAGE,
19
20
  method: constants.HTTPMethods.DELETE,
20
- params: { ota_image_id: otaImageId },
21
+ params: deleteParams.buildDeleteOTAImageParams(params),
21
22
  };
22
23
  const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
23
24
  return response;
@@ -0,0 +1,25 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ 'use strict';
7
+
8
+ var ESPRMAdminOTAImage = require('../../ESPRMAdminOTAImage.cjs');
9
+ var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
10
+ var constants = require('../../utils/constants.cjs');
11
+ var ESPAPICallValidationError = require('../../utils/error/ESPAPICallValidationError.cjs');
12
+ var deleteParams = require('./deleteParams.cjs');
13
+
14
+ ESPRMAdminOTAImage.ESPRMAdminOTAImage.prototype.deletePackage = async function (params) {
15
+ if (!params?.ota_image_id) {
16
+ throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
17
+ }
18
+ const requestConfig = {
19
+ url: constants.APIEndpoints.ADMIN_OTA_IMAGE_PACKAGE,
20
+ method: constants.HTTPMethods.DELETE,
21
+ params: deleteParams.buildDeleteOTAImageParams(params),
22
+ };
23
+ const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
24
+ return response;
25
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ 'use strict';
7
+
8
+ /**
9
+ * Builds the query string shared by the image and package delete endpoints.
10
+ *
11
+ * `force_delete` is sent only when requested: the backend reads it as a string and
12
+ * treats any value other than "true" as false, so omitting it keeps the URL clean.
13
+ */
14
+ function buildDeleteOTAImageParams(params) {
15
+ return {
16
+ ota_image_id: params.ota_image_id,
17
+ ...(params.force_delete ? { force_delete: "true" } : {}),
18
+ };
19
+ }
20
+
21
+ exports.buildDeleteOTAImageParams = buildDeleteOTAImageParams;
@@ -0,0 +1,24 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ 'use strict';
7
+
8
+ var ESPRMAdminOTAJob = require('../../ESPRMAdminOTAJob.cjs');
9
+ var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
10
+ var constants = require('../../utils/constants.cjs');
11
+ var ESPAPICallValidationError = require('../../utils/error/ESPAPICallValidationError.cjs');
12
+
13
+ ESPRMAdminOTAJob.ESPRMAdminOTAJob.prototype.archiveJob = async function (params) {
14
+ if (!params.ota_job_id) {
15
+ throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
16
+ }
17
+ const requestConfig = {
18
+ url: constants.APIEndpoints.ADMIN_OTA_JOB,
19
+ method: constants.HTTPMethods.PUT,
20
+ data: { ota_job_id: params.ota_job_id, archive: true },
21
+ };
22
+ const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
23
+ return response;
24
+ };
@@ -10,14 +10,14 @@ var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
10
10
  var constants = require('../../utils/constants.cjs');
11
11
  var ESPAPICallValidationError = require('../../utils/error/ESPAPICallValidationError.cjs');
12
12
 
13
- ESPRMAdminOTAJob.ESPRMAdminOTAJob.prototype.deleteJob = async function (otaJobId) {
14
- if (!otaJobId) {
13
+ ESPRMAdminOTAJob.ESPRMAdminOTAJob.prototype.cancelJob = async function (params) {
14
+ if (!params.ota_job_id) {
15
15
  throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
16
16
  }
17
17
  const requestConfig = {
18
18
  url: constants.APIEndpoints.ADMIN_OTA_JOB,
19
- method: constants.HTTPMethods.DELETE,
20
- params: { ota_job_id: otaJobId },
19
+ method: constants.HTTPMethods.PUT,
20
+ data: { ota_job_id: params.ota_job_id },
21
21
  };
22
22
  const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
23
23
  return response;
@@ -15,8 +15,8 @@ ESPRMAdminOTAJob.ESPRMAdminOTAJob.prototype.retriggerJob = async function (param
15
15
  throw new ESPAPICallValidationError.ESPAPICallValidationError(constants.APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
16
16
  }
17
17
  const requestConfig = {
18
- url: constants.APIEndpoints.ADMIN_OTA_JOB,
19
- method: constants.HTTPMethods.PUT,
18
+ url: constants.APIEndpoints.ADMIN_OTA_JOB_RETRIGGER,
19
+ method: constants.HTTPMethods.POST,
20
20
  data: params,
21
21
  };
22
22
  const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
@@ -77,8 +77,16 @@ class ESPRMAPIManager {
77
77
  const base = requestConfig.baseURL ?? instance.#baseUrl;
78
78
  let requestUrl = `${base}/${requestConfig.url}`;
79
79
  if (requestConfig.params) {
80
- const queryParams = new URLSearchParams(requestConfig.params).toString();
81
- requestUrl += `?${queryParams}`;
80
+ // `URLSearchParams` stringifies every own key, so an optional param
81
+ // left as `undefined` would reach the backend as the literal text
82
+ // "undefined" and fail validation. Drop absent values and let
83
+ // numbers / booleans stringify explicitly.
84
+ const queryEntries = Object.entries(requestConfig.params)
85
+ .filter(([, value]) => value !== undefined && value !== null)
86
+ .map(([key, value]) => [key, String(value)]);
87
+ if (queryEntries.length > 0) {
88
+ requestUrl += `?${new URLSearchParams(queryEntries).toString()}`;
89
+ }
82
90
  }
83
91
  const fetchOptions = {
84
92
  method: requestConfig.method,
@@ -29,7 +29,7 @@ const APIEndpoints = {
29
29
  ADMIN_OTA_JOB: "admin/otajob",
30
30
  ADMIN_OTA_JOB_STATUS: "admin/otajob/status",
31
31
  ADMIN_OTA_JOB_STATUS_SUMMARY: "admin/otajob/status/summary",
32
- ADMIN_OTA_JOB_ACTION: "admin/otajob",
32
+ ADMIN_OTA_JOB_RETRIGGER: "admin/otajob/retrigger",
33
33
  ADMIN_NODE_GROUP: "admin/node_group",
34
34
  ADMIN_TAGS: "admin/tags",
35
35
  ADMIN_TAG_NAMES: "admin/tags/names",
@@ -117,6 +117,7 @@ const StorageAdapterErrorCodes = {
117
117
  const APICallValidationErrorCodes = {
118
118
  MISSING_NODE_ID: "MISSING_NODE_ID",
119
119
  MISSING_OTA_IMAGE_ID: "MISSING_OTA_IMAGE_ID",
120
+ MISSING_ARCHIVE_FLAG: "MISSING_ARCHIVE_FLAG",
120
121
  MISSING_OTA_JOB_ID: "MISSING_OTA_JOB_ID",
121
122
  MISSING_GROUP_ID: "MISSING_GROUP_ID",
122
123
  MISSING_GROUP_NAME: "MISSING_GROUP_NAME",
@@ -21,6 +21,7 @@ const storageAdapterErrorMessages = {
21
21
  const apiCallValidationErrorMessages = {
22
22
  MISSING_NODE_ID: "ESPAPICallValidationError: Node ID is required.",
23
23
  MISSING_OTA_IMAGE_ID: "ESPAPICallValidationError: OTA image ID is required.",
24
+ MISSING_ARCHIVE_FLAG: "ESPAPICallValidationError: Archive flag is required and must be a boolean.",
24
25
  MISSING_OTA_JOB_ID: "ESPAPICallValidationError: OTA job ID is required.",
25
26
  MISSING_GROUP_ID: "ESPAPICallValidationError: Group ID is required.",
26
27
  MISSING_GROUP_NAME: "ESPAPICallValidationError: Group name is required.",
@@ -11,4 +11,5 @@ import '../methods/ESPRMAdminOTAImage/ConfirmPackageUpload.js';
11
11
  import '../methods/ESPRMAdminOTAImage/GetImages.js';
12
12
  import '../methods/ESPRMAdminOTAImage/ArchiveImage.js';
13
13
  import '../methods/ESPRMAdminOTAImage/DeleteImage.js';
14
+ import '../methods/ESPRMAdminOTAImage/DeletePackage.js';
14
15
  export { ESPRMAdminOTAImage } from '../ESPRMAdminOTAImage.js';
@@ -6,7 +6,8 @@
6
6
  import '../methods/ESPRMAdminOTAJob/CreateJob.js';
7
7
  import '../methods/ESPRMAdminOTAJob/GetJob.js';
8
8
  import '../methods/ESPRMAdminOTAJob/UpdateJob.js';
9
- import '../methods/ESPRMAdminOTAJob/DeleteJob.js';
9
+ import '../methods/ESPRMAdminOTAJob/CancelJob.js';
10
+ import '../methods/ESPRMAdminOTAJob/ArchiveJob.js';
10
11
  import '../methods/ESPRMAdminOTAJob/GetJobStatus.js';
11
12
  import '../methods/ESPRMAdminOTAJob/GetJobStatusSummary.js';
12
13
  import '../methods/ESPRMAdminOTAJob/RetriggerJob.js';
package/dist/esm/index.js CHANGED
@@ -88,10 +88,12 @@ import './methods/ESPRMAdminOTAImage/ConfirmPackageUpload.js';
88
88
  import './methods/ESPRMAdminOTAImage/GetImages.js';
89
89
  import './methods/ESPRMAdminOTAImage/ArchiveImage.js';
90
90
  import './methods/ESPRMAdminOTAImage/DeleteImage.js';
91
+ import './methods/ESPRMAdminOTAImage/DeletePackage.js';
91
92
  import './methods/ESPRMAdminOTAJob/CreateJob.js';
92
93
  import './methods/ESPRMAdminOTAJob/GetJob.js';
93
94
  import './methods/ESPRMAdminOTAJob/UpdateJob.js';
94
- import './methods/ESPRMAdminOTAJob/DeleteJob.js';
95
+ import './methods/ESPRMAdminOTAJob/CancelJob.js';
96
+ import './methods/ESPRMAdminOTAJob/ArchiveJob.js';
95
97
  import './methods/ESPRMAdminOTAJob/GetJobStatus.js';
96
98
  import './methods/ESPRMAdminOTAJob/GetJobStatusSummary.js';
97
99
  import './methods/ESPRMAdminOTAJob/RetriggerJob.js';
@@ -12,10 +12,19 @@ ESPRMAdminOTAImage.prototype.archiveImage = async function (params) {
12
12
  if (!params.ota_image_id) {
13
13
  throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
14
14
  }
15
+ if (typeof params.archive !== "boolean") {
16
+ throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_ARCHIVE_FLAG);
17
+ }
15
18
  const requestConfig = {
16
19
  url: APIEndpoints.ADMIN_OTA_IMAGE,
17
20
  method: HTTPMethods.PUT,
18
- data: params,
21
+ // This endpoint reads query parameters only — a JSON body is ignored and the
22
+ // request fails with "OTA Image Id is missing". `archive` is stringified
23
+ // explicitly because the backend accepts only the literals "true"/"false".
24
+ params: {
25
+ ota_image_id: params.ota_image_id,
26
+ archive: String(params.archive),
27
+ },
19
28
  };
20
29
  const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
21
30
  return response;
@@ -7,15 +7,16 @@ import { ESPRMAdminOTAImage } from '../../ESPRMAdminOTAImage.js';
7
7
  import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
8
8
  import { APICallValidationErrorCodes, HTTPMethods, APIEndpoints } from '../../utils/constants.js';
9
9
  import { ESPAPICallValidationError } from '../../utils/error/ESPAPICallValidationError.js';
10
+ import { buildDeleteOTAImageParams } from './deleteParams.js';
10
11
 
11
- ESPRMAdminOTAImage.prototype.deleteImage = async function (otaImageId) {
12
- if (!otaImageId) {
12
+ ESPRMAdminOTAImage.prototype.deleteImage = async function (params) {
13
+ if (!params?.ota_image_id) {
13
14
  throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
14
15
  }
15
16
  const requestConfig = {
16
17
  url: APIEndpoints.ADMIN_OTA_IMAGE,
17
18
  method: HTTPMethods.DELETE,
18
- params: { ota_image_id: otaImageId },
19
+ params: buildDeleteOTAImageParams(params),
19
20
  };
20
21
  const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
21
22
  return response;
@@ -0,0 +1,23 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ESPRMAdminOTAImage } from '../../ESPRMAdminOTAImage.js';
7
+ import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
8
+ import { APICallValidationErrorCodes, HTTPMethods, APIEndpoints } from '../../utils/constants.js';
9
+ import { ESPAPICallValidationError } from '../../utils/error/ESPAPICallValidationError.js';
10
+ import { buildDeleteOTAImageParams } from './deleteParams.js';
11
+
12
+ ESPRMAdminOTAImage.prototype.deletePackage = async function (params) {
13
+ if (!params?.ota_image_id) {
14
+ throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_IMAGE_ID);
15
+ }
16
+ const requestConfig = {
17
+ url: APIEndpoints.ADMIN_OTA_IMAGE_PACKAGE,
18
+ method: HTTPMethods.DELETE,
19
+ params: buildDeleteOTAImageParams(params),
20
+ };
21
+ const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
22
+ return response;
23
+ };
@@ -0,0 +1,19 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Builds the query string shared by the image and package delete endpoints.
8
+ *
9
+ * `force_delete` is sent only when requested: the backend reads it as a string and
10
+ * treats any value other than "true" as false, so omitting it keeps the URL clean.
11
+ */
12
+ function buildDeleteOTAImageParams(params) {
13
+ return {
14
+ ota_image_id: params.ota_image_id,
15
+ ...(params.force_delete ? { force_delete: "true" } : {}),
16
+ };
17
+ }
18
+
19
+ export { buildDeleteOTAImageParams };
@@ -0,0 +1,22 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ESPRMAdminOTAJob } from '../../ESPRMAdminOTAJob.js';
7
+ import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
8
+ import { APICallValidationErrorCodes, HTTPMethods, APIEndpoints } from '../../utils/constants.js';
9
+ import { ESPAPICallValidationError } from '../../utils/error/ESPAPICallValidationError.js';
10
+
11
+ ESPRMAdminOTAJob.prototype.archiveJob = async function (params) {
12
+ if (!params.ota_job_id) {
13
+ throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
14
+ }
15
+ const requestConfig = {
16
+ url: APIEndpoints.ADMIN_OTA_JOB,
17
+ method: HTTPMethods.PUT,
18
+ data: { ota_job_id: params.ota_job_id, archive: true },
19
+ };
20
+ const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
21
+ return response;
22
+ };
@@ -8,14 +8,14 @@ import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
8
8
  import { APICallValidationErrorCodes, HTTPMethods, APIEndpoints } from '../../utils/constants.js';
9
9
  import { ESPAPICallValidationError } from '../../utils/error/ESPAPICallValidationError.js';
10
10
 
11
- ESPRMAdminOTAJob.prototype.deleteJob = async function (otaJobId) {
12
- if (!otaJobId) {
11
+ ESPRMAdminOTAJob.prototype.cancelJob = async function (params) {
12
+ if (!params.ota_job_id) {
13
13
  throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
14
14
  }
15
15
  const requestConfig = {
16
16
  url: APIEndpoints.ADMIN_OTA_JOB,
17
- method: HTTPMethods.DELETE,
18
- params: { ota_job_id: otaJobId },
17
+ method: HTTPMethods.PUT,
18
+ data: { ota_job_id: params.ota_job_id },
19
19
  };
20
20
  const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
21
21
  return response;
@@ -13,8 +13,8 @@ ESPRMAdminOTAJob.prototype.retriggerJob = async function (params) {
13
13
  throw new ESPAPICallValidationError(APICallValidationErrorCodes.MISSING_OTA_JOB_ID);
14
14
  }
15
15
  const requestConfig = {
16
- url: APIEndpoints.ADMIN_OTA_JOB,
17
- method: HTTPMethods.PUT,
16
+ url: APIEndpoints.ADMIN_OTA_JOB_RETRIGGER,
17
+ method: HTTPMethods.POST,
18
18
  data: params,
19
19
  };
20
20
  const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
@@ -75,8 +75,16 @@ class ESPRMAPIManager {
75
75
  const base = requestConfig.baseURL ?? instance.#baseUrl;
76
76
  let requestUrl = `${base}/${requestConfig.url}`;
77
77
  if (requestConfig.params) {
78
- const queryParams = new URLSearchParams(requestConfig.params).toString();
79
- requestUrl += `?${queryParams}`;
78
+ // `URLSearchParams` stringifies every own key, so an optional param
79
+ // left as `undefined` would reach the backend as the literal text
80
+ // "undefined" and fail validation. Drop absent values and let
81
+ // numbers / booleans stringify explicitly.
82
+ const queryEntries = Object.entries(requestConfig.params)
83
+ .filter(([, value]) => value !== undefined && value !== null)
84
+ .map(([key, value]) => [key, String(value)]);
85
+ if (queryEntries.length > 0) {
86
+ requestUrl += `?${new URLSearchParams(queryEntries).toString()}`;
87
+ }
80
88
  }
81
89
  const fetchOptions = {
82
90
  method: requestConfig.method,
@@ -27,7 +27,7 @@ const APIEndpoints = {
27
27
  ADMIN_OTA_JOB: "admin/otajob",
28
28
  ADMIN_OTA_JOB_STATUS: "admin/otajob/status",
29
29
  ADMIN_OTA_JOB_STATUS_SUMMARY: "admin/otajob/status/summary",
30
- ADMIN_OTA_JOB_ACTION: "admin/otajob",
30
+ ADMIN_OTA_JOB_RETRIGGER: "admin/otajob/retrigger",
31
31
  ADMIN_NODE_GROUP: "admin/node_group",
32
32
  ADMIN_TAGS: "admin/tags",
33
33
  ADMIN_TAG_NAMES: "admin/tags/names",
@@ -115,6 +115,7 @@ const StorageAdapterErrorCodes = {
115
115
  const APICallValidationErrorCodes = {
116
116
  MISSING_NODE_ID: "MISSING_NODE_ID",
117
117
  MISSING_OTA_IMAGE_ID: "MISSING_OTA_IMAGE_ID",
118
+ MISSING_ARCHIVE_FLAG: "MISSING_ARCHIVE_FLAG",
118
119
  MISSING_OTA_JOB_ID: "MISSING_OTA_JOB_ID",
119
120
  MISSING_GROUP_ID: "MISSING_GROUP_ID",
120
121
  MISSING_GROUP_NAME: "MISSING_GROUP_NAME",
@@ -19,6 +19,7 @@ const storageAdapterErrorMessages = {
19
19
  const apiCallValidationErrorMessages = {
20
20
  MISSING_NODE_ID: "ESPAPICallValidationError: Node ID is required.",
21
21
  MISSING_OTA_IMAGE_ID: "ESPAPICallValidationError: OTA image ID is required.",
22
+ MISSING_ARCHIVE_FLAG: "ESPAPICallValidationError: Archive flag is required and must be a boolean.",
22
23
  MISSING_OTA_JOB_ID: "ESPAPICallValidationError: OTA job ID is required.",
23
24
  MISSING_GROUP_ID: "ESPAPICallValidationError: Group ID is required.",
24
25
  MISSING_GROUP_NAME: "ESPAPICallValidationError: Group name is required.",
@@ -8,10 +8,13 @@ import { ESPAPISuccessResponse } from "../../types/api.js";
8
8
  declare module "../../ESPRMAdminOTAImage.js" {
9
9
  interface ESPRMAdminOTAImage {
10
10
  /**
11
- * Archives an OTA firmware image by its image ID.
11
+ * Archives or unarchives an OTA firmware image by its image ID.
12
12
  *
13
- * @param params - Parameters including the OTA image ID to archive.
14
- * @returns A success response confirming the image was archived.
13
+ * Unlike OTA jobs, image archiving is two-way: pass `archive: false` to restore
14
+ * an archived image.
15
+ *
16
+ * @param params - The OTA image ID and the desired archived state.
17
+ * @returns A success response confirming the new archived state.
15
18
  */
16
19
  archiveImage(params: ArchiveOTAImageParams): Promise<ESPAPISuccessResponse>;
17
20
  }
@@ -3,15 +3,19 @@
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { DeleteOTAImageParams } from "../../types/ota.js";
6
7
  import { ESPAPISuccessResponse } from "../../types/api.js";
7
8
  declare module "../../ESPRMAdminOTAImage.js" {
8
9
  interface ESPRMAdminOTAImage {
9
10
  /**
10
11
  * Deletes an OTA firmware image by its image ID.
11
12
  *
12
- * @param otaImageId - The ID of the OTA image to delete.
13
+ * Images uploaded as part of a package are rejected by this endpoint and must
14
+ * be removed with {@link ESPRMAdminOTAImage.deletePackage} instead.
15
+ *
16
+ * @param params - The OTA image ID, and optionally `force_delete`.
13
17
  * @returns A success response confirming the image was deleted.
14
18
  */
15
- deleteImage(otaImageId: string): Promise<ESPAPISuccessResponse>;
19
+ deleteImage(params: DeleteOTAImageParams): Promise<ESPAPISuccessResponse>;
16
20
  }
17
21
  }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { DeleteOTAImageParams } from "../../types/ota.js";
7
+ import { ESPAPISuccessResponse } from "../../types/api.js";
8
+ declare module "../../ESPRMAdminOTAImage.js" {
9
+ interface ESPRMAdminOTAImage {
10
+ /**
11
+ * Deletes an OTA image that was uploaded as part of a package, removing both the
12
+ * image and the package archive it came from.
13
+ *
14
+ * Images uploaded as a standalone binary should use
15
+ * {@link ESPRMAdminOTAImage.deleteImage} instead.
16
+ *
17
+ * @param params - The OTA image ID, and optionally `force_delete`.
18
+ * @returns A success response confirming the package was deleted.
19
+ */
20
+ deletePackage(params: DeleteOTAImageParams): Promise<ESPAPISuccessResponse>;
21
+ }
22
+ }