@espressif/rainmaker-admin-sdk 1.3.1 → 1.5.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.
- package/CHANGELOG.md +55 -0
- package/dist/cjs/entries/ESPRMAuth.cjs +1 -0
- package/dist/cjs/entries/ESPRMBase.cjs +1 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/methods/ESPRMAdminDeploymentCapability/GetDeploymentCapabilities.cjs +2 -1
- package/dist/cjs/methods/ESPRMAuth/LoginWithAuthorizationCode.cjs +54 -0
- package/dist/cjs/services/ESPRMAPIManager.cjs +29 -4
- package/dist/cjs/utils/constants.cjs +4 -0
- package/dist/cjs/utils/error/errorMessages.cjs +3 -0
- package/dist/cjs/utils/error/parser.cjs +3 -2
- package/dist/esm/entries/ESPRMAuth.js +1 -0
- package/dist/esm/entries/ESPRMBase.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/methods/ESPRMAdminDeploymentCapability/GetDeploymentCapabilities.js +2 -1
- package/dist/esm/methods/ESPRMAuth/LoginWithAuthorizationCode.js +52 -0
- package/dist/esm/services/ESPRMAPIManager.js +29 -4
- package/dist/esm/utils/constants.js +4 -0
- package/dist/esm/utils/error/errorMessages.js +3 -0
- package/dist/esm/utils/error/parser.js +3 -2
- package/dist/types/methods/ESPRMAdminDeploymentCapability/GetDeploymentCapabilities.d.ts +6 -4
- package/dist/types/methods/ESPRMAuth/LoginWithAuthorizationCode.d.ts +40 -0
- package/dist/types/methods/ESPRMAuth/index.d.ts +1 -0
- package/dist/types/services/ESPRMAPIManager.d.ts +5 -0
- package/dist/types/types/auth.d.ts +30 -0
- package/dist/types/types/config.d.ts +5 -0
- package/dist/types/types/deployment_capability.d.ts +6 -5
- package/dist/types/types/input.d.ts +1 -1
- package/dist/types/utils/constants.d.ts +4 -0
- package/dist/types/utils/error/errorMessages.d.ts +3 -0
- package/dist/types/utils/error/parser.d.ts +6 -1
- package/dist/types-cjs/methods/ESPRMAdminDeploymentCapability/GetDeploymentCapabilities.d.cts +6 -4
- package/dist/types-cjs/methods/ESPRMAuth/LoginWithAuthorizationCode.d.cts +40 -0
- package/dist/types-cjs/methods/ESPRMAuth/index.d.cts +1 -0
- package/dist/types-cjs/services/ESPRMAPIManager.d.cts +5 -0
- package/dist/types-cjs/types/auth.d.cts +30 -0
- package/dist/types-cjs/types/config.d.cts +5 -0
- package/dist/types-cjs/types/deployment_capability.d.cts +6 -5
- package/dist/types-cjs/types/input.d.cts +1 -1
- package/dist/types-cjs/utils/constants.d.cts +4 -0
- package/dist/types-cjs/utils/error/errorMessages.d.cts +3 -0
- package/dist/types-cjs/utils/error/parser.d.cts +6 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,61 @@
|
|
|
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.5.0] - 2026-10-08
|
|
7
|
+
|
|
8
|
+
Minor release that lets callers fetch a single deployment capability by name,
|
|
9
|
+
which the dashboards use to read the ESP Insights URL. Calling
|
|
10
|
+
`getDeploymentCapabilities()` without arguments is unchanged; the two type
|
|
11
|
+
corrections below are fixes, one of which changes `errorCode` at runtime.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `ESPRMAdminDeploymentCapability.getDeploymentCapabilities({ name })` fetches
|
|
16
|
+
a single capability by name (`GET admin/deployment_capabilities?name=`).
|
|
17
|
+
The parameter is optional; calling it without arguments is unchanged. The
|
|
18
|
+
backend rejects an unknown name with error code `122005`.
|
|
19
|
+
- Type `GetDeploymentCapabilitiesParams`.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- `GetDeploymentCapabilitiesResponse` is now `DeploymentCapabilityInfo[]`. The
|
|
24
|
+
backend has always returned a top-level array; the old
|
|
25
|
+
`{ capabilities: [...] }` shape never matched the response.
|
|
26
|
+
- `ESPAPIError.errorCode` is now always a string, as its type declares. The
|
|
27
|
+
RainMaker backend sends `error_code` as a number, which the SDK passed
|
|
28
|
+
through unchanged, so `errorCode === "122005"` was false at runtime. Callers
|
|
29
|
+
that compared against a number must compare against the string instead.
|
|
30
|
+
|
|
31
|
+
## [1.4.0] - 2026-10-07
|
|
32
|
+
|
|
33
|
+
Minor release that adds OAuth 2.0 authorization-code login, so dashboards can
|
|
34
|
+
complete social sign-in that uses `response_type=code` (WeChat on China
|
|
35
|
+
deployments) through the SDK instead of calling `/token` themselves. Existing
|
|
36
|
+
methods keep their signatures; the two behaviour changes below are fixes.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- `ESPRMAuth.loginWithAuthorizationCode({ code, redirectUri, clientId })`
|
|
41
|
+
completes an OAuth 2.0 authorization-code login (`response_type=code`, used
|
|
42
|
+
by WeChat sign-in on China deployments). It sends a form-encoded
|
|
43
|
+
`POST {baseUrl}/token` and stores the returned tokens like `login()`. When
|
|
44
|
+
no refresh token is issued, an empty one is stored.
|
|
45
|
+
- `ESPRMRequestConfig.formData` sends a request body as
|
|
46
|
+
`application/x-www-form-urlencoded`.
|
|
47
|
+
- `ESPRMAPIManager.getRootUrl()` returns the configured `baseUrl` without the
|
|
48
|
+
API version segment.
|
|
49
|
+
- Types `AuthorizationCodeLoginParams`, `AuthorizationCodeTokenRequest` and
|
|
50
|
+
`OAuthTokenResponse`, and validation codes `MISSING_AUTHORIZATION_CODE`,
|
|
51
|
+
`MISSING_REDIRECT_URI` and `MISSING_OAUTH_CLIENT_ID`.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- `ESPAPIError` now reads RFC 6749 error bodies too. `errorCode` falls back to
|
|
56
|
+
`error`, and `description` falls back to `error_description`, when the
|
|
57
|
+
RainMaker `error_code` / `description` fields are absent.
|
|
58
|
+
- A trailing slash on `baseUrl` is now removed before the version segment is
|
|
59
|
+
appended. Before, it produced a double slash such as `https://host//v1`.
|
|
60
|
+
|
|
6
61
|
## [1.3.1] - 2026-10-07
|
|
7
62
|
|
|
8
63
|
Patch release that corrects the OTA job list types in `ESPRMAdminOTAJob.getJob`
|
|
@@ -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');
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -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');
|
|
@@ -10,10 +10,11 @@ var ESPRMAPIManager = require('../../services/ESPRMAPIManager.cjs');
|
|
|
10
10
|
var constants = require('../../utils/constants.cjs');
|
|
11
11
|
|
|
12
12
|
ESPRMAdminDeploymentCapability.ESPRMAdminDeploymentCapability.prototype.getDeploymentCapabilities =
|
|
13
|
-
async function () {
|
|
13
|
+
async function (params) {
|
|
14
14
|
const requestConfig = {
|
|
15
15
|
url: constants.APIEndpoints.ADMIN_DEPLOYMENT_CAPABILITIES,
|
|
16
16
|
method: constants.HTTPMethods.GET,
|
|
17
|
+
...(params && { params }),
|
|
17
18
|
};
|
|
18
19
|
const response = await ESPRMAPIManager.ESPRMAPIManager.authorizeRequest(requestConfig);
|
|
19
20
|
return response;
|
|
@@ -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.#
|
|
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
|
-
...(
|
|
136
|
+
...(contentType ? { "Content-Type": contentType } : {}),
|
|
112
137
|
...requestConfig.headers,
|
|
113
138
|
},
|
|
114
139
|
};
|
|
115
|
-
if (
|
|
116
|
-
fetchOptions.body =
|
|
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 =
|
|
14
|
+
errorCode = String(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';
|
|
@@ -8,10 +8,11 @@ import { ESPRMAPIManager } from '../../services/ESPRMAPIManager.js';
|
|
|
8
8
|
import { HTTPMethods, APIEndpoints } from '../../utils/constants.js';
|
|
9
9
|
|
|
10
10
|
ESPRMAdminDeploymentCapability.prototype.getDeploymentCapabilities =
|
|
11
|
-
async function () {
|
|
11
|
+
async function (params) {
|
|
12
12
|
const requestConfig = {
|
|
13
13
|
url: APIEndpoints.ADMIN_DEPLOYMENT_CAPABILITIES,
|
|
14
14
|
method: HTTPMethods.GET,
|
|
15
|
+
...(params && { params }),
|
|
15
16
|
};
|
|
16
17
|
const response = await ESPRMAPIManager.authorizeRequest(requestConfig);
|
|
17
18
|
return response;
|
|
@@ -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.#
|
|
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
|
-
...(
|
|
134
|
+
...(contentType ? { "Content-Type": contentType } : {}),
|
|
110
135
|
...requestConfig.headers,
|
|
111
136
|
},
|
|
112
137
|
};
|
|
113
|
-
if (
|
|
114
|
-
fetchOptions.body =
|
|
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 =
|
|
12
|
+
errorCode = String(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,14 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { GetDeploymentCapabilitiesResponse } from "../../types/deployment_capability.js";
|
|
6
|
+
import { GetDeploymentCapabilitiesParams, GetDeploymentCapabilitiesResponse } from "../../types/deployment_capability.js";
|
|
7
7
|
declare module "../../ESPRMAdminDeploymentCapability.js" {
|
|
8
8
|
interface ESPRMAdminDeploymentCapability {
|
|
9
9
|
/**
|
|
10
|
-
* Retrieves the
|
|
10
|
+
* Retrieves the deployment capabilities of the current deployment.
|
|
11
11
|
*
|
|
12
|
-
* @
|
|
12
|
+
* @param params - Optional filter. Pass `name` to fetch a single capability.
|
|
13
|
+
* @returns The matching capabilities. The backend rejects an unknown `name`
|
|
14
|
+
* with error code 122005 instead of returning an empty list.
|
|
13
15
|
*/
|
|
14
|
-
getDeploymentCapabilities(): Promise<GetDeploymentCapabilitiesResponse>;
|
|
16
|
+
getDeploymentCapabilities(params?: GetDeploymentCapabilitiesParams): Promise<GetDeploymentCapabilitiesResponse>;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -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
|
+
}
|
|
@@ -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. */
|
|
@@ -17,9 +17,10 @@ export interface DeploymentCapabilityInfo {
|
|
|
17
17
|
/** The capability value. */
|
|
18
18
|
value?: string;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
export interface
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
[key: string]: unknown;
|
|
20
|
+
/** Query parameters for fetching deployment capabilities. */
|
|
21
|
+
export interface GetDeploymentCapabilitiesParams {
|
|
22
|
+
/** Fetch only the capability with this name. */
|
|
23
|
+
name?: string;
|
|
25
24
|
}
|
|
25
|
+
/** Deployment capabilities, returned by the backend as a top-level array. */
|
|
26
|
+
export type GetDeploymentCapabilitiesResponse = DeploymentCapabilityInfo[];
|
|
@@ -49,7 +49,7 @@ export type { GetMailFailuresParams } from "./mail_failure.js";
|
|
|
49
49
|
export type { UpdateTermsPolicyRequest, GetTermsPolicyParams, DeleteTermsPolicyParams, } from "./terms_policy.js";
|
|
50
50
|
export type { AddCloudwatchLogUserRequest } from "./cloudwatch_log.js";
|
|
51
51
|
export type { UpdateLogConfigRequest } from "./log_config.js";
|
|
52
|
-
export type { UpdateDeploymentCapabilityRequest } from "./deployment_capability.js";
|
|
52
|
+
export type { GetDeploymentCapabilitiesParams, UpdateDeploymentCapabilityRequest, } from "./deployment_capability.js";
|
|
53
53
|
export type { GetAPIStatisticsParams } from "./api_statistics.js";
|
|
54
54
|
export type { GetMQTTStatisticsParams } from "./mqtt_statistics.js";
|
|
55
55
|
export type { CreateMatterAuthRequest, CreateMatterBatchRequest, UpdateMatterBatchRequest, GetMatterBatchParams, GetMatterBatchNodesParams, } from "./matter.js";
|
|
@@ -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;
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
import { ESPAPIError } from "../../types/api.js";
|
|
7
7
|
interface RawAPIErrorBody {
|
|
8
8
|
status?: string;
|
|
9
|
-
|
|
9
|
+
/** The RainMaker backend sends a number; some endpoints send a string. */
|
|
10
|
+
error_code?: string | number;
|
|
10
11
|
description?: string;
|
|
12
|
+
/** RFC 6749 error code, returned by the OAuth endpoints instead of `error_code`. */
|
|
13
|
+
error?: string;
|
|
14
|
+
/** RFC 6749 error text, returned by the OAuth endpoints instead of `description`. */
|
|
15
|
+
error_description?: string;
|
|
11
16
|
}
|
|
12
17
|
declare const parseAPIErrorResponse: (error: RawAPIErrorBody, statusCode: number) => ESPAPIError;
|
|
13
18
|
export { parseAPIErrorResponse };
|
package/dist/types-cjs/methods/ESPRMAdminDeploymentCapability/GetDeploymentCapabilities.d.cts
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { GetDeploymentCapabilitiesResponse } from "../../types/deployment_capability.cjs";
|
|
6
|
+
import { GetDeploymentCapabilitiesParams, GetDeploymentCapabilitiesResponse } from "../../types/deployment_capability.cjs";
|
|
7
7
|
declare module "../../ESPRMAdminDeploymentCapability.cjs" {
|
|
8
8
|
interface ESPRMAdminDeploymentCapability {
|
|
9
9
|
/**
|
|
10
|
-
* Retrieves the
|
|
10
|
+
* Retrieves the deployment capabilities of the current deployment.
|
|
11
11
|
*
|
|
12
|
-
* @
|
|
12
|
+
* @param params - Optional filter. Pass `name` to fetch a single capability.
|
|
13
|
+
* @returns The matching capabilities. The backend rejects an unknown `name`
|
|
14
|
+
* with error code 122005 instead of returning an empty list.
|
|
13
15
|
*/
|
|
14
|
-
getDeploymentCapabilities(): Promise<GetDeploymentCapabilitiesResponse>;
|
|
16
|
+
getDeploymentCapabilities(params?: GetDeploymentCapabilitiesParams): Promise<GetDeploymentCapabilitiesResponse>;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -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
|
+
}
|
|
@@ -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. */
|
|
@@ -17,9 +17,10 @@ export interface DeploymentCapabilityInfo {
|
|
|
17
17
|
/** The capability value. */
|
|
18
18
|
value?: string;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
export interface
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
[key: string]: unknown;
|
|
20
|
+
/** Query parameters for fetching deployment capabilities. */
|
|
21
|
+
export interface GetDeploymentCapabilitiesParams {
|
|
22
|
+
/** Fetch only the capability with this name. */
|
|
23
|
+
name?: string;
|
|
25
24
|
}
|
|
25
|
+
/** Deployment capabilities, returned by the backend as a top-level array. */
|
|
26
|
+
export type GetDeploymentCapabilitiesResponse = DeploymentCapabilityInfo[];
|
|
@@ -49,7 +49,7 @@ export type { GetMailFailuresParams } from "./mail_failure.cjs";
|
|
|
49
49
|
export type { UpdateTermsPolicyRequest, GetTermsPolicyParams, DeleteTermsPolicyParams, } from "./terms_policy.cjs";
|
|
50
50
|
export type { AddCloudwatchLogUserRequest } from "./cloudwatch_log.cjs";
|
|
51
51
|
export type { UpdateLogConfigRequest } from "./log_config.cjs";
|
|
52
|
-
export type { UpdateDeploymentCapabilityRequest } from "./deployment_capability.cjs";
|
|
52
|
+
export type { GetDeploymentCapabilitiesParams, UpdateDeploymentCapabilityRequest, } from "./deployment_capability.cjs";
|
|
53
53
|
export type { GetAPIStatisticsParams } from "./api_statistics.cjs";
|
|
54
54
|
export type { GetMQTTStatisticsParams } from "./mqtt_statistics.cjs";
|
|
55
55
|
export type { CreateMatterAuthRequest, CreateMatterBatchRequest, UpdateMatterBatchRequest, GetMatterBatchParams, GetMatterBatchNodesParams, } from "./matter.cjs";
|
|
@@ -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;
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
import { ESPAPIError } from "../../types/api.cjs";
|
|
7
7
|
interface RawAPIErrorBody {
|
|
8
8
|
status?: string;
|
|
9
|
-
|
|
9
|
+
/** The RainMaker backend sends a number; some endpoints send a string. */
|
|
10
|
+
error_code?: string | number;
|
|
10
11
|
description?: string;
|
|
12
|
+
/** RFC 6749 error code, returned by the OAuth endpoints instead of `error_code`. */
|
|
13
|
+
error?: string;
|
|
14
|
+
/** RFC 6749 error text, returned by the OAuth endpoints instead of `description`. */
|
|
15
|
+
error_description?: string;
|
|
11
16
|
}
|
|
12
17
|
declare const parseAPIErrorResponse: (error: RawAPIErrorBody, statusCode: number) => ESPAPIError;
|
|
13
18
|
export { parseAPIErrorResponse };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@espressif/rainmaker-admin-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.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",
|