@volant-autonomy/via-sdk 1.3748.1 → 1.3757.1

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.
@@ -1,5 +1,12 @@
1
- import { createPathingTask, Direct } from './direct';
2
- import { schemas, Waypoint } from './types';
1
+ import { createPathingTask, Direct, PathingTaskEvent } from './direct';
2
+ import { schemas } from './types';
3
+ export type StreamError = {
4
+ errors: {
5
+ detail: string;
6
+ status: string;
7
+ }[];
8
+ status: string;
9
+ };
3
10
  export declare class Composite {
4
11
  private direct;
5
12
  constructor(direct: Direct);
@@ -160,8 +167,23 @@ export declare class Composite {
160
167
  status: "401" | "400" | "422" | "404";
161
168
  };
162
169
  }>;
163
- /** Handles creating and polling a pathing task for you */
164
- doPathingTask(args: createPathingTask['requestBody']['content']['application/json']): Promise<{
170
+ /**
171
+ * Handles fetching a pathing task once it has reached a final state. This will be completed through one of two
172
+ * methods:
173
+ *
174
+ * - Event stream (default) - Opens an event stream and optionally calls onMessage when the state changes. The
175
+ * callback will not be called once the task is complete as the task being complete can be inferred from the stream
176
+ * being closed.
177
+ *
178
+ * - Polling (fallback) - Occurs automatically if the connection to the event stream is unsuccessful or the stream
179
+ * fails. Polls every 0.5s whilst queuing and every 0.2s whilst in progress. Note if onMessage is defined it is
180
+ * called on every poll.
181
+ * @param taskId - A UUID value that identifies a pathing task
182
+ * @param onMessage - Callback that is called upon receiving details on the state of the pathing task
183
+ * @returns - The result of the pathing task
184
+ */
185
+ getPathingTaskResult(taskId: string, onMessage?: (payload: PathingTaskEvent) => void): Promise<{
186
+ data?: never;
165
187
  error: {
166
188
  errors: {
167
189
  detail: string;
@@ -169,12 +191,48 @@ export declare class Composite {
169
191
  }[];
170
192
  status: "401" | "400" | "422" | "404";
171
193
  };
172
- data?: undefined;
194
+ response: Response;
195
+ aborted: false;
173
196
  } | {
174
- data: Waypoint[];
175
- error?: undefined;
197
+ data: {
198
+ id: string;
199
+ type?: "pathing_task";
200
+ attributes?: import("./volant-schema").components["schemas"]["PathingTaskAttributes"] | null;
201
+ meta: import("./volant-schema").components["schemas"]["PathingTaskMeta"];
202
+ };
203
+ error?: never;
204
+ response: Response;
205
+ aborted: false;
206
+ }>;
207
+ /** Handles creating and waiting for the result of a pathing task. */
208
+ doPathingTask(args: createPathingTask['requestBody']['content']['application/json']): Promise<{
209
+ errors: {
210
+ detail: string;
211
+ status: "401" | "400" | "422";
212
+ }[];
213
+ status: "401" | "400" | "422";
176
214
  } | {
177
- error: number;
178
- data?: undefined;
215
+ data?: never;
216
+ error: {
217
+ errors: {
218
+ detail: string;
219
+ status: "401" | "400" | "422" | "404";
220
+ }[];
221
+ status: "401" | "400" | "422" | "404";
222
+ };
223
+ response: Response;
224
+ aborted: false;
225
+ } | {
226
+ data: {
227
+ id: string;
228
+ type?: "pathing_task";
229
+ attributes?: import("./volant-schema").components["schemas"]["PathingTaskAttributes"] | null;
230
+ meta: import("./volant-schema").components["schemas"]["PathingTaskMeta"];
231
+ };
232
+ error?: never;
233
+ response: Response;
234
+ aborted: false;
179
235
  }>;
236
+ private pathingTaskStreamResult;
237
+ private pathingTaskPollResult;
180
238
  }
package/dist/direct.d.ts CHANGED
@@ -5,7 +5,7 @@ type requestOptions = {
5
5
  abortKey?: string;
6
6
  fetch?: typeof globalThis.fetch;
7
7
  };
8
- type PathingTaskEvent = {
8
+ export type PathingTaskEvent = {
9
9
  state: PathingTaskState;
10
10
  terminated: boolean;
11
11
  };
@@ -608,7 +608,7 @@ export declare class Direct {
608
608
  * task changes. Once it has reached it's final state, the last update is pushed and the stream is automatically
609
609
  * closed.
610
610
  */
611
- getPathingTaskStateStream(id: pathOf<getPathingTaskStateStream>['pathing_task_id'], onMessage?: (payload: PathingTaskEvent) => void, onFail?: () => void): Promise<PathingTaskEvent>;
611
+ getPathingTaskStateStream(id: pathOf<getPathingTaskStateStream>['pathing_task_id']): EventSource;
612
612
  /**
613
613
  * List all available Charts
614
614
  * @description List user's charts, including chart id and bounds.
package/dist/fetch.d.ts CHANGED
@@ -119,6 +119,7 @@ export declare class Fetcher<Paths extends Record<string, Record<HttpMethod, {}>
119
119
  DELETE<Path extends PathsWithMethod<Paths, 'delete'>, Data extends MaybeOptionalParams<Paths[Path], 'delete'>, Opts extends requestOptions = {}>(path: Path, data: HasRequiredKeys<Data> extends never ? Data | undefined : Data, opts?: Opts): Promise<FetchResponse<Paths[Path]["delete"], Opts>>;
120
120
  OPTIONS<Path extends PathsWithMethod<Paths, 'options'>, Data extends MaybeOptionalParams<Paths[Path], 'options'>, Opts extends requestOptions = {}>(path: Path, data: HasRequiredKeys<Data> extends never ? Data | undefined : Data, opts?: Opts): Promise<FetchResponse<Paths[Path]["options"], Opts>>;
121
121
  HEAD<Path extends PathsWithMethod<Paths, 'head'>, Data extends MaybeOptionalParams<Paths[Path], 'head'>, Opts extends requestOptions = {}>(path: Path, data: HasRequiredKeys<Data> extends never ? Data | undefined : Data, opts?: Opts): Promise<FetchResponse<Paths[Path]["head"], Opts>>;
122
+ STREAM<Path extends PathsWithMethod<Paths, 'get'>, Data extends MaybeOptionalParams<Paths[Path], 'get'>>(path: Path, data: HasRequiredKeys<Data> extends never ? Data | undefined : Data): EventSource;
122
123
  }
123
124
  export default function createFetcher<Paths extends {}>(...args: ConstructorParameters<typeof Fetcher>): Fetcher<Paths>;
124
125
  export {};
package/dist/index.cjs.js CHANGED
@@ -15,6 +15,12 @@ class UnauthenticatedError extends Error {
15
15
  }
16
16
  }
17
17
 
18
+ class StreamFailedError extends Error {
19
+ }
20
+ class TaskTimeoutError extends Error {
21
+ }
22
+ const PathingTaskTimeout = 30000;
23
+ const ValidStreamTimeout = 5000;
18
24
  class Composite {
19
25
  constructor(direct) {
20
26
  this.direct = direct;
@@ -55,36 +61,107 @@ class Composite {
55
61
  return this.direct.modifyDraftFlightplan(id, data.attributes);
56
62
  }
57
63
  /// pathing tasks
58
- /** Handles creating and polling a pathing task for you */
59
- async doPathingTask(args) {
60
- var _a, _b;
61
- const { error, data } = await this.direct.createPathingTask(args);
62
- if (error) {
63
- return { error };
64
+ /**
65
+ * Handles fetching a pathing task once it has reached a final state. This will be completed through one of two
66
+ * methods:
67
+ *
68
+ * - Event stream (default) - Opens an event stream and optionally calls onMessage when the state changes. The
69
+ * callback will not be called once the task is complete as the task being complete can be inferred from the stream
70
+ * being closed.
71
+ *
72
+ * - Polling (fallback) - Occurs automatically if the connection to the event stream is unsuccessful or the stream
73
+ * fails. Polls every 0.5s whilst queuing and every 0.2s whilst in progress. Note if onMessage is defined it is
74
+ * called on every poll.
75
+ * @param taskId - A UUID value that identifies a pathing task
76
+ * @param onMessage - Callback that is called upon receiving details on the state of the pathing task
77
+ * @returns - The result of the pathing task
78
+ */
79
+ async getPathingTaskResult(taskId, onMessage) {
80
+ try {
81
+ await this.pathingTaskStreamResult(taskId, onMessage);
82
+ }
83
+ catch (error) {
84
+ if (error instanceof StreamFailedError) {
85
+ await this.pathingTaskPollResult(taskId, onMessage);
86
+ }
64
87
  }
65
- const id = data.id;
66
- while (true) {
67
- const { data, error } = await this.direct.getPathingTask(id);
68
- if (error) {
69
- return { error };
88
+ return this.direct.getPathingTask(taskId);
89
+ }
90
+ /** Handles creating and waiting for the result of a pathing task. */
91
+ async doPathingTask(args) {
92
+ const createdTask = await this.direct.createPathingTask(args);
93
+ if (createdTask.error) {
94
+ return createdTask.error;
95
+ }
96
+ const id = createdTask.data.id;
97
+ return await this.getPathingTaskResult(id);
98
+ }
99
+ async pathingTaskStreamResult(taskId, onMessage) {
100
+ let streamConnectionTimeout;
101
+ let streamNotSuccessfulTimeout;
102
+ const promise = new Promise((resolve, reject) => {
103
+ const stream = this.direct.getPathingTaskStateStream(taskId);
104
+ streamConnectionTimeout = setTimeout(() => {
105
+ if (stream.readyState !== EventSource.OPEN) {
106
+ stream.close();
107
+ reject(new StreamFailedError('Timeout connecting'));
108
+ }
109
+ }, ValidStreamTimeout);
110
+ streamNotSuccessfulTimeout = setTimeout(() => {
111
+ stream.close();
112
+ reject(new TaskTimeoutError('Timeout whilst waiting for successful result'));
113
+ }, PathingTaskTimeout);
114
+ stream.onmessage = async (event) => {
115
+ // TODO(Jack): Use a discriminated union
116
+ const data = JSON.parse(event.data);
117
+ if (data.error === true) {
118
+ stream.close();
119
+ reject(new Error(`Task stream returned error: ${data.payload}`));
120
+ return;
121
+ }
122
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(data.payload);
123
+ if (data.payload.terminated === true) {
124
+ stream.close();
125
+ resolve(data.payload);
126
+ }
127
+ };
128
+ stream.onerror = (error) => {
129
+ stream.close();
130
+ reject(new StreamFailedError(`Stream failed: ${error}`));
131
+ };
132
+ });
133
+ return promise.finally(() => {
134
+ clearTimeout(streamConnectionTimeout);
135
+ clearTimeout(streamNotSuccessfulTimeout);
136
+ });
137
+ }
138
+ async pathingTaskPollResult(taskId, onMessage) {
139
+ let runPathing = true;
140
+ while (runPathing) {
141
+ setTimeout(() => {
142
+ runPathing = false;
143
+ }, PathingTaskTimeout);
144
+ const pathingTaskResult = await this.direct.getPathingTask(taskId);
145
+ if (pathingTaskResult.error) {
146
+ return pathingTaskResult.error;
147
+ }
148
+ if (pathingTaskResult.data.meta.state === 'successful' ||
149
+ pathingTaskResult.data.meta.state === 'failed') {
150
+ return;
70
151
  }
71
- switch (data.meta.state) {
152
+ const pathingTaskPayload = {
153
+ state: pathingTaskResult.data.meta.state,
154
+ terminated: false
155
+ };
156
+ // TODO: Make this only on change from previous
157
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(pathingTaskPayload);
158
+ switch (pathingTaskResult.data.meta.state) {
72
159
  case 'queued':
73
160
  await sleep(500);
74
- continue;
161
+ break;
75
162
  case 'in-progress':
76
- await sleep(50);
77
- continue;
78
- case 'successful':
79
- if ((_a = data.attributes) === null || _a === void 0 ? void 0 : _a.waypoints) {
80
- return { data: (_b = data.attributes) === null || _b === void 0 ? void 0 : _b.waypoints };
81
- }
82
- else {
83
- throw new Error(`endpoint did not return waypoints ${data}`); // TODO:
84
- }
85
- case 'failed':
86
- // TODO: this is bad, do this better.
87
- return { error: data.meta.error_code };
163
+ await sleep(200);
164
+ break;
88
165
  }
89
166
  }
90
167
  }
@@ -221,28 +298,9 @@ class Direct {
221
298
  }
222
299
  return resp;
223
300
  }
224
- getPathingTaskStateStream(id, onMessage, onFail) {
225
- return new Promise((resolve, reject) => {
226
- const eventSource = new EventSource(`/api/v1.0/pathing_tasks/${id}/state`);
227
- eventSource.onmessage = (event) => {
228
- const data = JSON.parse(event.data);
229
- if (data.error === true) {
230
- onFail === null || onFail === void 0 ? void 0 : onFail();
231
- eventSource.close();
232
- reject(new Error(`Task stream returned error: ${data.payload}`));
233
- return;
234
- }
235
- if (data.payload.terminated) {
236
- eventSource.close();
237
- resolve(data.payload);
238
- }
239
- onMessage === null || onMessage === void 0 ? void 0 : onMessage(data.payload);
240
- };
241
- eventSource.onerror = (err) => {
242
- eventSource.close();
243
- onFail === null || onFail === void 0 ? void 0 : onFail();
244
- reject(err);
245
- };
301
+ getPathingTaskStateStream(id) {
302
+ return this.fetcher.STREAM(`/pathing_tasks/{pathing_task_id}/state`, {
303
+ path: { pathing_task_id: id }
246
304
  });
247
305
  }
248
306
  /// charts
@@ -727,7 +785,7 @@ function defaultPathSerializer(pathname, pathParams) {
727
785
  return nextURL;
728
786
  }
729
787
 
730
- var version = "1.3748.1";
788
+ var version = "1.3757.1";
731
789
 
732
790
  const querySerializer = createQuerySerializer();
733
791
  class Fetcher {
@@ -896,6 +954,14 @@ class Fetcher {
896
954
  async HEAD(path, data, opts) {
897
955
  return this.fetcher('post', path, data, opts);
898
956
  }
957
+ STREAM(path, data) {
958
+ const downcastedData = data;
959
+ const url = this.createFinalURL(path, {
960
+ query: downcastedData === null || downcastedData === void 0 ? void 0 : downcastedData.query,
961
+ path: downcastedData === null || downcastedData === void 0 ? void 0 : downcastedData.path
962
+ });
963
+ return new EventSource(url);
964
+ }
899
965
  }
900
966
  // indirection is required to get ts to accept the type magic
901
967
  //* * `paths` MUST be passed in as a generic type arg or type inference falls apart */