@wandelbots/nova-js 3.9.0-pr.280.641b7e2 → 3.9.0-pr.280.74e07a8
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/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/lib/deprecated/v1/index.cjs +1 -1
- package/dist/lib/deprecated/v1/index.d.cts +1 -1
- package/dist/lib/deprecated/v1/index.d.mts +1 -1
- package/dist/lib/deprecated/v1/index.mjs +1 -1
- package/dist/lib/v2/index.cjs +24 -34
- package/dist/lib/v2/index.cjs.map +1 -1
- package/dist/lib/v2/index.d.cts +26 -30
- package/dist/lib/v2/index.d.cts.map +1 -1
- package/dist/lib/v2/index.d.mts +26 -30
- package/dist/lib/v2/index.d.mts.map +1 -1
- package/dist/lib/v2/index.mjs +23 -34
- package/dist/lib/v2/index.mjs.map +1 -1
- package/dist/{wandelscriptUtils-pySXnBlX.d.mts → wandelscriptUtils-CPA7fIA5.d.mts} +2 -1
- package/dist/{wandelscriptUtils-pySXnBlX.d.mts.map → wandelscriptUtils-CPA7fIA5.d.mts.map} +1 -1
- package/dist/{wandelscriptUtils-1A9uFPV_.d.cts → wandelscriptUtils-DxH6xiW6.d.cts} +2 -1
- package/dist/{wandelscriptUtils-1A9uFPV_.d.cts.map → wandelscriptUtils-DxH6xiW6.d.cts.map} +1 -1
- package/dist/{wandelscriptUtils-C7hQePlo.mjs → wandelscriptUtils-W_rEVq6i.mjs} +5 -4
- package/dist/{wandelscriptUtils-C7hQePlo.mjs.map → wandelscriptUtils-W_rEVq6i.mjs.map} +1 -1
- package/dist/{wandelscriptUtils-P0WYSZww.cjs → wandelscriptUtils-wnSvJKp0.cjs} +6 -4
- package/dist/{wandelscriptUtils-P0WYSZww.cjs.map → wandelscriptUtils-wnSvJKp0.cjs.map} +1 -1
- package/package.json +3 -2
- package/src/lib/deprecated/v1/NovaClient.ts +9 -7
- package/src/lib/deprecated/v2/NovaClient.ts +8 -7
- package/src/lib/v2/Nova.ts +4 -3
- package/src/lib/v2/NovaAPIClient.ts +93 -81
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wandelbots/nova-js",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.9.0-pr.280.
|
|
4
|
+
"version": "3.9.0-pr.280.74e07a8",
|
|
5
5
|
"description": "Official JS client for the Wandelbots API",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"packageManager": "pnpm@11.1.3+sha512.c85357fe17ca12dd23dd7071822666dfd7e3cb76fe214e3370b5ea2fb34f2a231185509b63e717f3cd0acb38dd3f8d82bcd5e8172400ae678b70ea4fbed0896d",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"mobx": "^6.15.0",
|
|
75
75
|
"path-to-regexp": "^8.4.0",
|
|
76
76
|
"reconnecting-websocket": "^4.4.0",
|
|
77
|
-
"three": "^0.183.2"
|
|
77
|
+
"three": "^0.183.2",
|
|
78
|
+
"url-join": "^5.0.0"
|
|
78
79
|
}
|
|
79
80
|
}
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import type { Configuration as BaseConfiguration } from "@wandelbots/nova-api/v1"
|
|
7
7
|
import type { AxiosRequestConfig } from "axios"
|
|
8
8
|
import axios, { isAxiosError } from "axios"
|
|
9
|
+
import urlJoin from "url-join"
|
|
9
10
|
import { loginWithAuth0 } from "../../../LoginWithAuth0.js"
|
|
10
11
|
import { AutoReconnectingWebsocket } from "../../AutoReconnectingWebsocket.js"
|
|
11
12
|
import { availableStorage } from "../../availableStorage.js"
|
|
12
13
|
import { parseNovaInstanceUrl } from "../../converters.js"
|
|
13
|
-
|
|
14
14
|
import { ConnectedMotionGroup } from "./ConnectedMotionGroup.js"
|
|
15
15
|
import { JoggerConnection } from "./JoggerConnection.js"
|
|
16
16
|
import { MotionStreamConnection } from "./MotionStreamConnection.js"
|
|
@@ -45,6 +45,7 @@ export type NovaClientConfig = {
|
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Access token for Bearer authentication.
|
|
48
|
+
* @deprecated use accessToken instead
|
|
48
49
|
*/
|
|
49
50
|
accessToken?: string
|
|
50
51
|
} & Omit<BaseConfiguration, "isJsonMime" | "basePath">
|
|
@@ -81,7 +82,7 @@ export class NovaClient {
|
|
|
81
82
|
|
|
82
83
|
// Set up Axios instance with interceptor for token fetching
|
|
83
84
|
const axiosInstance = axios.create({
|
|
84
|
-
baseURL:
|
|
85
|
+
baseURL: urlJoin(this.config.instanceUrl, "/api/v1"),
|
|
85
86
|
// TODO - backend needs to set proper CORS headers for this
|
|
86
87
|
headers:
|
|
87
88
|
typeof window !== "undefined" &&
|
|
@@ -143,7 +144,7 @@ export class NovaClient {
|
|
|
143
144
|
|
|
144
145
|
this.api = new NovaCellAPIClient(cellId, {
|
|
145
146
|
...config,
|
|
146
|
-
basePath:
|
|
147
|
+
basePath: urlJoin(this.instanceUrl.href, "/api/v1"),
|
|
147
148
|
isJsonMime: (mime: string) => {
|
|
148
149
|
return mime === "application/json"
|
|
149
150
|
},
|
|
@@ -192,10 +193,11 @@ export class NovaClient {
|
|
|
192
193
|
|
|
193
194
|
makeWebsocketURL(path: string): string {
|
|
194
195
|
const url = new URL(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
this.
|
|
198
|
-
|
|
196
|
+
urlJoin(
|
|
197
|
+
this.instanceUrl.href,
|
|
198
|
+
`/api/v1/cells/${this.config.cellId}`,
|
|
199
|
+
path,
|
|
200
|
+
),
|
|
199
201
|
)
|
|
200
202
|
url.protocol = url.protocol.replace("http", "ws")
|
|
201
203
|
url.protocol = url.protocol.replace("https", "wss")
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import type { Configuration as BaseConfiguration } from "@wandelbots/nova-api/v2"
|
|
3
3
|
import type { AxiosRequestConfig } from "axios"
|
|
4
4
|
import axios, { isAxiosError } from "axios"
|
|
5
|
+
import urlJoin from "url-join"
|
|
5
6
|
import { loginWithAuth0 } from "../../../LoginWithAuth0"
|
|
6
7
|
import { AutoReconnectingWebsocket } from "../../AutoReconnectingWebsocket"
|
|
7
8
|
import { availableStorage } from "../../availableStorage"
|
|
8
9
|
import { parseNovaInstanceUrl } from "../../converters"
|
|
9
|
-
|
|
10
10
|
import { MockNovaInstance } from "../../v2/mock/MockNovaInstance"
|
|
11
11
|
import { NovaCellAPIClient } from "./NovaCellAPIClient"
|
|
12
12
|
|
|
@@ -74,7 +74,7 @@ export class NovaClient {
|
|
|
74
74
|
|
|
75
75
|
// Set up Axios instance with interceptor for token fetching
|
|
76
76
|
const axiosInstance = axios.create({
|
|
77
|
-
baseURL:
|
|
77
|
+
baseURL: urlJoin(this.instanceUrl.href, "/api/v2"),
|
|
78
78
|
// TODO - backend needs to set proper CORS headers for this
|
|
79
79
|
headers:
|
|
80
80
|
typeof window !== "undefined" &&
|
|
@@ -136,7 +136,7 @@ export class NovaClient {
|
|
|
136
136
|
|
|
137
137
|
this.api = new NovaCellAPIClient(cellId, {
|
|
138
138
|
...config,
|
|
139
|
-
basePath:
|
|
139
|
+
basePath: urlJoin(this.instanceUrl.href, "/api/v2"),
|
|
140
140
|
isJsonMime: (mime: string) => {
|
|
141
141
|
return mime === "application/json"
|
|
142
142
|
},
|
|
@@ -184,10 +184,11 @@ export class NovaClient {
|
|
|
184
184
|
|
|
185
185
|
makeWebsocketURL(path: string): string {
|
|
186
186
|
const url = new URL(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.
|
|
190
|
-
|
|
187
|
+
urlJoin(
|
|
188
|
+
this.instanceUrl.href,
|
|
189
|
+
`/api/v2/cells/${this.config.cellId}`,
|
|
190
|
+
path,
|
|
191
|
+
),
|
|
191
192
|
)
|
|
192
193
|
url.protocol = url.protocol.replace("http", "ws")
|
|
193
194
|
url.protocol = url.protocol.replace("https", "wss")
|
package/src/lib/v2/Nova.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Configuration as BaseConfiguration } from "@wandelbots/nova-api/v2"
|
|
2
2
|
import type { AxiosRequestConfig } from "axios"
|
|
3
3
|
import axios, { isAxiosError } from "axios"
|
|
4
|
+
import urlJoin from "url-join"
|
|
4
5
|
import { loginWithAuth0 } from "../../LoginWithAuth0"
|
|
5
6
|
import { AutoReconnectingWebsocket } from "../AutoReconnectingWebsocket"
|
|
6
7
|
import { availableStorage } from "../availableStorage"
|
|
@@ -49,7 +50,7 @@ export class Nova {
|
|
|
49
50
|
|
|
50
51
|
// Set up Axios instance with interceptor for token fetching
|
|
51
52
|
const axiosInstance = axios.create({
|
|
52
|
-
baseURL:
|
|
53
|
+
baseURL: urlJoin(this.instanceUrl.href, "/api/v2"),
|
|
53
54
|
// TODO - backend needs to set proper CORS headers for this
|
|
54
55
|
headers:
|
|
55
56
|
typeof window !== "undefined" &&
|
|
@@ -111,7 +112,7 @@ export class Nova {
|
|
|
111
112
|
|
|
112
113
|
this.api = new NovaAPIClient({
|
|
113
114
|
...config,
|
|
114
|
-
basePath:
|
|
115
|
+
basePath: urlJoin(this.instanceUrl.href, "/api/v2"),
|
|
115
116
|
isJsonMime: (mime: string) => {
|
|
116
117
|
return mime === "application/json"
|
|
117
118
|
},
|
|
@@ -161,7 +162,7 @@ export class Nova {
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
makeWebsocketURL(path: string): string {
|
|
164
|
-
const url = new URL(`/api/v2
|
|
165
|
+
const url = new URL(urlJoin(this.instanceUrl.href, `/api/v2`, path))
|
|
165
166
|
url.protocol = url.protocol.replace("http", "ws")
|
|
166
167
|
url.protocol = url.protocol.replace("https", "wss")
|
|
167
168
|
|
|
@@ -2,33 +2,7 @@ import type {
|
|
|
2
2
|
BaseAPI,
|
|
3
3
|
Configuration as BaseConfiguration,
|
|
4
4
|
} from "@wandelbots/nova-api/v2"
|
|
5
|
-
import
|
|
6
|
-
ApplicationApi,
|
|
7
|
-
BUSInputsOutputsApi,
|
|
8
|
-
CellApi,
|
|
9
|
-
ControllerApi,
|
|
10
|
-
ControllerInputsOutputsApi,
|
|
11
|
-
JoggingApi,
|
|
12
|
-
KinematicsApi,
|
|
13
|
-
LicenseApi,
|
|
14
|
-
MotionGroupApi,
|
|
15
|
-
MotionGroupModelsApi,
|
|
16
|
-
NOVACloudApi,
|
|
17
|
-
ProgramApi,
|
|
18
|
-
RobotConfigurationsApi,
|
|
19
|
-
SessionApi,
|
|
20
|
-
StoreCollisionComponentsApi,
|
|
21
|
-
StoreCollisionSetupsApi,
|
|
22
|
-
StoreObjectApi,
|
|
23
|
-
SystemApi,
|
|
24
|
-
TrajectoryCachingApi,
|
|
25
|
-
TrajectoryExecutionApi,
|
|
26
|
-
TrajectoryPlanningApi,
|
|
27
|
-
VersionApi,
|
|
28
|
-
VirtualControllerApi,
|
|
29
|
-
VirtualControllerBehaviorApi,
|
|
30
|
-
VirtualControllerInputsOutputsApi,
|
|
31
|
-
} from "@wandelbots/nova-api/v2"
|
|
5
|
+
import * as novaApiV2 from "@wandelbots/nova-api/v2"
|
|
32
6
|
import type { AxiosInstance } from "axios"
|
|
33
7
|
import axios from "axios"
|
|
34
8
|
|
|
@@ -43,12 +17,71 @@ type WithUnwrappedAxiosResponse<T> = {
|
|
|
43
17
|
[P in keyof T]: UnwrapAxiosResponseReturn<T[P]>
|
|
44
18
|
}
|
|
45
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Filters nova-api/v2 exports to just the API class constructors,
|
|
22
|
+
* excluding helper factories and param creators.
|
|
23
|
+
*/
|
|
24
|
+
type ApiConstructors = {
|
|
25
|
+
[K in keyof typeof novaApiV2 as K extends `${string}Api`
|
|
26
|
+
? K extends
|
|
27
|
+
| `${string}Factory${string}`
|
|
28
|
+
| `${string}Fp${string}`
|
|
29
|
+
| `${string}ParamCreator${string}`
|
|
30
|
+
? never
|
|
31
|
+
: K
|
|
32
|
+
: never]: (typeof novaApiV2)[K]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Lowercases leading uppercase characters to produce a camelCase property name.
|
|
37
|
+
* e.g. "BUSInputsOutputs" -> "busInputsOutputs", "NOVACloud" -> "novaCloud",
|
|
38
|
+
* "Application" -> "application"
|
|
39
|
+
*/
|
|
40
|
+
type CamelCase<S extends string> =
|
|
41
|
+
S extends `${Uppercase<infer A>}${Uppercase<infer B>}${infer Rest}`
|
|
42
|
+
? Rest extends `${Lowercase<string>}${string}`
|
|
43
|
+
? `${Lowercase<A>}${CamelCase<`${Uppercase<B>}${Rest}`>}`
|
|
44
|
+
: `${Lowercase<A>}${CamelCase<`${Uppercase<B>}${Rest}`>}`
|
|
45
|
+
: Uncapitalize<S>
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Maps API class names to property names by stripping "Api" and converting
|
|
49
|
+
* the leading acronym to lowercase camelCase.
|
|
50
|
+
*/
|
|
51
|
+
type ApiProperties = {
|
|
52
|
+
readonly [K in keyof ApiConstructors as K extends `${infer P}Api`
|
|
53
|
+
? CamelCase<P>
|
|
54
|
+
: never]: ApiConstructors[K] extends new (
|
|
55
|
+
// biome-ignore lint/suspicious/noExplicitAny: needed for contravariant parameter matching
|
|
56
|
+
...args: any[]
|
|
57
|
+
) => infer I
|
|
58
|
+
? WithUnwrappedAxiosResponse<I>
|
|
59
|
+
: never
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
type NovaAPIClientOpts = BaseConfiguration & {
|
|
47
63
|
axiosInstance?: AxiosInstance
|
|
48
64
|
mock?: boolean
|
|
49
65
|
}
|
|
50
66
|
|
|
51
|
-
function
|
|
67
|
+
function isApiClass(
|
|
68
|
+
name: string,
|
|
69
|
+
value: unknown,
|
|
70
|
+
): value is new (
|
|
71
|
+
config: BaseConfiguration,
|
|
72
|
+
basePath: string,
|
|
73
|
+
axios: AxiosInstance,
|
|
74
|
+
) => BaseAPI {
|
|
75
|
+
return (
|
|
76
|
+
name.endsWith("Api") &&
|
|
77
|
+
typeof value === "function" &&
|
|
78
|
+
!name.includes("Factory") &&
|
|
79
|
+
!name.includes("Fp") &&
|
|
80
|
+
!name.includes("ParamCreator")
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function wrapApi<T extends BaseAPI>(
|
|
52
85
|
ApiConstructor: new (
|
|
53
86
|
config: BaseConfiguration,
|
|
54
87
|
basePath: string,
|
|
@@ -82,64 +115,43 @@ function unwrap<T extends BaseAPI>(
|
|
|
82
115
|
|
|
83
116
|
/**
|
|
84
117
|
* API client providing type-safe access to all the endpoints of a NOVA
|
|
85
|
-
* instance.
|
|
118
|
+
* instance. API sections are auto-discovered from @wandelbots/nova-api/v2
|
|
119
|
+
* at runtime, so new sections added upstream are exposed automatically.
|
|
86
120
|
*/
|
|
87
|
-
export class NovaAPIClient {
|
|
121
|
+
export const NovaAPIClient = class NovaAPIClient {
|
|
88
122
|
readonly opts: NovaAPIClientOpts
|
|
89
123
|
|
|
90
|
-
readonly application: WithUnwrappedAxiosResponse<ApplicationApi>
|
|
91
|
-
readonly busIOs: WithUnwrappedAxiosResponse<BUSInputsOutputsApi>
|
|
92
|
-
readonly cell: WithUnwrappedAxiosResponse<CellApi>
|
|
93
|
-
readonly controller: WithUnwrappedAxiosResponse<ControllerApi>
|
|
94
|
-
readonly controllerIOs: WithUnwrappedAxiosResponse<ControllerInputsOutputsApi>
|
|
95
|
-
readonly jogging: WithUnwrappedAxiosResponse<JoggingApi>
|
|
96
|
-
readonly kinematics: WithUnwrappedAxiosResponse<KinematicsApi>
|
|
97
|
-
readonly license: WithUnwrappedAxiosResponse<LicenseApi>
|
|
98
|
-
readonly motionGroup: WithUnwrappedAxiosResponse<MotionGroupApi>
|
|
99
|
-
readonly motionGroupModels: WithUnwrappedAxiosResponse<MotionGroupModelsApi>
|
|
100
|
-
readonly novaCloud: WithUnwrappedAxiosResponse<NOVACloudApi>
|
|
101
|
-
readonly program: WithUnwrappedAxiosResponse<ProgramApi>
|
|
102
|
-
readonly robotConfigurations: WithUnwrappedAxiosResponse<RobotConfigurationsApi>
|
|
103
|
-
readonly session: WithUnwrappedAxiosResponse<SessionApi>
|
|
104
|
-
readonly storeCollisionComponents: WithUnwrappedAxiosResponse<StoreCollisionComponentsApi>
|
|
105
|
-
readonly storeCollisionSetups: WithUnwrappedAxiosResponse<StoreCollisionSetupsApi>
|
|
106
|
-
readonly storeObject: WithUnwrappedAxiosResponse<StoreObjectApi>
|
|
107
|
-
readonly system: WithUnwrappedAxiosResponse<SystemApi>
|
|
108
|
-
readonly trajectoryCaching: WithUnwrappedAxiosResponse<TrajectoryCachingApi>
|
|
109
|
-
readonly trajectoryExecution: WithUnwrappedAxiosResponse<TrajectoryExecutionApi>
|
|
110
|
-
readonly trajectoryPlanning: WithUnwrappedAxiosResponse<TrajectoryPlanningApi>
|
|
111
|
-
readonly version: WithUnwrappedAxiosResponse<VersionApi>
|
|
112
|
-
readonly virtualController: WithUnwrappedAxiosResponse<VirtualControllerApi>
|
|
113
|
-
readonly virtualControllerBehavior: WithUnwrappedAxiosResponse<VirtualControllerBehaviorApi>
|
|
114
|
-
readonly virtualControllerIOs: WithUnwrappedAxiosResponse<VirtualControllerInputsOutputsApi>
|
|
115
|
-
|
|
116
124
|
constructor(opts: NovaAPIClientOpts) {
|
|
117
125
|
this.opts = opts
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
127
|
+
for (const [name, value] of Object.entries(novaApiV2)) {
|
|
128
|
+
if (isApiClass(name, value)) {
|
|
129
|
+
const stripped = name.slice(0, -3)
|
|
130
|
+
// Lowercase leading acronym run: "BUSInputsOutputs" -> "busInputsOutputs"
|
|
131
|
+
let i = 0
|
|
132
|
+
while (
|
|
133
|
+
i < stripped.length &&
|
|
134
|
+
stripped[i] === stripped[i].toUpperCase() &&
|
|
135
|
+
stripped[i] !== stripped[i].toLowerCase()
|
|
136
|
+
) {
|
|
137
|
+
i++
|
|
138
|
+
}
|
|
139
|
+
// If multiple uppercase chars, keep the last one uppercase (it starts the next word)
|
|
140
|
+
const boundary = i > 1 ? i - 1 : i
|
|
141
|
+
const propName =
|
|
142
|
+
stripped.slice(0, boundary).toLowerCase() + stripped.slice(boundary)
|
|
143
|
+
// biome-ignore lint/suspicious/noExplicitAny: dynamically assigning discovered API properties
|
|
144
|
+
;(this as any)[propName] = wrapApi(value, opts)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} as {
|
|
149
|
+
new (
|
|
150
|
+
opts: NovaAPIClientOpts,
|
|
151
|
+
): ApiProperties & {
|
|
152
|
+
readonly cellId: string
|
|
153
|
+
readonly opts: NovaAPIClientOpts
|
|
144
154
|
}
|
|
145
155
|
}
|
|
156
|
+
|
|
157
|
+
export type NovaAPIClient = InstanceType<typeof NovaAPIClient>
|