@truenas/api-client 3.0.2 → 3.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 +49 -7
- package/dist/index.cjs +29 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -3
- package/dist/index.d.ts +97 -3
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,19 +84,61 @@ client.api.events('app.query').subscribe(event => {
|
|
|
84
84
|
|
|
85
85
|
### Naming a version
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
`createTrueNasClient`
|
|
89
|
-
understates a newer server rather than promising methods it lacks.
|
|
90
|
-
|
|
87
|
+
By default the version is discovered at runtime while the types are fixed at
|
|
88
|
+
compile time, and `createTrueNasClient` assumes the oldest supported version —
|
|
89
|
+
which understates a newer server rather than promising methods it lacks. There
|
|
90
|
+
are two ways to reach the rest, and they differ in more than syntax.
|
|
91
|
+
|
|
92
|
+
**Assert the surface** when you do not know the version but intend to write
|
|
93
|
+
against a particular one:
|
|
91
94
|
|
|
92
95
|
```typescript
|
|
93
96
|
const client = await createTrueNasClient<ApiDirectoryV26_0_0>(opts);
|
|
94
97
|
client.api.query('container.query'); // v26-only, reachable
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
Discovery still runs and still decides which client is built. The type argument
|
|
101
|
+
is a claim about the server, not a guarantee — the client you get is whichever
|
|
102
|
+
version discovery found, so a wrong claim fails at runtime.
|
|
103
|
+
|
|
104
|
+
**State the version** when you already know it — a UI served by the appliance,
|
|
105
|
+
a harness against a pinned image:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const client = await createTrueNasClient({
|
|
109
|
+
uuid, hostnames, enabled: true, version: 'v27.0.0',
|
|
110
|
+
});
|
|
111
|
+
client.api.query('container.query'); // typed v27, derived from the string
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This skips discovery entirely: no `GET /api/versions`, no CORS fallback. The
|
|
115
|
+
surface is *derived* rather than asserted, so there is no type argument to get
|
|
116
|
+
wrong, and a version the package ships no types for does not compile.
|
|
117
|
+
|
|
118
|
+
It is the stronger claim of the two, because the version also selects the
|
|
119
|
+
websocket path. Naming `v27.0.0` at a v26 appliance connects on `/api/v27.0.0`
|
|
120
|
+
with v27 types over a v26 server, and discovery cannot correct it — declining
|
|
121
|
+
discovery is the point.
|
|
122
|
+
|
|
123
|
+
The derivation needs the version to be literal at the call site. Passing a type
|
|
124
|
+
argument as well, forwarding `version` through a wrapper, or annotating the
|
|
125
|
+
options object as `CreateClientOptions` all compile, all connect to the version
|
|
126
|
+
you named, and all type as the default surface instead. That
|
|
127
|
+
errs safely — understated types fail at the method call, not at runtime — but
|
|
128
|
+
silently, so keep the literal where the call is.
|
|
129
|
+
|
|
130
|
+
Compatibility is still checked, and two kinds of refusal reach a caller. A string that
|
|
131
|
+
is not a supported version — reachable only from JavaScript — throws a plain
|
|
132
|
+
`Error` naming the ones that are. A supported version this build has no client
|
|
133
|
+
for throws `VersionTooNewError`, the same type discovery raises; that happens
|
|
134
|
+
when types have been generated for a release before its client was written.
|
|
135
|
+
There is no `VersionTooOldError` here, because the oldest version you can name
|
|
136
|
+
is the oldest one supported.
|
|
137
|
+
|
|
138
|
+
Operations that must work across versions belong on `client.ops`. On the
|
|
139
|
+
discovery route that resolves against whatever the appliance turned out to be.
|
|
140
|
+
On the named route it cannot: the client class is picked from the version you
|
|
141
|
+
stated, so `ops` is that version's mappings whether or not the server agrees.
|
|
100
142
|
|
|
101
143
|
## Documentation
|
|
102
144
|
|
package/dist/index.cjs
CHANGED
|
@@ -3644,12 +3644,40 @@ async function createTrueNasClient(opts) {
|
|
|
3644
3644
|
`Cannot create client for system ${uuid}: hostnames array is empty`
|
|
3645
3645
|
);
|
|
3646
3646
|
}
|
|
3647
|
-
const versionDiscovery = new VersionDiscovery(logger);
|
|
3648
3647
|
logger.info("Creating versioned API client", {
|
|
3649
3648
|
uuid: uuid.slice(0, 8),
|
|
3650
3649
|
hostnames: hostnames.join(", "),
|
|
3651
3650
|
systemName
|
|
3652
3651
|
});
|
|
3652
|
+
if (opts.version !== void 0) {
|
|
3653
|
+
if (!SUPPORTED_API_VERSIONS.includes(opts.version)) {
|
|
3654
|
+
throw new Error(
|
|
3655
|
+
`Cannot create client for system ${uuid}: '${opts.version}' is not a version this package ships types for. Supported: ${SUPPORTED_API_VERSIONS.join(", ")}.`
|
|
3656
|
+
);
|
|
3657
|
+
}
|
|
3658
|
+
const known = parseApiVersion(opts.version);
|
|
3659
|
+
if (!known) {
|
|
3660
|
+
throw new Error(
|
|
3661
|
+
`Cannot create client for system ${uuid}: supported version '${opts.version}' failed to parse.`
|
|
3662
|
+
);
|
|
3663
|
+
}
|
|
3664
|
+
const compatibility = checkVersionCompatibility(known);
|
|
3665
|
+
if (compatibility === "too-new" /* TooNew */) {
|
|
3666
|
+
throw new VersionTooNewError(hostnames[0], [known.version]);
|
|
3667
|
+
}
|
|
3668
|
+
if (compatibility !== "compatible" /* Compatible */) {
|
|
3669
|
+
throw new Error(
|
|
3670
|
+
`Cannot create client for system ${uuid}: the supported version range is not usable (${apiVersionConfig.MIN_SUPPORTED_VERSION}..${apiVersionConfig.MAX_SUPPORTED_VERSION}).`
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
logger.info("API version supplied by the caller, skipping discovery", {
|
|
3674
|
+
uuid: uuid.slice(0, 8),
|
|
3675
|
+
version: known.version,
|
|
3676
|
+
websocketPath: known.websocketPath
|
|
3677
|
+
});
|
|
3678
|
+
return instantiateClientForVersion(known, opts, logger);
|
|
3679
|
+
}
|
|
3680
|
+
const versionDiscovery = new VersionDiscovery(logger);
|
|
3653
3681
|
let version;
|
|
3654
3682
|
try {
|
|
3655
3683
|
const winner = await discoverVersionFromAnyHostname(
|