@truenas/api-client 4.0.1 → 4.0.2
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 +59 -0
- package/dist/index.cjs +66 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +188 -7
- package/dist/index.d.ts +188 -7
- package/dist/index.js +66 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -183,6 +183,65 @@ discovery route that resolves against whatever the appliance turned out to be.
|
|
|
183
183
|
On the named route it cannot: the client class is picked from the version you
|
|
184
184
|
stated, so `ops` is that version's mappings whether or not the server agrees.
|
|
185
185
|
|
|
186
|
+
`ops` is deliberately flat — `OperationMappings`, not parameterized by the
|
|
187
|
+
directory — so every operation is callable whether or not you pinned a version.
|
|
188
|
+
That is what lets an operation paper over a difference the type system would
|
|
189
|
+
otherwise force the caller to handle.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// The same call on every supported version.
|
|
193
|
+
const sessions = await firstValueFrom(
|
|
194
|
+
client.ops.smbStatus({ infoLevel: 'SESSIONS' })
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// A client count is this composed, not a second operation.
|
|
198
|
+
const count = await firstValueFrom(
|
|
199
|
+
client.ops.smbStatus({
|
|
200
|
+
infoLevel: 'SESSIONS',
|
|
201
|
+
options: { count: true },
|
|
202
|
+
statusOptions: { fast: true },
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`smbStatus` is worth singling out, because it is the first operation whose
|
|
208
|
+
v25.10 leg is invisible to `middlewared --dump-api`. `smb.status` is public on
|
|
209
|
+
v26+ and generated like any other method; on v25.10 it is the same method taking
|
|
210
|
+
the same four positional arguments and returning the same `list | dict | int`,
|
|
211
|
+
but middleware declares it `private=True`, so the dump omits it and no generated
|
|
212
|
+
v25.10 type mentions it. The v25.10 client therefore *asserts* the method exists
|
|
213
|
+
rather than reading it from the directory — a single narrow declaration admitting
|
|
214
|
+
one method name, one argument tuple and one return type, checked against
|
|
215
|
+
middleware source instead of against the dump.
|
|
216
|
+
|
|
217
|
+
Three consequences worth knowing before you reach for it.
|
|
218
|
+
|
|
219
|
+
**It needs a full-admin session on v25.10.** Being private there decides
|
|
220
|
+
authorization, not just documentation. `smb.status` declares no roles on
|
|
221
|
+
v25.10, and middleware role-registers a method only `if roles:` — so it is in no
|
|
222
|
+
role's allowlist, and only a **non-STIG full-admin** session, whose allowlist is
|
|
223
|
+
the wildcard `{ method: '*', resource: '*' }`, reaches it. A session holding
|
|
224
|
+
exactly `SHARING_SMB_READ` is refused with `EACCES` on v25.10 and succeeds on
|
|
225
|
+
v26+, where the method carries that role. Under STIG, full admin is expanded to
|
|
226
|
+
the union of its roles' allowlists rather than the wildcard, so it is refused on
|
|
227
|
+
v25.10 as well. The client does not pre-empt any of this: you get middleware's
|
|
228
|
+
own error, on the version where it applies.
|
|
229
|
+
|
|
230
|
+
**It logs server-side on every dispatch**, which matters if you poll it. v25.10
|
|
231
|
+
is in maintenance and that cost is accepted there, but it is not a pattern to
|
|
232
|
+
extend.
|
|
233
|
+
|
|
234
|
+
**The result is the union middleware sends** — which arm arrives is decided by
|
|
235
|
+
the options, not the info level — so callers narrow it themselves.
|
|
236
|
+
|
|
237
|
+
These types are deliberately not the generated ones. `SmbStatusOptions` is not
|
|
238
|
+
v26's `SMBStatusOptions`, and `SmbStatusResponse` is not that method's generated
|
|
239
|
+
response: the generated types describe one version's dump, while these describe
|
|
240
|
+
the contract both versions honour. They are named `Smb…` rather than `SMB…` so
|
|
241
|
+
the two cannot be confused at a call site — and `SmbStatusOptions` is the one
|
|
242
|
+
pair where the names sit closest, since it is the fourth positional argument on
|
|
243
|
+
both versions.
|
|
244
|
+
|
|
186
245
|
## Documentation
|
|
187
246
|
|
|
188
247
|
The API reference is generated from the TSDoc comments in the source with
|
package/dist/index.cjs
CHANGED
|
@@ -3449,6 +3449,16 @@ function toAppState(state) {
|
|
|
3449
3449
|
}
|
|
3450
3450
|
}
|
|
3451
3451
|
|
|
3452
|
+
// src/utils/smb-status.utils.ts
|
|
3453
|
+
function toSmbStatusParams(request = {}) {
|
|
3454
|
+
return [
|
|
3455
|
+
request.infoLevel ?? "ALL",
|
|
3456
|
+
request.filters ?? [],
|
|
3457
|
+
request.options ?? {},
|
|
3458
|
+
request.statusOptions ?? {}
|
|
3459
|
+
];
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3452
3462
|
// src/client/truenas-api-client-v25-10.ts
|
|
3453
3463
|
var TrueNasApiClientV2510 = class extends TrueNasApiClient {
|
|
3454
3464
|
/**
|
|
@@ -3488,6 +3498,42 @@ var TrueNasApiClientV2510 = class extends TrueNasApiClient {
|
|
|
3488
3498
|
);
|
|
3489
3499
|
}
|
|
3490
3500
|
return this.api.job("virt.instance.delete", [id]);
|
|
3501
|
+
},
|
|
3502
|
+
// The private leg. See `PrivateSmbStatusCall` for why this is a cast and
|
|
3503
|
+
// not a directory lookup.
|
|
3504
|
+
//
|
|
3505
|
+
// v25.10 answers rather than refusing, for a caller with the authority.
|
|
3506
|
+
// Being private does not stop the method running: `ws_handler/rpc.py`
|
|
3507
|
+
// logs a warning for a private call over websocket and dispatches it
|
|
3508
|
+
// anyway — the `# FIXME: Eventually, prohibit this` above that branch is
|
|
3509
|
+
// still unresolved on master.
|
|
3510
|
+
//
|
|
3511
|
+
// It does decide who may run it. `smb.status` carries no `roles=` here,
|
|
3512
|
+
// and middleware role-registers a method only `if roles:`, so it is in no
|
|
3513
|
+
// role's allowlist and only the non-STIG full-admin wildcard reaches it.
|
|
3514
|
+
// That is documented on `OperationMappings.smbStatus`; this leg does not
|
|
3515
|
+
// pre-empt it. A caller without the authority gets middleware's `EACCES`,
|
|
3516
|
+
// which is the honest answer and the server's to give.
|
|
3517
|
+
//
|
|
3518
|
+
// The server-side warning is per dispatch, and a client count is exactly
|
|
3519
|
+
// the sort of thing a caller polls. Reported at debug rather than warn,
|
|
3520
|
+
// because nothing here is degraded or unhonoured — the request is served
|
|
3521
|
+
// in full — and left to the caller to weigh.
|
|
3522
|
+
//
|
|
3523
|
+
// Future tense, and for the same reason as `containerDelete` above: this
|
|
3524
|
+
// runs when the operation is built, and `api.call` is cold, so no request
|
|
3525
|
+
// has gone out yet and may never. One built observable subscribed twice
|
|
3526
|
+
// dispatches twice; this line is what will happen, not a record that it
|
|
3527
|
+
// did.
|
|
3528
|
+
smbStatus: (request) => {
|
|
3529
|
+
this.logger.debug(
|
|
3530
|
+
"smbStatus: smb.status is private on v25.10; each dispatch will log a warning server-side and needs a non-STIG full-admin session",
|
|
3531
|
+
{ method: "smb.status", infoLevel: request?.infoLevel ?? "ALL" }
|
|
3532
|
+
);
|
|
3533
|
+
return this.api.call(
|
|
3534
|
+
"smb.status",
|
|
3535
|
+
toSmbStatusParams(request)
|
|
3536
|
+
);
|
|
3491
3537
|
}
|
|
3492
3538
|
};
|
|
3493
3539
|
}
|
|
@@ -3575,7 +3621,16 @@ var TrueNasApiClientV26 = class extends TrueNasApiClient {
|
|
|
3575
3621
|
containerDelete: (id, options) => this.api.job(
|
|
3576
3622
|
"container.delete",
|
|
3577
3623
|
options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
|
|
3578
|
-
)
|
|
3624
|
+
),
|
|
3625
|
+
// `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
|
|
3626
|
+
// an ordinary `call` read straight out of the generated directory — the
|
|
3627
|
+
// one leg of this operation that needs no assertion about the server.
|
|
3628
|
+
//
|
|
3629
|
+
// Not a query verb: middleware returns the same `list | dict | int`
|
|
3630
|
+
// polymorphism a `.query` does, but the generator did not mark the entry
|
|
3631
|
+
// with an `entity`, so `api.query` does not accept it and the union is
|
|
3632
|
+
// handed to the caller to narrow.
|
|
3633
|
+
smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
|
|
3579
3634
|
};
|
|
3580
3635
|
}
|
|
3581
3636
|
};
|
|
@@ -3656,7 +3711,16 @@ var TrueNasApiClientV27 = class extends TrueNasApiClient {
|
|
|
3656
3711
|
containerDelete: (id, options) => this.api.job(
|
|
3657
3712
|
"container.delete",
|
|
3658
3713
|
options ? [parseInt(id, 10), options] : [parseInt(id, 10)]
|
|
3659
|
-
)
|
|
3714
|
+
),
|
|
3715
|
+
// `smb.status` is public here and gated on `SHARING_SMB_READ`, so it is
|
|
3716
|
+
// an ordinary `call` read straight out of the generated directory — the
|
|
3717
|
+
// one leg of this operation that needs no assertion about the server.
|
|
3718
|
+
//
|
|
3719
|
+
// Not a query verb: middleware returns the same `list | dict | int`
|
|
3720
|
+
// polymorphism a `.query` does, but the generator did not mark the entry
|
|
3721
|
+
// with an `entity`, so `api.query` does not accept it and the union is
|
|
3722
|
+
// handed to the caller to narrow.
|
|
3723
|
+
smbStatus: (request) => this.api.call("smb.status", toSmbStatusParams(request))
|
|
3660
3724
|
};
|
|
3661
3725
|
}
|
|
3662
3726
|
};
|