@truenas/api-client 9.0.1 → 9.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -4
- package/dist/{chunk-U6V2Y3AE.cjs → chunk-DJCZ545I.cjs} +29 -11
- package/dist/chunk-DJCZ545I.cjs.map +1 -0
- package/dist/{chunk-K7BL6J3Z.js → chunk-K5ICTA2D.js} +29 -11
- package/dist/chunk-K5ICTA2D.js.map +1 -0
- package/dist/index.cjs +37 -37
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +1 -1
- package/dist/testing/index.cjs +15 -15
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +4 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/{truenas-auth-mechanism.enum-Bp2XMMwK.d.cts → truenas-auth-mechanism.enum-krCGFs13.d.cts} +31 -2
- package/dist/{truenas-auth-mechanism.enum-Bp2XMMwK.d.ts → truenas-auth-mechanism.enum-krCGFs13.d.ts} +31 -2
- package/package.json +1 -1
- package/dist/chunk-K7BL6J3Z.js.map +0 -1
- package/dist/chunk-U6V2Y3AE.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -71,15 +71,18 @@ promise.
|
|
|
71
71
|
|
|
72
72
|
| Method | Use it for |
|
|
73
73
|
|---|---|
|
|
74
|
-
| `loginWithUserPass(username, password)` | Interactive logins. Resolves with `response_type: 'OTP_REQUIRED'` when two-factor is on. |
|
|
74
|
+
| `loginWithUserPass(username, password, options?)` | Interactive logins. Resolves with `response_type: 'OTP_REQUIRED'` when two-factor is on. Pass `{ rememberPassword: false }` to keep the password out of memory once the login succeeds. |
|
|
75
75
|
| `loginWithOtp(code)` | The second step of a two-factor login. |
|
|
76
76
|
| `loginWithApiKey({ username, key })` | Services and scripts. |
|
|
77
77
|
| `loginWithToken(token)` | Opening another session from a previous login's `reconnect_token`. |
|
|
78
78
|
|
|
79
79
|
All four live on `client.authenticator`. Password and API-key sessions log back
|
|
80
|
-
in by themselves after a reconnect
|
|
81
|
-
`
|
|
82
|
-
`
|
|
80
|
+
in by themselves after a reconnect, unless the password login passed
|
|
81
|
+
`rememberPassword: false`; a token session is the caller's to restore.
|
|
82
|
+
`authenticated$` tracks the session, `logout()` ends it, and a rejected login
|
|
83
|
+
errors with an `AuthError` carrying an `AuthErrorCode`, plus the refusing
|
|
84
|
+
`response` when middleware answered with one (`response.response_type` tells
|
|
85
|
+
`EXPIRED`, `DENIED` and `REDIRECT` apart from `AUTH_ERR`).
|
|
83
86
|
|
|
84
87
|
## Calls
|
|
85
88
|
|
|
@@ -168,6 +171,21 @@ client you get. A named `version` skips discovery and also selects the
|
|
|
168
171
|
WebSocket endpoint, so name the version the appliance actually runs. The types
|
|
169
172
|
follow it when the version is a literal.
|
|
170
173
|
|
|
174
|
+
To be written against one version but run against whatever the appliance
|
|
175
|
+
serves, as an appliance's own UI is, keep the `version` and move the socket:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const client = await createTrueNasClient({
|
|
179
|
+
...options,
|
|
180
|
+
version: 'v28.0.0', // the surface you compile against
|
|
181
|
+
websocketPath: '/api/current', // the appliance's newest version, whichever it is
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The client then works against an older or newer release call for call; a
|
|
186
|
+
method or field that release lacks fails when it is called rather than at
|
|
187
|
+
compile time.
|
|
188
|
+
|
|
171
189
|
For code that must run against any supported release, use `client.ops`. It
|
|
172
190
|
offers the same calls on every version and maps them onto whatever that version
|
|
173
191
|
provides:
|
|
@@ -2193,9 +2193,16 @@ var AuthErrorCode = /* @__PURE__ */ ((AuthErrorCode2) => {
|
|
|
2193
2193
|
return AuthErrorCode2;
|
|
2194
2194
|
})(AuthErrorCode || {});
|
|
2195
2195
|
var AuthError = class _AuthError extends Error {
|
|
2196
|
-
|
|
2196
|
+
/**
|
|
2197
|
+
* @param response - the answer middleware refused the login with, when there was one.
|
|
2198
|
+
* Its `response_type` is what tells `EXPIRED`, `DENIED` and `REDIRECT` apart from
|
|
2199
|
+
* `AUTH_ERR`; the code alone says only which mechanism failed. Absent when the login
|
|
2200
|
+
* never got an answer of that kind (an error frame, or a superseded login).
|
|
2201
|
+
*/
|
|
2202
|
+
constructor(code, message, response) {
|
|
2197
2203
|
super(message);
|
|
2198
2204
|
this.code = code;
|
|
2205
|
+
this.response = response;
|
|
2199
2206
|
this.name = "AuthError";
|
|
2200
2207
|
Object.setPrototypeOf(this, _AuthError.prototype);
|
|
2201
2208
|
}
|
|
@@ -2733,7 +2740,7 @@ function getWebSocketPath(version) {
|
|
|
2733
2740
|
// src/auth/truenas-authenticator.ts
|
|
2734
2741
|
var throwOnAuthenticationFailure = (code, message) => rxjs.switchMap((response) => {
|
|
2735
2742
|
if (response.response_type === "AUTH_ERR" /* AuthErr */) {
|
|
2736
|
-
return rxjs.throwError(() => new AuthError(code, message));
|
|
2743
|
+
return rxjs.throwError(() => new AuthError(code, message, response));
|
|
2737
2744
|
}
|
|
2738
2745
|
return rxjs.of(response);
|
|
2739
2746
|
});
|
|
@@ -2870,7 +2877,8 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
|
|
|
2870
2877
|
}
|
|
2871
2878
|
this.authenticating$.next(false);
|
|
2872
2879
|
}
|
|
2873
|
-
loginWithUserPass(username, password) {
|
|
2880
|
+
loginWithUserPass(username, password, options = {}) {
|
|
2881
|
+
const { rememberPassword = true } = options;
|
|
2874
2882
|
const { sentDuring, callerInitiated } = this.beginLogin();
|
|
2875
2883
|
let answered = false;
|
|
2876
2884
|
const message = createJsonRpcMessage("auth.login_ex", [
|
|
@@ -2906,9 +2914,11 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
|
|
|
2906
2914
|
rxjs.tap((res) => {
|
|
2907
2915
|
if (res.response_type === "SUCCESS" /* Success */) {
|
|
2908
2916
|
this.assertNotSuperseded(sentDuring);
|
|
2909
|
-
this.credentials = { username, password, key: "" };
|
|
2917
|
+
this.credentials = rememberPassword ? { username, password, key: "" } : { username: "", password: "", key: "" };
|
|
2910
2918
|
this.sessionLifetime = res.user_info?.attributes?.preferences?.lifetime ?? _TrueNasAuthenticator.DefaultSessionLifetime;
|
|
2911
2919
|
this.authenticated$.next(true);
|
|
2920
|
+
} else if (res.response_type === "OTP_REQUIRED" /* OtpRequired */ && !rememberPassword && this.authEpoch === sentDuring) {
|
|
2921
|
+
this.credentials = { username: "", password: "", key: "" };
|
|
2912
2922
|
}
|
|
2913
2923
|
}),
|
|
2914
2924
|
rxjs.finalize(() => {
|
|
@@ -3006,7 +3016,8 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
|
|
|
3006
3016
|
if (res.response_type !== "SUCCESS" /* Success */) {
|
|
3007
3017
|
throw new AuthError(
|
|
3008
3018
|
"TOKEN_AUTH_FAILED" /* TokenAuthFailed */,
|
|
3009
|
-
`TrueNAS token authentication failed (${res.response_type}). The token may have expired or been used, or the account may no longer be permitted to log in
|
|
3019
|
+
`TrueNAS token authentication failed (${res.response_type}). The token may have expired or been used, or the account may no longer be permitted to log in.`,
|
|
3020
|
+
res
|
|
3010
3021
|
);
|
|
3011
3022
|
}
|
|
3012
3023
|
return res;
|
|
@@ -4297,6 +4308,11 @@ async function createTrueNasClient(opts) {
|
|
|
4297
4308
|
`Cannot create client for system ${uuid}: hostnames array is empty`
|
|
4298
4309
|
);
|
|
4299
4310
|
}
|
|
4311
|
+
if (opts.websocketPath !== void 0 && !opts.websocketPath.startsWith("/")) {
|
|
4312
|
+
throw new Error(
|
|
4313
|
+
`Cannot create client for system ${uuid}: websocketPath must be an absolute path, got '${opts.websocketPath}'.`
|
|
4314
|
+
);
|
|
4315
|
+
}
|
|
4300
4316
|
logger.info("Creating versioned API client", {
|
|
4301
4317
|
uuid: uuid.slice(0, 8),
|
|
4302
4318
|
hostnames: hostnames.join(", "),
|
|
@@ -4326,7 +4342,7 @@ async function createTrueNasClient(opts) {
|
|
|
4326
4342
|
logger.info("API version supplied by the caller, skipping discovery", {
|
|
4327
4343
|
uuid: uuid.slice(0, 8),
|
|
4328
4344
|
version: known.version,
|
|
4329
|
-
websocketPath: known.websocketPath
|
|
4345
|
+
websocketPath: opts.websocketPath ?? known.websocketPath
|
|
4330
4346
|
});
|
|
4331
4347
|
return instantiateClientForVersion(known, opts, logger);
|
|
4332
4348
|
}
|
|
@@ -4345,7 +4361,7 @@ async function createTrueNasClient(opts) {
|
|
|
4345
4361
|
// of them anyway.
|
|
4346
4362
|
hostname: winner.hostname,
|
|
4347
4363
|
version: version.version,
|
|
4348
|
-
websocketPath: version.websocketPath
|
|
4364
|
+
websocketPath: opts.websocketPath ?? version.websocketPath
|
|
4349
4365
|
});
|
|
4350
4366
|
} catch (error) {
|
|
4351
4367
|
const errorMessage = errorMessageOrDefault(error, "Unknown error");
|
|
@@ -4471,6 +4487,7 @@ function clientClassFor(version) {
|
|
|
4471
4487
|
function instantiateClientForVersion(version, opts, logger) {
|
|
4472
4488
|
const { uuid, hostnames, enabled, systemName } = opts;
|
|
4473
4489
|
const versionKey = clientVersionKey(version);
|
|
4490
|
+
const endpoint = opts.websocketPath === void 0 ? version : { ...version, websocketPath: opts.websocketPath };
|
|
4474
4491
|
const Client = CLIENT_BY_VERSION_KEY[versionKey];
|
|
4475
4492
|
if (!Client) {
|
|
4476
4493
|
logger.error("No client implementation for version", {
|
|
@@ -4485,12 +4502,13 @@ function instantiateClientForVersion(version, opts, logger) {
|
|
|
4485
4502
|
logger.info(`Instantiating ${Client.name}`, {
|
|
4486
4503
|
uuid: uuid.slice(0, 8),
|
|
4487
4504
|
version: version.version,
|
|
4488
|
-
versionKey
|
|
4505
|
+
versionKey,
|
|
4506
|
+
websocketPath: endpoint.websocketPath
|
|
4489
4507
|
});
|
|
4490
4508
|
return new Client(
|
|
4491
4509
|
uuid,
|
|
4492
4510
|
hostnames,
|
|
4493
|
-
|
|
4511
|
+
endpoint,
|
|
4494
4512
|
enabled,
|
|
4495
4513
|
systemName,
|
|
4496
4514
|
logger,
|
|
@@ -4557,5 +4575,5 @@ exports.v25_10_4_exports = v25_10_4_exports;
|
|
|
4557
4575
|
exports.v25_10_5_exports = v25_10_5_exports;
|
|
4558
4576
|
exports.v27_0_0_exports = v27_0_0_exports;
|
|
4559
4577
|
exports.v28_0_0_exports = v28_0_0_exports;
|
|
4560
|
-
//# sourceMappingURL=chunk-
|
|
4561
|
-
//# sourceMappingURL=chunk-
|
|
4578
|
+
//# sourceMappingURL=chunk-DJCZ545I.cjs.map
|
|
4579
|
+
//# sourceMappingURL=chunk-DJCZ545I.cjs.map
|