@wandelbots/nova-js
Version:
Official JS client for the Wandelbots API
1 lines • 40.5 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","names":["cellId: string","opts: BaseConfiguration & {\n axiosInstance?: AxiosInstance\n mock?: boolean\n }","SystemApi","CellApi","MotionGroupApi","MotionGroupModelsApi","ControllerApi","ControllerInputsOutputsApi","TrajectoryPlanningApi","TrajectoryExecutionApi","TrajectoryCachingApi","ApplicationApi","JoggingApi","KinematicsApi","BUSInputsOutputsApi","VirtualControllerApi","VirtualControllerBehaviorApi","VirtualControllerInputsOutputsApi","StoreObjectApi","StoreCollisionComponentsApi","StoreCollisionSetupsApi","pathToRegexp","AxiosError","availableStorage","config","loginWithAuth0","AutoReconnectingWebsocket"],"sources":["../../../src/lib/v2/NovaCellAPIClient.ts","../../../src/lib/v2/mock/MockNovaInstance.ts","../../../src/lib/v2/NovaClient.ts","../../../src/lib/v2/wandelscriptUtils.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny: legacy code */\n/** biome-ignore-all lint/style/noNonNullAssertion: legacy code */\nimport type {\n BaseAPI,\n Configuration as BaseConfiguration,\n} from \"@wandelbots/nova-api/v2\"\nimport {\n ApplicationApi,\n BUSInputsOutputsApi,\n CellApi,\n ControllerApi,\n ControllerInputsOutputsApi,\n JoggingApi,\n KinematicsApi,\n MotionGroupApi,\n MotionGroupModelsApi,\n StoreCollisionComponentsApi,\n StoreCollisionSetupsApi,\n StoreObjectApi,\n SystemApi,\n TrajectoryCachingApi,\n TrajectoryExecutionApi,\n TrajectoryPlanningApi,\n VirtualControllerApi,\n VirtualControllerBehaviorApi,\n VirtualControllerInputsOutputsApi,\n} from \"@wandelbots/nova-api/v2\"\nimport type { AxiosInstance } from \"axios\"\nimport axios from \"axios\"\n\ntype OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R\n ? (...args: P) => R\n : never\n\ntype UnwrapAxiosResponseReturn<T> = T extends (...a: any) => any\n ? (\n ...a: Parameters<T>\n ) => Promise<Awaited<ReturnType<T>> extends { data: infer D } ? D : never>\n : never\n\nexport type WithCellId<T> = {\n [P in keyof T]: UnwrapAxiosResponseReturn<OmitFirstArg<T[P]>>\n}\n\nexport type WithUnwrappedAxiosResponse<T> = {\n [P in keyof T]: UnwrapAxiosResponseReturn<T[P]>\n}\n\n/**\n * API client providing type-safe access to all the Nova API REST endpoints\n * associated with a specific cell id.\n */\nexport class NovaCellAPIClient {\n constructor(\n readonly cellId: string,\n readonly opts: BaseConfiguration & {\n axiosInstance?: AxiosInstance\n mock?: boolean\n },\n ) {}\n\n /**\n * Some TypeScript sorcery which alters the API class methods so you don't\n * have to pass the cell id to every single one, and de-encapsulates the\n * response data\n */\n private withCellId<T extends BaseAPI>(\n ApiConstructor: new (\n config: BaseConfiguration,\n basePath: string,\n axios: AxiosInstance,\n ) => T,\n ) {\n const apiClient = new ApiConstructor(\n {\n ...this.opts,\n isJsonMime: (mime: string) => {\n return mime === \"application/json\"\n },\n },\n this.opts.basePath ?? \"\",\n this.opts.axiosInstance ?? axios.create(),\n ) as {\n [key: string | symbol]: any\n }\n\n for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient)!)) {\n if (key !== \"constructor\" && typeof apiClient[key] === \"function\") {\n const originalFunction = apiClient[key]\n apiClient[key] = (...args: any[]) => {\n return originalFunction\n .apply(apiClient, [this.cellId, ...args])\n .then((res: any) => res.data)\n }\n }\n }\n\n return apiClient as WithCellId<T>\n }\n\n /**\n * As withCellId, but only does the response unwrapping\n */\n private withUnwrappedResponsesOnly<T extends BaseAPI>(\n ApiConstructor: new (\n config: BaseConfiguration,\n basePath: string,\n axios: AxiosInstance,\n ) => T,\n ) {\n const apiClient = new ApiConstructor(\n {\n ...this.opts,\n isJsonMime: (mime: string) => {\n return mime === \"application/json\"\n },\n },\n this.opts.basePath ?? \"\",\n this.opts.axiosInstance ?? axios.create(),\n ) as {\n [key: string | symbol]: any\n }\n\n for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient)!)) {\n if (key !== \"constructor\" && typeof apiClient[key] === \"function\") {\n const originalFunction = apiClient[key]\n apiClient[key] = (...args: any[]) => {\n return originalFunction\n .apply(apiClient, args)\n .then((res: any) => res.data)\n }\n }\n }\n\n return apiClient as WithUnwrappedAxiosResponse<T>\n }\n\n readonly system = this.withUnwrappedResponsesOnly(SystemApi)\n readonly cell = this.withUnwrappedResponsesOnly(CellApi)\n\n readonly motionGroup = this.withCellId(MotionGroupApi)\n readonly motionGroupModels = this.withCellId(MotionGroupModelsApi)\n\n readonly controller = this.withCellId(ControllerApi)\n\n readonly controllerIOs = this.withCellId(ControllerInputsOutputsApi)\n\n readonly trajectoryPlanning = this.withCellId(TrajectoryPlanningApi)\n readonly trajectoryExecution = this.withCellId(TrajectoryExecutionApi)\n readonly trajectoryCaching = this.withCellId(TrajectoryCachingApi)\n\n readonly application = this.withCellId(ApplicationApi)\n readonly applicationGlobal = this.withUnwrappedResponsesOnly(ApplicationApi)\n\n readonly jogging = this.withCellId(JoggingApi)\n\n readonly kinematics = this.withCellId(KinematicsApi)\n\n readonly busInputsOutputs = this.withCellId(BUSInputsOutputsApi)\n\n readonly virtualController = this.withCellId(VirtualControllerApi)\n readonly virtualControllerBehavior = this.withCellId(\n VirtualControllerBehaviorApi,\n )\n readonly virtualControllerIOs = this.withCellId(\n VirtualControllerInputsOutputsApi,\n )\n\n readonly storeObject = this.withCellId(StoreObjectApi)\n readonly storeCollisionComponents = this.withCellId(\n StoreCollisionComponentsApi,\n )\n readonly storeCollisionSetups = this.withCellId(StoreCollisionSetupsApi)\n}\n","/** biome-ignore-all lint/suspicious/noApproximativeNumericConstant: mock data contains approximative pi values from robot description */\nimport type { MotionGroupState, RobotController } from \"@wandelbots/nova-api/v2\"\nimport type { AxiosResponse, InternalAxiosRequestConfig } from \"axios\"\nimport { AxiosError } from \"axios\"\nimport * as pathToRegexp from \"path-to-regexp\"\nimport type { AutoReconnectingWebsocket } from \"../../AutoReconnectingWebsocket\"\n\n/**\n * Ultra-simplified mock Nova server for testing stuff\n */\nexport class MockNovaInstance {\n readonly connections: AutoReconnectingWebsocket[] = []\n\n async handleAPIRequest(\n config: InternalAxiosRequestConfig,\n ): Promise<AxiosResponse> {\n const apiHandlers = [\n {\n method: \"GET\",\n path: \"/cells/:cellId/controllers\",\n handle() {\n return [\"mock-ur5e\"]\n },\n },\n {\n method: \"GET\",\n path: \"/cells/:cellId/controllers/:controllerId\",\n handle() {\n return {\n configuration: {\n initial_joint_position: \"[0,-1.571,-1.571,-1.571,1.571,-1.571,0]\",\n kind: \"VirtualController\",\n manufacturer: \"universalrobots\",\n type: \"universalrobots-ur5e\",\n },\n name: \"mock-ur5\",\n } satisfies RobotController\n },\n },\n {\n method: \"GET\",\n path: \"/cells/:cellId/controllers/:controllerId/state\",\n handle() {\n return {\n mode: \"MODE_CONTROL\",\n last_error: [],\n timestamp: \"2025-10-16T09:19:26.634534092Z\",\n sequence_number: 1054764,\n controller: \"mock-ur5e\",\n operation_mode: \"OPERATION_MODE_AUTO\",\n safety_state: \"SAFETY_STATE_NORMAL\",\n velocity_override: 100,\n motion_groups: [\n {\n timestamp: \"2025-10-16T09:19:26.634534092Z\",\n sequence_number: 1054764,\n motion_group: \"0@mock-ur5e\",\n controller: \"mock-ur5e\",\n joint_position: [\n 1.487959623336792, -1.8501918315887451, 1.8003005981445312,\n 6.034560203552246, 1.4921919107437134, 1.593459963798523,\n ],\n joint_limit_reached: {\n limit_reached: [false, false, false, false, false, false],\n },\n joint_torque: [],\n joint_current: [0, 0, 0, 0, 0, 0],\n flange_pose: {\n position: [\n 107.6452433732927, -409.0402987746852, 524.2402132330305,\n ],\n orientation: [\n 0.9874434028353319, -0.986571714997442, 1.3336589451098142,\n ],\n },\n tcp: \"Flange\",\n tcp_pose: {\n position: [\n 107.6452433732927, -409.0402987746852, 524.2402132330305,\n ],\n orientation: [\n 0.9874434028353319, -0.986571714997442, 1.3336589451098142,\n ],\n },\n payload: \"\",\n coordinate_system: \"\",\n standstill: true,\n },\n ],\n }\n },\n },\n {\n method: \"GET\",\n path: \"/cells/:cellId/controllers/:controllerId/motion-groups/:motionGroupId/description\",\n handle() {\n return {\n motion_group_model: \"UniversalRobots_UR5e\",\n mounting: {\n position: [0, 0, 0],\n orientation: [0, 0, 0],\n },\n tcps: {\n Flange: {\n name: \"Default-Flange\",\n pose: {\n position: [0, 0, 0],\n orientation: [0, 0, 0],\n },\n },\n },\n payloads: {\n \"FPay-0\": {\n name: \"FPay-0\",\n payload: 0,\n center_of_mass: [0, 0, 0],\n moment_of_inertia: [0, 0, 0],\n },\n },\n cycle_time: 8,\n dh_parameters: [\n {\n alpha: 1.5707963267948966,\n d: 162.25,\n },\n {\n a: -425,\n },\n {\n a: -392.2,\n },\n {\n alpha: 1.5707963267948966,\n d: 133.3,\n },\n {\n alpha: -1.5707963267948966,\n d: 99.7,\n },\n {\n d: 99.6,\n },\n ],\n operation_limits: {\n auto_limits: {\n joints: [\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n ],\n tcp: {\n velocity: 5000,\n },\n elbow: {\n velocity: 5000,\n },\n flange: {\n velocity: 5000,\n },\n },\n manual_limits: {\n joints: [\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n ],\n tcp: {\n velocity: 5000,\n },\n },\n manual_t1_limits: {\n joints: [\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n ],\n tcp: {\n velocity: 5000,\n },\n },\n manual_t2_limits: {\n joints: [\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 150,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n {\n position: {\n lower_limit: -6.283185307179586,\n upper_limit: 6.283185307179586,\n },\n velocity: 3.34159255027771,\n acceleration: 40,\n torque: 28,\n },\n ],\n tcp: {\n velocity: 5000,\n },\n },\n },\n serial_number: \"WBVirtualRobot\",\n }\n },\n },\n {\n method: \"GET\",\n path: \"/cells/:cellId/controllers/:controllerId/coordinate-systems\",\n handle() {\n return [\n {\n coordinate_system: \"\",\n name: \"world\",\n reference_coordinate_system: \"\",\n position: [0, 0, 0],\n orientation: [0, 0, 0],\n orientation_type: \"ROTATION_VECTOR\",\n },\n {\n coordinate_system: \"CS-0\",\n name: \"Default-CS\",\n reference_coordinate_system: \"\",\n position: [0, 0, 0],\n orientation: [0, 0, 0],\n orientation_type: \"ROTATION_VECTOR\",\n },\n ] //satisfies CoordinateSystems\n },\n },\n ]\n\n const method = config.method?.toUpperCase() || \"GET\"\n const path = `/cells${config.url?.split(\"/cells\")[1]?.split(\"?\")[0]}`\n\n for (const handler of apiHandlers) {\n const match = pathToRegexp.match(handler.path)(path || \"\")\n if (method === handler.method && match) {\n const json = handler.handle()\n return {\n status: 200,\n statusText: \"Success\",\n data: JSON.stringify(json),\n headers: {},\n config,\n request: {\n responseURL: config.url,\n },\n }\n }\n }\n\n throw new AxiosError(\n `No mock handler matched this request: ${method} ${path}`,\n \"404\",\n config,\n )\n\n // return {\n // status: 404,\n // statusText: \"Not Found\",\n // data: \"\",\n // headers: {},\n // config,\n // request: {\n // responseURL: config.url,\n // },\n // }\n }\n\n // Please note: Only very basic websocket mocking is done here, needs to be extended as needed\n handleWebsocketConnection(socket: AutoReconnectingWebsocket) {\n this.connections.push(socket)\n\n setTimeout(() => {\n socket.dispatchEvent(new Event(\"open\"))\n\n console.log(\"Websocket connection opened from\", socket.url)\n\n if (socket.url.includes(\"/state-stream\")) {\n socket.dispatchEvent(\n new MessageEvent(\"message\", {\n data: JSON.stringify(defaultMotionState),\n }),\n )\n }\n\n if (socket.url.includes(\"/execution/jogging\")) {\n socket.dispatchEvent(\n new MessageEvent(\"message\", {\n data: JSON.stringify({\n result: {\n message: \"string\",\n kind: \"INITIALIZE_RECEIVED\",\n },\n }),\n }),\n )\n }\n }, 10)\n }\n\n handleWebsocketMessage(socket: AutoReconnectingWebsocket, message: string) {\n console.log(`Received message on ${socket.url}`, message)\n }\n}\n\nconst defaultMotionState = {\n result: {\n motion_group: \"0@universalrobots-ur5e\",\n controller: \"universalrobots-ur5e\",\n timestamp: new Date().toISOString(),\n sequence_number: 1,\n joint_position: [\n 1.1699999570846558, -1.5700000524520874, 1.3600000143051147,\n 1.0299999713897705, 1.2899999618530273, 1.2799999713897705,\n ],\n joint_limit_reached: {\n limit_reached: [false, false, false, false, false, false],\n },\n standstill: false,\n flange_pose: {\n position: [1.3300010259703043, -409.2680714682808, 531.0203477065281],\n orientation: [\n 1.7564919306270736, -1.7542521568325058, 0.7326972590614671,\n ],\n },\n tcp_pose: {\n position: [1.3300010259703043, -409.2680714682808, 531.0203477065281],\n orientation: [\n 1.7564919306270736, -1.7542521568325058, 0.7326972590614671,\n ],\n },\n } satisfies MotionGroupState,\n}\n","/** biome-ignore-all lint/style/noNonNullAssertion: legacy code */\nimport type { Configuration as BaseConfiguration } from \"@wandelbots/nova-api/v2\"\nimport type { AxiosRequestConfig } from \"axios\"\nimport axios, { isAxiosError } from \"axios\"\nimport urlJoin from \"url-join\"\nimport { loginWithAuth0 } from \"../../LoginWithAuth0\"\nimport { AutoReconnectingWebsocket } from \"../AutoReconnectingWebsocket\"\nimport { availableStorage } from \"../availableStorage\"\nimport { MockNovaInstance } from \"./mock/MockNovaInstance\"\nimport { NovaCellAPIClient } from \"./NovaCellAPIClient\"\n\nexport type NovaClientConfig = {\n /**\n * Url of the deployed Nova instance to connect to\n * e.g. https://saeattii.instance.wandelbots.io\n */\n instanceUrl: string | \"https://mock.example.com\"\n\n /**\n * Identifier of the cell on the Nova instance to connect this client to.\n * If omitted, the default identifier \"cell\" is used.\n **/\n cellId?: string\n\n /**\n * Username for basic auth to the Nova instance.\n * @deprecated use accessToken instead\n */\n username?: string\n\n /**\n * Password for basic auth to the Nova instance.\n * @deprecated use accessToken instead\n */\n password?: string\n\n /**\n * Access token for Bearer authentication.\n */\n accessToken?: string\n} & Omit<BaseConfiguration, \"isJsonMime\" | \"basePath\">\n\ntype NovaClientConfigWithDefaults = NovaClientConfig & { cellId: string }\n\nfunction permissiveInstanceUrlParse(url: string): string {\n if (!url.startsWith(\"http\")) {\n url = `http://${url}`\n }\n\n return new URL(url).toString()\n}\n\n/**\n *\n * Client for connecting to a Nova instance and controlling robots.\n */\nexport class NovaClient {\n readonly api: NovaCellAPIClient\n readonly config: NovaClientConfigWithDefaults\n readonly mock?: MockNovaInstance\n authPromise: Promise<string | null> | null = null\n accessToken: string | null = null\n\n constructor(config: NovaClientConfig) {\n const cellId = config.cellId ?? \"cell\"\n this.config = {\n cellId,\n ...config,\n }\n this.accessToken =\n config.accessToken ||\n availableStorage.getString(\"wbjs.access_token\") ||\n null\n\n if (this.config.instanceUrl === \"https://mock.example.com\") {\n this.mock = new MockNovaInstance()\n } else {\n this.config.instanceUrl = permissiveInstanceUrlParse(\n this.config.instanceUrl,\n )\n }\n\n // Set up Axios instance with interceptor for token fetching\n const axiosInstance = axios.create({\n baseURL: urlJoin(this.config.instanceUrl, \"/api/v2\"),\n // TODO - backend needs to set proper CORS headers for this\n headers:\n typeof window !== \"undefined\" &&\n window.location.origin.includes(\"localhost\")\n ? {}\n : {\n // Identify the client to the backend for logging purposes\n \"X-Wandelbots-Client\": \"Wandelbots-Nova-JS-SDK\",\n },\n })\n\n axiosInstance.interceptors.request.use(async (request) => {\n if (!request.headers.Authorization) {\n if (this.accessToken) {\n request.headers.Authorization = `Bearer ${this.accessToken}`\n } else if (this.config.username && this.config.password) {\n request.headers.Authorization = `Basic ${btoa(`${config.username}:${config.password}`)}`\n }\n }\n return request\n })\n\n if (typeof window !== \"undefined\") {\n axiosInstance.interceptors.response.use(\n (r) => r,\n async (error) => {\n if (isAxiosError(error)) {\n if (error.response?.status === 401) {\n // If we hit a 401, attempt to login the user and retry with\n // a new access token\n try {\n await this.renewAuthentication()\n\n if (error.config) {\n if (this.accessToken) {\n error.config.headers.Authorization = `Bearer ${this.accessToken}`\n } else {\n delete error.config.headers.Authorization\n }\n return axiosInstance.request(error.config)\n }\n } catch (err) {\n return Promise.reject(err)\n }\n } else if (error.response?.status === 503) {\n // Check if the server as a whole is down\n const res = await fetch(window.location.href)\n if (res.status === 503) {\n // Go to 503 page\n window.location.reload()\n }\n }\n }\n\n return Promise.reject(error)\n },\n )\n }\n\n this.api = new NovaCellAPIClient(cellId, {\n ...config,\n basePath: urlJoin(this.config.instanceUrl, \"/api/v2\"),\n isJsonMime: (mime: string) => {\n return mime === \"application/json\"\n },\n baseOptions: {\n ...(this.mock\n ? ({\n adapter: (config) => {\n return this.mock!.handleAPIRequest(config)\n },\n } satisfies AxiosRequestConfig)\n : {}),\n ...config.baseOptions,\n },\n axiosInstance,\n })\n }\n\n async renewAuthentication(): Promise<void> {\n if (this.authPromise) {\n // Don't double up\n return\n }\n\n this.authPromise = loginWithAuth0(this.config.instanceUrl)\n try {\n this.accessToken = await this.authPromise\n if (this.accessToken) {\n // Cache access token so we don't need to log in every refresh\n availableStorage.setString(\"wbjs.access_token\", this.accessToken)\n } else {\n availableStorage.delete(\"wbjs.access_token\")\n }\n } finally {\n this.authPromise = null\n }\n }\n\n makeWebsocketURL(path: string): string {\n const url = new URL(\n urlJoin(\n this.config.instanceUrl,\n `/api/v2/cells/${this.config.cellId}`,\n path,\n ),\n )\n url.protocol = url.protocol.replace(\"http\", \"ws\")\n url.protocol = url.protocol.replace(\"https\", \"wss\")\n\n // If provided, add basic auth credentials to the URL\n // NOTE - basic auth is deprecated on websockets and doesn't work in Safari\n // use tokens instead\n if (this.accessToken) {\n url.searchParams.append(\"token\", this.accessToken)\n } else if (this.config.username && this.config.password) {\n url.username = this.config.username\n url.password = this.config.password\n }\n\n return url.toString()\n }\n\n /**\n * Retrieve an AutoReconnectingWebsocket to the given path on the Nova instance.\n * If you explicitly want to reconnect an existing websocket, call `reconnect`\n * on the returned object.\n */\n openReconnectingWebsocket(path: string) {\n return new AutoReconnectingWebsocket(this.makeWebsocketURL(path), {\n mock: this.mock,\n })\n }\n}\n","import type { Pose } from \"@wandelbots/nova-api/v2\"\n\n/**\n * Convert a Pose object representing a motion group position\n * into a string which represents that pose in Wandelscript.\n */\nexport function poseToWandelscriptString(\n pose: Pick<Pose, \"position\" | \"orientation\">,\n) {\n const position = [\n pose.position?.[0] ?? 0,\n pose.position?.[1] ?? 0,\n pose.position?.[2] ?? 0,\n ]\n\n const orientation = [\n pose.orientation?.[0] ?? 0,\n pose.orientation?.[1] ?? 0,\n pose.orientation?.[2] ?? 0,\n ]\n\n const positionValues = position.map((v) => v.toFixed(1))\n // Rotation needs more precision since it's in radians\n const rotationValues = orientation.map((v) => v.toFixed(4))\n\n return `(${positionValues.concat(rotationValues).join(\", \")})`\n}\n"],"mappings":"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OACN,MAAM;QACJ,UAAU;SAAC;SAAG;SAAG;SAAE;QACnB,aAAa;SAAC;SAAG;SAAG;SAAE;QACvB;OACF,EACF;MACD,UAAU,EACR,UAAU;OACR,MAAM;OACN,SAAS;OACT,gBAAgB;QAAC;QAAG;QAAG;QAAE;OACzB,mBAAmB;QAAC;QAAG;QAAG;QAAE;OAC7B,EACF;MACD,YAAY;MACZ,eAAe;OACb;QACE,OAAO;QACP,GAAG;QACJ;OACD,EACE,GAAG,MACJ;OACD,EACE,GAAG,QACJ;OACD;QACE,OAAO;QACP,GAAG;QACJ;OACD;QACE,OAAO;QACP,GAAG;QACJ;OACD,EACE,GAAG,MACJ;OACF;MACD,kBAAkB;OAChB,aAAa;QACX,QAAQ;SACN;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACF;QACD,KAAK,EACH,UAAU,KACX;QACD,OAAO,EACL,UAAU,KACX;QACD,QAAQ,EACN,UAAU,KACX;QACF;OACD,eAAe;QACb,QAAQ;SACN;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACF;QACD,KAAK,EACH,UAAU,KACX;QACF;OACD,kBAAkB;QAChB,QAAQ;SACN;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACF;QACD,KAAK,EACH,UAAU,KACX;QACF;OACD,kBAAkB;QAChB,QAAQ;SACN;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UACD,UAAU;UACV,cAAc;UACd,QAAQ;UACT;SACD;UACE,UAAU;WACR,aAAa;WACb,aAAa;WACd;UAC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"}