@espressif/rainmaker-admin-sdk 1.3.0 → 1.4.0

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 (40) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/cjs/entries/ESPRMAuth.cjs +1 -0
  3. package/dist/cjs/entries/ESPRMBase.cjs +1 -0
  4. package/dist/cjs/index.cjs +1 -0
  5. package/dist/cjs/methods/ESPRMAuth/LoginWithAuthorizationCode.cjs +54 -0
  6. package/dist/cjs/services/ESPRMAPIManager.cjs +29 -4
  7. package/dist/cjs/utils/constants.cjs +4 -0
  8. package/dist/cjs/utils/error/errorMessages.cjs +3 -0
  9. package/dist/cjs/utils/error/parser.cjs +3 -2
  10. package/dist/esm/entries/ESPRMAuth.js +1 -0
  11. package/dist/esm/entries/ESPRMBase.js +1 -0
  12. package/dist/esm/index.js +1 -0
  13. package/dist/esm/methods/ESPRMAuth/LoginWithAuthorizationCode.js +52 -0
  14. package/dist/esm/services/ESPRMAPIManager.js +29 -4
  15. package/dist/esm/utils/constants.js +4 -0
  16. package/dist/esm/utils/error/errorMessages.js +3 -0
  17. package/dist/esm/utils/error/parser.js +3 -2
  18. package/dist/types/methods/ESPRMAdminOTAJob/GetJob.d.ts +12 -3
  19. package/dist/types/methods/ESPRMAuth/LoginWithAuthorizationCode.d.ts +40 -0
  20. package/dist/types/methods/ESPRMAuth/index.d.ts +1 -0
  21. package/dist/types/services/ESPRMAPIManager.d.ts +5 -0
  22. package/dist/types/types/auth.d.ts +30 -0
  23. package/dist/types/types/config.d.ts +5 -0
  24. package/dist/types/types/input.d.ts +1 -1
  25. package/dist/types/types/ota.d.ts +42 -8
  26. package/dist/types/utils/constants.d.ts +4 -0
  27. package/dist/types/utils/error/errorMessages.d.ts +3 -0
  28. package/dist/types/utils/error/parser.d.ts +4 -0
  29. package/dist/types-cjs/methods/ESPRMAdminOTAJob/GetJob.d.cts +12 -3
  30. package/dist/types-cjs/methods/ESPRMAuth/LoginWithAuthorizationCode.d.cts +40 -0
  31. package/dist/types-cjs/methods/ESPRMAuth/index.d.cts +1 -0
  32. package/dist/types-cjs/services/ESPRMAPIManager.d.cts +5 -0
  33. package/dist/types-cjs/types/auth.d.cts +30 -0
  34. package/dist/types-cjs/types/config.d.cts +5 -0
  35. package/dist/types-cjs/types/input.d.cts +1 -1
  36. package/dist/types-cjs/types/ota.d.cts +42 -8
  37. package/dist/types-cjs/utils/constants.d.cts +4 -0
  38. package/dist/types-cjs/utils/error/errorMessages.d.cts +3 -0
  39. package/dist/types-cjs/utils/error/parser.d.cts +4 -0
  40. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,62 @@
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
+ ## [1.4.0] - 2026-10-07
7
+
8
+ Minor release that adds OAuth 2.0 authorization-code login, so dashboards can
9
+ complete social sign-in that uses `response_type=code` (WeChat on China
10
+ deployments) through the SDK instead of calling `/token` themselves. Existing
11
+ methods keep their signatures; the two behaviour changes below are fixes.
12
+
13
+ ### Added
14
+
15
+ - `ESPRMAuth.loginWithAuthorizationCode({ code, redirectUri, clientId })`
16
+ completes an OAuth 2.0 authorization-code login (`response_type=code`, used
17
+ by WeChat sign-in on China deployments). It sends a form-encoded
18
+ `POST {baseUrl}/token` and stores the returned tokens like `login()`. When
19
+ no refresh token is issued, an empty one is stored.
20
+ - `ESPRMRequestConfig.formData` sends a request body as
21
+ `application/x-www-form-urlencoded`.
22
+ - `ESPRMAPIManager.getRootUrl()` returns the configured `baseUrl` without the
23
+ API version segment.
24
+ - Types `AuthorizationCodeLoginParams`, `AuthorizationCodeTokenRequest` and
25
+ `OAuthTokenResponse`, and validation codes `MISSING_AUTHORIZATION_CODE`,
26
+ `MISSING_REDIRECT_URI` and `MISSING_OAUTH_CLIENT_ID`.
27
+
28
+ ### Changed
29
+
30
+ - `ESPAPIError` now reads RFC 6749 error bodies too. `errorCode` falls back to
31
+ `error`, and `description` falls back to `error_description`, when the
32
+ RainMaker `error_code` / `description` fields are absent.
33
+ - A trailing slash on `baseUrl` is now removed before the version segment is
34
+ appended. Before, it produced a double slash such as `https://host//v1`.
35
+
36
+ ## [1.3.1] - 2026-10-07
37
+
38
+ Patch release that corrects the OTA job list types in `ESPRMAdminOTAJob.getJob`
39
+ to match what the backend accepts and returns. No runtime behaviour changes:
40
+ the SDK already forwarded every query parameter and returned the backend's
41
+ response as-is. Only the types were wrong.
42
+
43
+ ### Added
44
+
45
+ - `GetOTAJobParams` now declares the filters the backend accepts:
46
+ `ota_job_name` (case-sensitive "contains" search), `ota_image_id`,
47
+ `archived` and `all`. Callers no longer need a cast to search.
48
+ - `GetOTAJobsResponse.otaJobs`, the key the backend actually returns the job
49
+ list under.
50
+ - `GetOTAJobByIdParams` and a `getJob({ ota_job_id })` overload that returns
51
+ `OTAJobInfo`. The backend answers an ID lookup with the job itself, not a
52
+ list.
53
+
54
+ ### Deprecated
55
+
56
+ - `GetOTAJobsResponse.ota_update_jobs` and `GetOTAJobsResponse.total`. The
57
+ backend has never returned either; read `otaJobs` instead. Both will be
58
+ removed in the next minor release.
59
+ - `GetOTAJobParams.ota_job_id`. Pass `GetOTAJobByIdParams` to get the
60
+ correctly typed single-job response.
61
+
6
62
  ## [1.3.0] - 2026-10-06
7
63
 
8
64
  Minor release that adds node deletion, node claiming through the standalone
@@ -6,6 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  require('../methods/ESPRMAuth/Login.cjs');
9
+ require('../methods/ESPRMAuth/LoginWithAuthorizationCode.cjs');
9
10
  require('../methods/ESPRMAuth/Logout.cjs');
10
11
  require('../methods/ESPRMAuth/ForgotPassword.cjs');
11
12
  require('../methods/ESPRMAuth/ChangePassword.cjs');
@@ -6,6 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  require('../methods/ESPRMAuth/Login.cjs');
9
+ require('../methods/ESPRMAuth/LoginWithAuthorizationCode.cjs');
9
10
  require('../methods/ESPRMAuth/Logout.cjs');
10
11
  require('../methods/ESPRMAuth/ForgotPassword.cjs');
11
12
  require('../methods/ESPRMAuth/ChangePassword.cjs');
@@ -58,6 +58,7 @@ var ESPRMAdminMatter = require('./ESPRMAdminMatter.cjs');
58
58
  var ESPRMAdminNodeParams = require('./ESPRMAdminNodeParams.cjs');
59
59
  var ESPRMClaim = require('./ESPRMClaim.cjs');
60
60
  require('./methods/ESPRMAuth/Login.cjs');
61
+ require('./methods/ESPRMAuth/LoginWithAuthorizationCode.cjs');
61
62
  require('./methods/ESPRMAuth/Logout.cjs');
62
63
  require('./methods/ESPRMAuth/ForgotPassword.cjs');
63
64
  require('./methods/ESPRMAuth/ChangePassword.cjs');
@@ -0,0 +1,54 @@
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 ESPRMAuth = require('../../ESPRMAuth.cjs');
9
+ var ESPRMUser = require('../../ESPRMUser.cjs');
10
+ var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
11
+ var constants = require('../../utils/constants.cjs');
12
+ var ESPValidationError = require('../../utils/error/ESPValidationError.cjs');
13
+ var parser = require('../../utils/error/parser.cjs');
14
+
15
+ function validateParams({ code, redirectUri, clientId, }) {
16
+ if (!code) {
17
+ throw new ESPValidationError.ESPValidationError(constants.ValidationErrorCodes.MISSING_AUTHORIZATION_CODE);
18
+ }
19
+ if (!redirectUri) {
20
+ throw new ESPValidationError.ESPValidationError(constants.ValidationErrorCodes.MISSING_REDIRECT_URI);
21
+ }
22
+ if (!clientId) {
23
+ throw new ESPValidationError.ESPValidationError(constants.ValidationErrorCodes.MISSING_OAUTH_CLIENT_ID);
24
+ }
25
+ }
26
+ ESPRMAuth.ESPRMAuth.prototype.loginWithAuthorizationCode = async function (params) {
27
+ validateParams(params);
28
+ const tokenRequest = {
29
+ grant_type: "authorization_code",
30
+ code: params.code,
31
+ redirect_uri: params.redirectUri,
32
+ client_id: params.clientId,
33
+ };
34
+ const requestConfig = {
35
+ baseURL: ESPRMAPIManager.ESPRMAPIManager.getRootUrl(),
36
+ url: constants.APIEndpoints.OAUTH_TOKEN,
37
+ method: constants.HTTPMethods.POST,
38
+ formData: tokenRequest,
39
+ };
40
+ const responseData = await ESPRMAPIManager.ESPRMAPIManager.request(requestConfig);
41
+ if (!responseData?.access_token || !responseData?.id_token) {
42
+ throw parser.parseAPIErrorResponse({
43
+ status: "failure",
44
+ description: "Token response is missing access_token or id_token",
45
+ }, 200);
46
+ }
47
+ const userTokens = {
48
+ accessToken: responseData.access_token,
49
+ idToken: responseData.id_token,
50
+ refreshToken: responseData.refresh_token ?? "",
51
+ };
52
+ await ESPRMUser.ESPRMUser.storeTokens(userTokens);
53
+ return new ESPRMUser.ESPRMUser(userTokens);
54
+ };
@@ -20,11 +20,13 @@ var common = require('../types/common.cjs');
20
20
  class ESPRMAPIManager {
21
21
  static #instance;
22
22
  #baseUrl;
23
+ #rootUrl;
23
24
  #timeoutMs;
24
25
  #claimingBaseUrl;
25
26
  constructor(config) {
26
27
  const { baseUrl, version, timeoutMs, claimingBaseUrl } = config;
27
- this.#baseUrl = `${baseUrl}/${version}`;
28
+ this.#rootUrl = baseUrl.replace(/\/+$/, "");
29
+ this.#baseUrl = `${this.#rootUrl}/${version}`;
28
30
  this.#timeoutMs = timeoutMs ?? constants.DEFAULT_REQUEST_TIMEOUT_MS;
29
31
  this.#claimingBaseUrl = claimingBaseUrl?.replace(/\/+$/, "");
30
32
  }
@@ -37,6 +39,13 @@ class ESPRMAPIManager {
37
39
  }
38
40
  return ESPRMAPIManager.#instance;
39
41
  }
42
+ /**
43
+ * Configured `baseUrl` without the API version segment, for the endpoints
44
+ * served outside `/{version}`, such as the OAuth `/token` endpoint.
45
+ */
46
+ static getRootUrl() {
47
+ return ESPRMAPIManager.#getInstance().#rootUrl;
48
+ }
40
49
  /**
41
50
  * Base URL of the claiming service set through `claimingBaseUrl`.
42
51
  *
@@ -82,6 +91,21 @@ class ESPRMAPIManager {
82
91
  throw error;
83
92
  }
84
93
  }
94
+ static #serializeBody(requestConfig) {
95
+ if (requestConfig.formData) {
96
+ return {
97
+ contentType: "application/x-www-form-urlencoded",
98
+ body: new URLSearchParams(requestConfig.formData).toString(),
99
+ };
100
+ }
101
+ if (requestConfig.data) {
102
+ return {
103
+ contentType: "application/json",
104
+ body: JSON.stringify(requestConfig.data),
105
+ };
106
+ }
107
+ return {};
108
+ }
85
109
  /**
86
110
  * Send an unauthenticated request. Non-2xx responses and network/timeout
87
111
  * failures reject with an {@link ESPAPIError}.
@@ -102,18 +126,19 @@ class ESPRMAPIManager {
102
126
  requestUrl += `?${new URLSearchParams(queryEntries).toString()}`;
103
127
  }
104
128
  }
129
+ const { contentType, body } = ESPRMAPIManager.#serializeBody(requestConfig);
105
130
  const fetchOptions = {
106
131
  method: requestConfig.method,
107
132
  // The API never redirects. Following one would re-send the body (login
108
133
  // password, refresh token) to whatever host the redirect names.
109
134
  redirect: "error",
110
135
  headers: {
111
- ...(requestConfig.data ? { "Content-Type": "application/json" } : {}),
136
+ ...(contentType ? { "Content-Type": contentType } : {}),
112
137
  ...requestConfig.headers,
113
138
  },
114
139
  };
115
- if (requestConfig.data) {
116
- fetchOptions.body = JSON.stringify(requestConfig.data);
140
+ if (body !== undefined) {
141
+ fetchOptions.body = body;
117
142
  }
118
143
  const timeoutMs = requestConfig.timeoutMs ?? instance.#timeoutMs;
119
144
  let timer;
@@ -17,6 +17,7 @@ const APIEndpoints = {
17
17
  LOGIN: "login2",
18
18
  PASSWORD: "password2",
19
19
  LOGOUT: "logout2",
20
+ OAUTH_TOKEN: "token",
20
21
  ADMIN_USER: "admin/user2",
21
22
  ADMIN_USER_SUMMARY: "admin/user2/summary",
22
23
  ADMIN_NODES: "admin/nodes",
@@ -115,6 +116,9 @@ const ValidationErrorCodes = {
115
116
  MISSING_LOGIN_PASSWORD: "MISSING_LOGIN_PASSWORD",
116
117
  MISSING_USERNAME: "MISSING_USERNAME",
117
118
  MISSING_VERIFICATION_CODE: "MISSING_VERIFICATION_CODE",
119
+ MISSING_AUTHORIZATION_CODE: "MISSING_AUTHORIZATION_CODE",
120
+ MISSING_REDIRECT_URI: "MISSING_REDIRECT_URI",
121
+ MISSING_OAUTH_CLIENT_ID: "MISSING_OAUTH_CLIENT_ID",
118
122
  };
119
123
  const StorageAdapterErrorCodes = {
120
124
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API",
@@ -16,6 +16,9 @@ const validationErrorMessages = {
16
16
  MISSING_LOGIN_PASSWORD: "Validation Error: Password is required.",
17
17
  MISSING_USERNAME: "Validation Error: Username is required.",
18
18
  MISSING_VERIFICATION_CODE: "Validation Error: Verification code is required.",
19
+ MISSING_AUTHORIZATION_CODE: "Validation Error: Authorization code is required.",
20
+ MISSING_REDIRECT_URI: "Validation Error: Redirect URI is required.",
21
+ MISSING_OAUTH_CLIENT_ID: "Validation Error: OAuth client ID is required.",
19
22
  };
20
23
  const storageAdapterErrorMessages = {
21
24
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "ESPStorageAdapterError: It seems like your environment doesn't support window.localstorage, you can define your own storage adapter while configuring the ESPRMBase instance. Please refer docs for more information.",
@@ -11,8 +11,9 @@ const parseAPIErrorResponse = (error, statusCode) => {
11
11
  let description = "An error has occurred";
12
12
  if (error) {
13
13
  status = error.status ?? "";
14
- errorCode = error.error_code ?? "";
15
- description = error.description ?? "An error has occurred";
14
+ errorCode = error.error_code ?? error.error ?? "";
15
+ description =
16
+ error.description ?? error.error_description ?? "An error has occurred";
16
17
  }
17
18
  else {
18
19
  throw error;
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import '../methods/ESPRMAuth/Login.js';
7
+ import '../methods/ESPRMAuth/LoginWithAuthorizationCode.js';
7
8
  import '../methods/ESPRMAuth/Logout.js';
8
9
  import '../methods/ESPRMAuth/ForgotPassword.js';
9
10
  import '../methods/ESPRMAuth/ChangePassword.js';
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import '../methods/ESPRMAuth/Login.js';
7
+ import '../methods/ESPRMAuth/LoginWithAuthorizationCode.js';
7
8
  import '../methods/ESPRMAuth/Logout.js';
8
9
  import '../methods/ESPRMAuth/ForgotPassword.js';
9
10
  import '../methods/ESPRMAuth/ChangePassword.js';
package/dist/esm/index.js CHANGED
@@ -56,6 +56,7 @@ export { ESPRMAdminMatter } from './ESPRMAdminMatter.js';
56
56
  export { ESPRMAdminNodeParams } from './ESPRMAdminNodeParams.js';
57
57
  export { ESPRMClaim } from './ESPRMClaim.js';
58
58
  import './methods/ESPRMAuth/Login.js';
59
+ import './methods/ESPRMAuth/LoginWithAuthorizationCode.js';
59
60
  import './methods/ESPRMAuth/Logout.js';
60
61
  import './methods/ESPRMAuth/ForgotPassword.js';
61
62
  import './methods/ESPRMAuth/ChangePassword.js';
@@ -0,0 +1,52 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ESPRMAuth } from '../../ESPRMAuth.js';
7
+ import { ESPRMUser } from '../../ESPRMUser.js';
8
+ import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
9
+ import { HTTPMethods, APIEndpoints, ValidationErrorCodes } from '../../utils/constants.js';
10
+ import { ESPValidationError } from '../../utils/error/ESPValidationError.js';
11
+ import { parseAPIErrorResponse } from '../../utils/error/parser.js';
12
+
13
+ function validateParams({ code, redirectUri, clientId, }) {
14
+ if (!code) {
15
+ throw new ESPValidationError(ValidationErrorCodes.MISSING_AUTHORIZATION_CODE);
16
+ }
17
+ if (!redirectUri) {
18
+ throw new ESPValidationError(ValidationErrorCodes.MISSING_REDIRECT_URI);
19
+ }
20
+ if (!clientId) {
21
+ throw new ESPValidationError(ValidationErrorCodes.MISSING_OAUTH_CLIENT_ID);
22
+ }
23
+ }
24
+ ESPRMAuth.prototype.loginWithAuthorizationCode = async function (params) {
25
+ validateParams(params);
26
+ const tokenRequest = {
27
+ grant_type: "authorization_code",
28
+ code: params.code,
29
+ redirect_uri: params.redirectUri,
30
+ client_id: params.clientId,
31
+ };
32
+ const requestConfig = {
33
+ baseURL: ESPRMAPIManager.getRootUrl(),
34
+ url: APIEndpoints.OAUTH_TOKEN,
35
+ method: HTTPMethods.POST,
36
+ formData: tokenRequest,
37
+ };
38
+ const responseData = await ESPRMAPIManager.request(requestConfig);
39
+ if (!responseData?.access_token || !responseData?.id_token) {
40
+ throw parseAPIErrorResponse({
41
+ status: "failure",
42
+ description: "Token response is missing access_token or id_token",
43
+ }, 200);
44
+ }
45
+ const userTokens = {
46
+ accessToken: responseData.access_token,
47
+ idToken: responseData.id_token,
48
+ refreshToken: responseData.refresh_token ?? "",
49
+ };
50
+ await ESPRMUser.storeTokens(userTokens);
51
+ return new ESPRMUser(userTokens);
52
+ };
@@ -18,11 +18,13 @@ import { PropertyCheckMode } from '../types/common.js';
18
18
  class ESPRMAPIManager {
19
19
  static #instance;
20
20
  #baseUrl;
21
+ #rootUrl;
21
22
  #timeoutMs;
22
23
  #claimingBaseUrl;
23
24
  constructor(config) {
24
25
  const { baseUrl, version, timeoutMs, claimingBaseUrl } = config;
25
- this.#baseUrl = `${baseUrl}/${version}`;
26
+ this.#rootUrl = baseUrl.replace(/\/+$/, "");
27
+ this.#baseUrl = `${this.#rootUrl}/${version}`;
26
28
  this.#timeoutMs = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
27
29
  this.#claimingBaseUrl = claimingBaseUrl?.replace(/\/+$/, "");
28
30
  }
@@ -35,6 +37,13 @@ class ESPRMAPIManager {
35
37
  }
36
38
  return ESPRMAPIManager.#instance;
37
39
  }
40
+ /**
41
+ * Configured `baseUrl` without the API version segment, for the endpoints
42
+ * served outside `/{version}`, such as the OAuth `/token` endpoint.
43
+ */
44
+ static getRootUrl() {
45
+ return ESPRMAPIManager.#getInstance().#rootUrl;
46
+ }
38
47
  /**
39
48
  * Base URL of the claiming service set through `claimingBaseUrl`.
40
49
  *
@@ -80,6 +89,21 @@ class ESPRMAPIManager {
80
89
  throw error;
81
90
  }
82
91
  }
92
+ static #serializeBody(requestConfig) {
93
+ if (requestConfig.formData) {
94
+ return {
95
+ contentType: "application/x-www-form-urlencoded",
96
+ body: new URLSearchParams(requestConfig.formData).toString(),
97
+ };
98
+ }
99
+ if (requestConfig.data) {
100
+ return {
101
+ contentType: "application/json",
102
+ body: JSON.stringify(requestConfig.data),
103
+ };
104
+ }
105
+ return {};
106
+ }
83
107
  /**
84
108
  * Send an unauthenticated request. Non-2xx responses and network/timeout
85
109
  * failures reject with an {@link ESPAPIError}.
@@ -100,18 +124,19 @@ class ESPRMAPIManager {
100
124
  requestUrl += `?${new URLSearchParams(queryEntries).toString()}`;
101
125
  }
102
126
  }
127
+ const { contentType, body } = ESPRMAPIManager.#serializeBody(requestConfig);
103
128
  const fetchOptions = {
104
129
  method: requestConfig.method,
105
130
  // The API never redirects. Following one would re-send the body (login
106
131
  // password, refresh token) to whatever host the redirect names.
107
132
  redirect: "error",
108
133
  headers: {
109
- ...(requestConfig.data ? { "Content-Type": "application/json" } : {}),
134
+ ...(contentType ? { "Content-Type": contentType } : {}),
110
135
  ...requestConfig.headers,
111
136
  },
112
137
  };
113
- if (requestConfig.data) {
114
- fetchOptions.body = JSON.stringify(requestConfig.data);
138
+ if (body !== undefined) {
139
+ fetchOptions.body = body;
115
140
  }
116
141
  const timeoutMs = requestConfig.timeoutMs ?? instance.#timeoutMs;
117
142
  let timer;
@@ -15,6 +15,7 @@ const APIEndpoints = {
15
15
  LOGIN: "login2",
16
16
  PASSWORD: "password2",
17
17
  LOGOUT: "logout2",
18
+ OAUTH_TOKEN: "token",
18
19
  ADMIN_USER: "admin/user2",
19
20
  ADMIN_USER_SUMMARY: "admin/user2/summary",
20
21
  ADMIN_NODES: "admin/nodes",
@@ -113,6 +114,9 @@ const ValidationErrorCodes = {
113
114
  MISSING_LOGIN_PASSWORD: "MISSING_LOGIN_PASSWORD",
114
115
  MISSING_USERNAME: "MISSING_USERNAME",
115
116
  MISSING_VERIFICATION_CODE: "MISSING_VERIFICATION_CODE",
117
+ MISSING_AUTHORIZATION_CODE: "MISSING_AUTHORIZATION_CODE",
118
+ MISSING_REDIRECT_URI: "MISSING_REDIRECT_URI",
119
+ MISSING_OAUTH_CLIENT_ID: "MISSING_OAUTH_CLIENT_ID",
116
120
  };
117
121
  const StorageAdapterErrorCodes = {
118
122
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API",
@@ -14,6 +14,9 @@ const validationErrorMessages = {
14
14
  MISSING_LOGIN_PASSWORD: "Validation Error: Password is required.",
15
15
  MISSING_USERNAME: "Validation Error: Username is required.",
16
16
  MISSING_VERIFICATION_CODE: "Validation Error: Verification code is required.",
17
+ MISSING_AUTHORIZATION_CODE: "Validation Error: Authorization code is required.",
18
+ MISSING_REDIRECT_URI: "Validation Error: Redirect URI is required.",
19
+ MISSING_OAUTH_CLIENT_ID: "Validation Error: OAuth client ID is required.",
17
20
  };
18
21
  const storageAdapterErrorMessages = {
19
22
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "ESPStorageAdapterError: It seems like your environment doesn't support window.localstorage, you can define your own storage adapter while configuring the ESPRMBase instance. Please refer docs for more information.",
@@ -9,8 +9,9 @@ const parseAPIErrorResponse = (error, statusCode) => {
9
9
  let description = "An error has occurred";
10
10
  if (error) {
11
11
  status = error.status ?? "";
12
- errorCode = error.error_code ?? "";
13
- description = error.description ?? "An error has occurred";
12
+ errorCode = error.error_code ?? error.error ?? "";
13
+ description =
14
+ error.description ?? error.error_description ?? "An error has occurred";
14
15
  }
15
16
  else {
16
17
  throw error;
@@ -3,12 +3,21 @@
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { GetOTAJobParams } from "../../types/ota.js";
7
- import { GetOTAJobsResponse } from "../../types/ota.js";
6
+ import { GetOTAJobByIdParams, GetOTAJobParams, GetOTAJobsResponse, OTAJobInfo } from "../../types/ota.js";
8
7
  declare module "../../ESPRMAdminOTAJob.js" {
9
8
  interface ESPRMAdminOTAJob {
10
9
  /**
11
- * Retrieves OTA jobs with optional filtering parameters.
10
+ * Retrieves a single OTA job by ID.
11
+ *
12
+ * @param params - The ID of the job to fetch.
13
+ * @returns The OTA job. The backend returns the job itself, not a list.
14
+ */
15
+ getJob(params: GetOTAJobByIdParams): Promise<OTAJobInfo>;
16
+ /**
17
+ * Retrieves a page of OTA jobs, optionally filtered by name or image.
18
+ *
19
+ * When nothing matches, the backend rejects with HTTP 404 and error code
20
+ * `105012` rather than returning an empty list.
12
21
  *
13
22
  * @param params - Optional query parameters to filter the job list.
14
23
  * @returns The list of OTA jobs matching the specified criteria.
@@ -0,0 +1,40 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ESPRMUser } from "../../ESPRMUser.js";
7
+ import { AuthorizationCodeLoginParams } from "../../types/auth.js";
8
+ declare module "../../ESPRMAuth.js" {
9
+ interface ESPRMAuth {
10
+ /**
11
+ * Complete an OAuth 2.0 authorization-code login (`response_type=code`)
12
+ * by exchanging the code returned on the redirect URI for tokens.
13
+ *
14
+ * Sends `POST {baseUrl}/token` (outside the API version path) as
15
+ * `application/x-www-form-urlencoded`, without an `Authorization` header.
16
+ * Stores the returned tokens like {@link ESPRMAuth.login}. When the server
17
+ * issues no refresh token, an empty one is stored, so the session ends
18
+ * when the access token expires.
19
+ *
20
+ * @param params - Authorization code plus the `redirect_uri` and
21
+ * `client_id` sent in the authorize request
22
+ * @returns A new {@link ESPRMUser} instance with active session tokens
23
+ * @throws ESPValidationError when `code`, `redirectUri` or `clientId` is empty
24
+ * @throws ESPAPIError on a non-2xx response, where `errorCode` carries the
25
+ * RFC 6749 `error` value (for example `invalid_grant`), or when a 2xx
26
+ * response lacks `access_token` or `id_token`
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const code = new URLSearchParams(window.location.search).get("code");
31
+ * const user = await ESPRMBase.getAuthInstance().loginWithAuthorizationCode({
32
+ * code,
33
+ * redirectUri: "https://dashboard.example.com/socialauth",
34
+ * clientId: "<OAUTH_CLIENT_ID>",
35
+ * });
36
+ * ```
37
+ */
38
+ loginWithAuthorizationCode(params: AuthorizationCodeLoginParams): Promise<ESPRMUser>;
39
+ }
40
+ }
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import "./Login.js";
7
+ import "./LoginWithAuthorizationCode.js";
7
8
  import "./Logout.js";
8
9
  import "./ForgotPassword.js";
9
10
  import "./ChangePassword.js";
@@ -13,6 +13,11 @@ export declare class ESPRMAPIManager {
13
13
  #private;
14
14
  private constructor();
15
15
  static initialize(config: ESPRMAPIManagerConfig): void;
16
+ /**
17
+ * Configured `baseUrl` without the API version segment, for the endpoints
18
+ * served outside `/{version}`, such as the OAuth `/token` endpoint.
19
+ */
20
+ static getRootUrl(): string;
16
21
  /**
17
22
  * Base URL of the claiming service set through `claimingBaseUrl`.
18
23
  *
@@ -84,3 +84,33 @@ export interface GetUserInfoResponse {
84
84
  locale?: string;
85
85
  tags?: string[];
86
86
  }
87
+ /** Parameters for {@link ESPRMAuth.loginWithAuthorizationCode}. */
88
+ export interface AuthorizationCodeLoginParams {
89
+ /** Authorization code from the `code` query parameter of the OAuth callback. */
90
+ code: string;
91
+ /** Redirect URI sent in the authorize request. Must match it exactly. */
92
+ redirectUri: string;
93
+ /** OAuth client ID sent in the authorize request. */
94
+ clientId: string;
95
+ }
96
+ /**
97
+ * Form body for `POST /token` with `grant_type=authorization_code`.
98
+ * A type alias, not an interface, so it is assignable to the
99
+ * `Record<string, string>` that `formData` takes.
100
+ */
101
+ export type AuthorizationCodeTokenRequest = {
102
+ grant_type: "authorization_code";
103
+ code: string;
104
+ redirect_uri: string;
105
+ client_id: string;
106
+ };
107
+ /** Successful `POST /token` response (RFC 6749 section 5.1). */
108
+ export interface OAuthTokenResponse {
109
+ access_token: string;
110
+ id_token: string;
111
+ /** Omitted or empty when the grant issues no refresh token. */
112
+ refresh_token?: string;
113
+ token_type?: string;
114
+ /** Access-token lifetime in seconds. */
115
+ expires_in?: number;
116
+ }
@@ -45,6 +45,11 @@ export interface ESPRMRequestConfig {
45
45
  method: string;
46
46
  /** Request body data (will be JSON-stringified). */
47
47
  data?: Record<string, unknown> | object;
48
+ /**
49
+ * Request body sent as `application/x-www-form-urlencoded`, for the OAuth
50
+ * endpoints. Takes precedence over `data` when both are set.
51
+ */
52
+ formData?: Record<string, string>;
48
53
  /** URL query parameters. */
49
54
  params?: Record<string, string> | object;
50
55
  /** Additional HTTP headers. */
@@ -8,7 +8,7 @@ export type { ESPRMBaseConfig, ESPRMAPIManagerConfig, UserTokensData } from "./c
8
8
  export type { SignUpRequest, ConfirmUserRequest, ChangePasswordRequest, ForgotPasswordRequest, ForgotPasswordConfirmRequest, LogoutRequest, UpdateUserProfileRequest, DeleteAccountParams, } from "./auth.js";
9
9
  export type { CreateAdminUserRequest, UpdateAdminUserRequest, GetAdminUsersParams, DeleteAdminUserParams, } from "./admin_user.js";
10
10
  export type { GetAdminNodesParams, ActivateDeactivateNodesParams, GetNodeTagsParams, NodeAttachTagsRequest, } from "./node.js";
11
- export type { CreateOTAImageRequest, GetOTAImagesParams, ArchiveOTAImageParams, DeleteOTAImageParams, GetOTAImageUploadUrlParams, ConfirmOTAImageUploadRequest, GetOTAPackageUploadUrlParams, ConfirmOTAPackageUploadRequest, CreateOTAJobRequest, CreateOTAJobQueryOptions, OtaJobDownloadWindow, OtaJobValidity, OtaJobMetadata, OtaSecureBoot, OtaNetworkSerialisation, GetOTAJobParams, UpdateOTAJobParams, CancelOTAJobRequest, ArchiveOTAJobRequest, GetOTAJobStatusParams, GetOTAJobStatusSummaryParams, RetriggerOTAJobRequest, } from "./ota.js";
11
+ export type { CreateOTAImageRequest, GetOTAImagesParams, ArchiveOTAImageParams, DeleteOTAImageParams, GetOTAImageUploadUrlParams, ConfirmOTAImageUploadRequest, GetOTAPackageUploadUrlParams, ConfirmOTAPackageUploadRequest, CreateOTAJobRequest, CreateOTAJobQueryOptions, OtaJobDownloadWindow, OtaJobValidity, OtaJobMetadata, OtaSecureBoot, OtaNetworkSerialisation, GetOTAJobParams, GetOTAJobByIdParams, UpdateOTAJobParams, CancelOTAJobRequest, ArchiveOTAJobRequest, GetOTAJobStatusParams, GetOTAJobStatusSummaryParams, RetriggerOTAJobRequest, } from "./ota.js";
12
12
  export type { CreateAdminGroupRequest, UpdateAdminGroupRequest, GetAdminGroupsParams, } from "./group.js";
13
13
  export type { GetAdminTagsParams, AttachDetachTagsParams, GetTagNamesParams, } from "./tag.js";
14
14
  export type { GetCommandRequestsParams, AddCommandRequestBody, CancelCommandRequestsParams, CommandRequestStatus, } from "./command_response.js";
@@ -159,14 +159,40 @@ export interface CreateOTAJobQueryOptions {
159
159
  /** Serialise OTA delivery per local network. */
160
160
  network_serialised?: boolean;
161
161
  }
162
- /** Parameters for listing OTA jobs. */
162
+ /**
163
+ * Parameters for listing or searching OTA jobs.
164
+ *
165
+ * Without a filter the backend returns a page of jobs, scoped by `archived`
166
+ * and `all`. `ota_job_name` and `ota_image_id` switch it to a search.
167
+ */
163
168
  export interface GetOTAJobParams {
164
- /** Filter by specific OTA job ID. */
169
+ /**
170
+ * Filter by specific OTA job ID.
171
+ *
172
+ * @deprecated The backend answers an ID lookup with a single job, not a
173
+ * list. Pass {@link GetOTAJobByIdParams} so `getJob` returns `OTAJobInfo`.
174
+ */
165
175
  ota_job_id?: string;
166
- /** Maximum number of records to return. */
176
+ /**
177
+ * Return jobs whose name contains this text. Case-sensitive. Covers archived
178
+ * and unarchived jobs alike: `archived` and `all` are ignored.
179
+ */
180
+ ota_job_name?: string;
181
+ /** Return every job created from this OTA image. Honours `archived`. */
182
+ ota_image_id?: string;
183
+ /** Maximum number of records to return (backend default and maximum: 25). */
167
184
  num_records?: string;
168
- /** Job ID to start pagination from. */
185
+ /** Job ID to start pagination from (the previous page's `next_id`). */
169
186
  start_id?: string;
187
+ /** List archived jobs instead of unarchived ones. Defaults to `false`. */
188
+ archived?: boolean;
189
+ /** List archived and unarchived jobs together. Defaults to `false`. */
190
+ all?: boolean;
191
+ }
192
+ /** Parameters for fetching a single OTA job by ID. */
193
+ export interface GetOTAJobByIdParams {
194
+ /** ID of the OTA job to fetch. */
195
+ ota_job_id: string;
170
196
  }
171
197
  /** Parameters for updating an OTA job. */
172
198
  export interface UpdateOTAJobParams {
@@ -368,11 +394,19 @@ export interface OTAJobRetriggerResponse {
368
394
  }
369
395
  /** Paginated response containing a list of OTA jobs. */
370
396
  export interface GetOTAJobsResponse {
371
- /** List of OTA job objects. */
372
- ota_update_jobs?: OTAJobInfo[];
373
- /** ID to use for fetching the next page. */
397
+ /** OTA jobs on this page. */
398
+ otaJobs?: OTAJobInfo[];
399
+ /** ID to use for fetching the next page. Absent on the last page. */
374
400
  next_id?: string;
375
- /** Total number of jobs matching the query. */
401
+ /**
402
+ * @deprecated Never returned by the backend; read `otaJobs` instead.
403
+ * Will be removed in the next minor release.
404
+ */
405
+ ota_update_jobs?: OTAJobInfo[];
406
+ /**
407
+ * @deprecated Never returned by the backend. Will be removed in the next
408
+ * minor release.
409
+ */
376
410
  total?: number;
377
411
  }
378
412
  /** Per-node OTA status row (GET admin/otajob/status). */
@@ -15,6 +15,7 @@ declare const APIEndpoints: {
15
15
  readonly LOGIN: "login2";
16
16
  readonly PASSWORD: "password2";
17
17
  readonly LOGOUT: "logout2";
18
+ readonly OAUTH_TOKEN: "token";
18
19
  readonly ADMIN_USER: "admin/user2";
19
20
  readonly ADMIN_USER_SUMMARY: "admin/user2/summary";
20
21
  readonly ADMIN_NODES: "admin/nodes";
@@ -113,6 +114,9 @@ declare const ValidationErrorCodes: {
113
114
  readonly MISSING_LOGIN_PASSWORD: "MISSING_LOGIN_PASSWORD";
114
115
  readonly MISSING_USERNAME: "MISSING_USERNAME";
115
116
  readonly MISSING_VERIFICATION_CODE: "MISSING_VERIFICATION_CODE";
117
+ readonly MISSING_AUTHORIZATION_CODE: "MISSING_AUTHORIZATION_CODE";
118
+ readonly MISSING_REDIRECT_URI: "MISSING_REDIRECT_URI";
119
+ readonly MISSING_OAUTH_CLIENT_ID: "MISSING_OAUTH_CLIENT_ID";
116
120
  };
117
121
  declare const StorageAdapterErrorCodes: {
118
122
  readonly UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API";
@@ -14,6 +14,9 @@ declare const validationErrorMessages: {
14
14
  MISSING_LOGIN_PASSWORD: string;
15
15
  MISSING_USERNAME: string;
16
16
  MISSING_VERIFICATION_CODE: string;
17
+ MISSING_AUTHORIZATION_CODE: string;
18
+ MISSING_REDIRECT_URI: string;
19
+ MISSING_OAUTH_CLIENT_ID: string;
17
20
  };
18
21
  declare const storageAdapterErrorMessages: {
19
22
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: string;
@@ -8,6 +8,10 @@ interface RawAPIErrorBody {
8
8
  status?: string;
9
9
  error_code?: string;
10
10
  description?: string;
11
+ /** RFC 6749 error code, returned by the OAuth endpoints instead of `error_code`. */
12
+ error?: string;
13
+ /** RFC 6749 error text, returned by the OAuth endpoints instead of `description`. */
14
+ error_description?: string;
11
15
  }
12
16
  declare const parseAPIErrorResponse: (error: RawAPIErrorBody, statusCode: number) => ESPAPIError;
13
17
  export { parseAPIErrorResponse };
@@ -3,12 +3,21 @@
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { GetOTAJobParams } from "../../types/ota.cjs";
7
- import { GetOTAJobsResponse } from "../../types/ota.cjs";
6
+ import { GetOTAJobByIdParams, GetOTAJobParams, GetOTAJobsResponse, OTAJobInfo } from "../../types/ota.cjs";
8
7
  declare module "../../ESPRMAdminOTAJob.cjs" {
9
8
  interface ESPRMAdminOTAJob {
10
9
  /**
11
- * Retrieves OTA jobs with optional filtering parameters.
10
+ * Retrieves a single OTA job by ID.
11
+ *
12
+ * @param params - The ID of the job to fetch.
13
+ * @returns The OTA job. The backend returns the job itself, not a list.
14
+ */
15
+ getJob(params: GetOTAJobByIdParams): Promise<OTAJobInfo>;
16
+ /**
17
+ * Retrieves a page of OTA jobs, optionally filtered by name or image.
18
+ *
19
+ * When nothing matches, the backend rejects with HTTP 404 and error code
20
+ * `105012` rather than returning an empty list.
12
21
  *
13
22
  * @param params - Optional query parameters to filter the job list.
14
23
  * @returns The list of OTA jobs matching the specified criteria.
@@ -0,0 +1,40 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ESPRMUser } from "../../ESPRMUser.cjs";
7
+ import { AuthorizationCodeLoginParams } from "../../types/auth.cjs";
8
+ declare module "../../ESPRMAuth.cjs" {
9
+ interface ESPRMAuth {
10
+ /**
11
+ * Complete an OAuth 2.0 authorization-code login (`response_type=code`)
12
+ * by exchanging the code returned on the redirect URI for tokens.
13
+ *
14
+ * Sends `POST {baseUrl}/token` (outside the API version path) as
15
+ * `application/x-www-form-urlencoded`, without an `Authorization` header.
16
+ * Stores the returned tokens like {@link ESPRMAuth.login}. When the server
17
+ * issues no refresh token, an empty one is stored, so the session ends
18
+ * when the access token expires.
19
+ *
20
+ * @param params - Authorization code plus the `redirect_uri` and
21
+ * `client_id` sent in the authorize request
22
+ * @returns A new {@link ESPRMUser} instance with active session tokens
23
+ * @throws ESPValidationError when `code`, `redirectUri` or `clientId` is empty
24
+ * @throws ESPAPIError on a non-2xx response, where `errorCode` carries the
25
+ * RFC 6749 `error` value (for example `invalid_grant`), or when a 2xx
26
+ * response lacks `access_token` or `id_token`
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const code = new URLSearchParams(window.location.search).get("code");
31
+ * const user = await ESPRMBase.getAuthInstance().loginWithAuthorizationCode({
32
+ * code,
33
+ * redirectUri: "https://dashboard.example.com/socialauth",
34
+ * clientId: "<OAUTH_CLIENT_ID>",
35
+ * });
36
+ * ```
37
+ */
38
+ loginWithAuthorizationCode(params: AuthorizationCodeLoginParams): Promise<ESPRMUser>;
39
+ }
40
+ }
@@ -4,6 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import "./Login.cjs";
7
+ import "./LoginWithAuthorizationCode.cjs";
7
8
  import "./Logout.cjs";
8
9
  import "./ForgotPassword.cjs";
9
10
  import "./ChangePassword.cjs";
@@ -13,6 +13,11 @@ export declare class ESPRMAPIManager {
13
13
  #private;
14
14
  private constructor();
15
15
  static initialize(config: ESPRMAPIManagerConfig): void;
16
+ /**
17
+ * Configured `baseUrl` without the API version segment, for the endpoints
18
+ * served outside `/{version}`, such as the OAuth `/token` endpoint.
19
+ */
20
+ static getRootUrl(): string;
16
21
  /**
17
22
  * Base URL of the claiming service set through `claimingBaseUrl`.
18
23
  *
@@ -84,3 +84,33 @@ export interface GetUserInfoResponse {
84
84
  locale?: string;
85
85
  tags?: string[];
86
86
  }
87
+ /** Parameters for {@link ESPRMAuth.loginWithAuthorizationCode}. */
88
+ export interface AuthorizationCodeLoginParams {
89
+ /** Authorization code from the `code` query parameter of the OAuth callback. */
90
+ code: string;
91
+ /** Redirect URI sent in the authorize request. Must match it exactly. */
92
+ redirectUri: string;
93
+ /** OAuth client ID sent in the authorize request. */
94
+ clientId: string;
95
+ }
96
+ /**
97
+ * Form body for `POST /token` with `grant_type=authorization_code`.
98
+ * A type alias, not an interface, so it is assignable to the
99
+ * `Record<string, string>` that `formData` takes.
100
+ */
101
+ export type AuthorizationCodeTokenRequest = {
102
+ grant_type: "authorization_code";
103
+ code: string;
104
+ redirect_uri: string;
105
+ client_id: string;
106
+ };
107
+ /** Successful `POST /token` response (RFC 6749 section 5.1). */
108
+ export interface OAuthTokenResponse {
109
+ access_token: string;
110
+ id_token: string;
111
+ /** Omitted or empty when the grant issues no refresh token. */
112
+ refresh_token?: string;
113
+ token_type?: string;
114
+ /** Access-token lifetime in seconds. */
115
+ expires_in?: number;
116
+ }
@@ -45,6 +45,11 @@ export interface ESPRMRequestConfig {
45
45
  method: string;
46
46
  /** Request body data (will be JSON-stringified). */
47
47
  data?: Record<string, unknown> | object;
48
+ /**
49
+ * Request body sent as `application/x-www-form-urlencoded`, for the OAuth
50
+ * endpoints. Takes precedence over `data` when both are set.
51
+ */
52
+ formData?: Record<string, string>;
48
53
  /** URL query parameters. */
49
54
  params?: Record<string, string> | object;
50
55
  /** Additional HTTP headers. */
@@ -8,7 +8,7 @@ export type { ESPRMBaseConfig, ESPRMAPIManagerConfig, UserTokensData } from "./c
8
8
  export type { SignUpRequest, ConfirmUserRequest, ChangePasswordRequest, ForgotPasswordRequest, ForgotPasswordConfirmRequest, LogoutRequest, UpdateUserProfileRequest, DeleteAccountParams, } from "./auth.cjs";
9
9
  export type { CreateAdminUserRequest, UpdateAdminUserRequest, GetAdminUsersParams, DeleteAdminUserParams, } from "./admin_user.cjs";
10
10
  export type { GetAdminNodesParams, ActivateDeactivateNodesParams, GetNodeTagsParams, NodeAttachTagsRequest, } from "./node.cjs";
11
- export type { CreateOTAImageRequest, GetOTAImagesParams, ArchiveOTAImageParams, DeleteOTAImageParams, GetOTAImageUploadUrlParams, ConfirmOTAImageUploadRequest, GetOTAPackageUploadUrlParams, ConfirmOTAPackageUploadRequest, CreateOTAJobRequest, CreateOTAJobQueryOptions, OtaJobDownloadWindow, OtaJobValidity, OtaJobMetadata, OtaSecureBoot, OtaNetworkSerialisation, GetOTAJobParams, UpdateOTAJobParams, CancelOTAJobRequest, ArchiveOTAJobRequest, GetOTAJobStatusParams, GetOTAJobStatusSummaryParams, RetriggerOTAJobRequest, } from "./ota.cjs";
11
+ export type { CreateOTAImageRequest, GetOTAImagesParams, ArchiveOTAImageParams, DeleteOTAImageParams, GetOTAImageUploadUrlParams, ConfirmOTAImageUploadRequest, GetOTAPackageUploadUrlParams, ConfirmOTAPackageUploadRequest, CreateOTAJobRequest, CreateOTAJobQueryOptions, OtaJobDownloadWindow, OtaJobValidity, OtaJobMetadata, OtaSecureBoot, OtaNetworkSerialisation, GetOTAJobParams, GetOTAJobByIdParams, UpdateOTAJobParams, CancelOTAJobRequest, ArchiveOTAJobRequest, GetOTAJobStatusParams, GetOTAJobStatusSummaryParams, RetriggerOTAJobRequest, } from "./ota.cjs";
12
12
  export type { CreateAdminGroupRequest, UpdateAdminGroupRequest, GetAdminGroupsParams, } from "./group.cjs";
13
13
  export type { GetAdminTagsParams, AttachDetachTagsParams, GetTagNamesParams, } from "./tag.cjs";
14
14
  export type { GetCommandRequestsParams, AddCommandRequestBody, CancelCommandRequestsParams, CommandRequestStatus, } from "./command_response.cjs";
@@ -159,14 +159,40 @@ export interface CreateOTAJobQueryOptions {
159
159
  /** Serialise OTA delivery per local network. */
160
160
  network_serialised?: boolean;
161
161
  }
162
- /** Parameters for listing OTA jobs. */
162
+ /**
163
+ * Parameters for listing or searching OTA jobs.
164
+ *
165
+ * Without a filter the backend returns a page of jobs, scoped by `archived`
166
+ * and `all`. `ota_job_name` and `ota_image_id` switch it to a search.
167
+ */
163
168
  export interface GetOTAJobParams {
164
- /** Filter by specific OTA job ID. */
169
+ /**
170
+ * Filter by specific OTA job ID.
171
+ *
172
+ * @deprecated The backend answers an ID lookup with a single job, not a
173
+ * list. Pass {@link GetOTAJobByIdParams} so `getJob` returns `OTAJobInfo`.
174
+ */
165
175
  ota_job_id?: string;
166
- /** Maximum number of records to return. */
176
+ /**
177
+ * Return jobs whose name contains this text. Case-sensitive. Covers archived
178
+ * and unarchived jobs alike: `archived` and `all` are ignored.
179
+ */
180
+ ota_job_name?: string;
181
+ /** Return every job created from this OTA image. Honours `archived`. */
182
+ ota_image_id?: string;
183
+ /** Maximum number of records to return (backend default and maximum: 25). */
167
184
  num_records?: string;
168
- /** Job ID to start pagination from. */
185
+ /** Job ID to start pagination from (the previous page's `next_id`). */
169
186
  start_id?: string;
187
+ /** List archived jobs instead of unarchived ones. Defaults to `false`. */
188
+ archived?: boolean;
189
+ /** List archived and unarchived jobs together. Defaults to `false`. */
190
+ all?: boolean;
191
+ }
192
+ /** Parameters for fetching a single OTA job by ID. */
193
+ export interface GetOTAJobByIdParams {
194
+ /** ID of the OTA job to fetch. */
195
+ ota_job_id: string;
170
196
  }
171
197
  /** Parameters for updating an OTA job. */
172
198
  export interface UpdateOTAJobParams {
@@ -368,11 +394,19 @@ export interface OTAJobRetriggerResponse {
368
394
  }
369
395
  /** Paginated response containing a list of OTA jobs. */
370
396
  export interface GetOTAJobsResponse {
371
- /** List of OTA job objects. */
372
- ota_update_jobs?: OTAJobInfo[];
373
- /** ID to use for fetching the next page. */
397
+ /** OTA jobs on this page. */
398
+ otaJobs?: OTAJobInfo[];
399
+ /** ID to use for fetching the next page. Absent on the last page. */
374
400
  next_id?: string;
375
- /** Total number of jobs matching the query. */
401
+ /**
402
+ * @deprecated Never returned by the backend; read `otaJobs` instead.
403
+ * Will be removed in the next minor release.
404
+ */
405
+ ota_update_jobs?: OTAJobInfo[];
406
+ /**
407
+ * @deprecated Never returned by the backend. Will be removed in the next
408
+ * minor release.
409
+ */
376
410
  total?: number;
377
411
  }
378
412
  /** Per-node OTA status row (GET admin/otajob/status). */
@@ -15,6 +15,7 @@ declare const APIEndpoints: {
15
15
  readonly LOGIN: "login2";
16
16
  readonly PASSWORD: "password2";
17
17
  readonly LOGOUT: "logout2";
18
+ readonly OAUTH_TOKEN: "token";
18
19
  readonly ADMIN_USER: "admin/user2";
19
20
  readonly ADMIN_USER_SUMMARY: "admin/user2/summary";
20
21
  readonly ADMIN_NODES: "admin/nodes";
@@ -113,6 +114,9 @@ declare const ValidationErrorCodes: {
113
114
  readonly MISSING_LOGIN_PASSWORD: "MISSING_LOGIN_PASSWORD";
114
115
  readonly MISSING_USERNAME: "MISSING_USERNAME";
115
116
  readonly MISSING_VERIFICATION_CODE: "MISSING_VERIFICATION_CODE";
117
+ readonly MISSING_AUTHORIZATION_CODE: "MISSING_AUTHORIZATION_CODE";
118
+ readonly MISSING_REDIRECT_URI: "MISSING_REDIRECT_URI";
119
+ readonly MISSING_OAUTH_CLIENT_ID: "MISSING_OAUTH_CLIENT_ID";
116
120
  };
117
121
  declare const StorageAdapterErrorCodes: {
118
122
  readonly UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: "UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API";
@@ -14,6 +14,9 @@ declare const validationErrorMessages: {
14
14
  MISSING_LOGIN_PASSWORD: string;
15
15
  MISSING_USERNAME: string;
16
16
  MISSING_VERIFICATION_CODE: string;
17
+ MISSING_AUTHORIZATION_CODE: string;
18
+ MISSING_REDIRECT_URI: string;
19
+ MISSING_OAUTH_CLIENT_ID: string;
17
20
  };
18
21
  declare const storageAdapterErrorMessages: {
19
22
  UNSUPPORTED_DEFAULT_STORAGE_ADAPTER_API: string;
@@ -8,6 +8,10 @@ interface RawAPIErrorBody {
8
8
  status?: string;
9
9
  error_code?: string;
10
10
  description?: string;
11
+ /** RFC 6749 error code, returned by the OAuth endpoints instead of `error_code`. */
12
+ error?: string;
13
+ /** RFC 6749 error text, returned by the OAuth endpoints instead of `description`. */
14
+ error_description?: string;
11
15
  }
12
16
  declare const parseAPIErrorResponse: (error: RawAPIErrorBody, statusCode: number) => ESPAPIError;
13
17
  export { parseAPIErrorResponse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@espressif/rainmaker-admin-sdk",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Espressif's Rainmaker Admin SDK enables seamless integration of admin applications with the ESP Rainmaker ecosystem.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Espressif Systems (Shanghai) CO LTD",