@volant-autonomy/via-sdk 1.3567.1 → 1.3595.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.
@@ -0,0 +1,905 @@
1
+ // eslint-disable-next-line promise/param-names
2
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
3
+ class UnauthenticatedError extends Error {
4
+ constructor() {
5
+ super(...arguments);
6
+ // Both properties are needed to allow for errors to be identified when used in scenarios such
7
+ // as 'PromiseRejectionEvent' such as:
8
+ // `if (errorEvent.reason.name === UnauthenticatedError.name)`
9
+ // In the above, the first is the instance property and the latter a class property
10
+ this.name = 'Unauthenticated';
11
+ // FIXME: this was valid in the via codebase for some reason.
12
+ // public static override name = 'Unauthenticated'
13
+ }
14
+ }
15
+
16
+ class Composite {
17
+ constructor(direct) {
18
+ this.direct = direct;
19
+ }
20
+ /// flightplans
21
+ async upsertFlightplan(args, id) {
22
+ if (id) {
23
+ return this.direct.modifyDraftFlightplan(id, args);
24
+ }
25
+ else {
26
+ return this.direct.createDraftFlightplan(args);
27
+ }
28
+ }
29
+ async getAllDraftFlightplans() {
30
+ return this.direct.getAllFlightplans({ 'filter[state]': ['Draft'] });
31
+ }
32
+ async getAllClosedFlightplans() {
33
+ return this.direct.getAllFlightplans({ 'filter[state]': ['Closed'] });
34
+ }
35
+ async getAllPendingFlightplans() {
36
+ return this.direct.getAllFlightplans({ 'filter[state]': ['Pending'] });
37
+ }
38
+ async getAllAcceptedFlightplans() {
39
+ return this.direct.getAllFlightplans({ 'filter[state]': ['Accepted'] });
40
+ }
41
+ // TODO: make error 409 more obvious, as it is different
42
+ async attemptAcceptFlightplan(id) {
43
+ return this.direct.changeFlightplanState(id, 'Accepted');
44
+ }
45
+ async attemptTemporalDeconfliction(id, timeInterval = 60) {
46
+ const startTimeDeconflictArgs = {
47
+ time_interval: timeInterval
48
+ };
49
+ const { data, error } = await this.direct.getFlightplanDeconflictedStartTime(id, startTimeDeconflictArgs);
50
+ if (error) {
51
+ return { error };
52
+ }
53
+ return this.direct.modifyDraftFlightplan(id, data.attributes);
54
+ }
55
+ /// pathing tasks
56
+ /** Handles creating and polling a pathing task for you */
57
+ async doPathingTask(args) {
58
+ var _a, _b;
59
+ const { error, data } = await this.direct.createPathingTask(args);
60
+ if (error) {
61
+ return { error };
62
+ }
63
+ const id = data.id;
64
+ while (true) {
65
+ const { data, error } = await this.direct.getPathingTask(id);
66
+ if (error) {
67
+ return { error };
68
+ }
69
+ switch (data.meta.state) {
70
+ case 'queued':
71
+ await sleep(500);
72
+ continue;
73
+ case 'in-progress':
74
+ await sleep(50);
75
+ continue;
76
+ case 'successful':
77
+ if ((_a = data.attributes) === null || _a === undefined ? undefined : _a.waypoints) {
78
+ return { data: (_b = data.attributes) === null || _b === undefined ? undefined : _b.waypoints };
79
+ }
80
+ else {
81
+ throw new Error(`endpoint did not return waypoints ${data}`); // TODO:
82
+ }
83
+ case 'failed':
84
+ // TODO: this is bad, do this better.
85
+ return { error: data.meta.error_code };
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ class Direct {
92
+ constructor(fetcher) {
93
+ this.fetcher = fetcher;
94
+ }
95
+ /// flightplans
96
+ async getAllFlightplans(args, opts) {
97
+ const resp = await this.fetcher.GET('/flightplans/', { query: args }, opts);
98
+ if (resp.error === undefined && !resp.aborted) {
99
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((flightplan) => flightplan.data) });
100
+ }
101
+ else {
102
+ return resp;
103
+ }
104
+ }
105
+ async createDraftFlightplan(args, opts) {
106
+ const resp = await this.fetcher.POST('/flightplans/', { body: args }, opts);
107
+ if (resp.error === undefined && !resp.aborted) {
108
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
109
+ }
110
+ return resp;
111
+ }
112
+ async modifyDraftFlightplan(id, args, opts) {
113
+ const resp = await this.fetcher.PUT('/flightplans/{flightplan_id}', { body: args, path: { flightplan_id: id } }, opts);
114
+ if (resp.error === undefined && !resp.aborted) {
115
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
116
+ }
117
+ return resp;
118
+ }
119
+ async getFlightplan(id, opts) {
120
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}', { path: { flightplan_id: id } }, opts);
121
+ if (resp.error === undefined && !resp.aborted) {
122
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
123
+ }
124
+ return resp;
125
+ }
126
+ // FIXME: this name is poor
127
+ async getFlightplanWaypointsDetailed(id, opts) {
128
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}/waypoints_detail', { path: { flightplan_id: id } }, opts);
129
+ if (resp.error === undefined && !resp.aborted) {
130
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
131
+ }
132
+ return resp;
133
+ }
134
+ async getFlightplanStatistics(id, args, opts) {
135
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}/statistics', { path: { flightplan_id: id }, query: args }, opts);
136
+ if (resp.error === undefined && !resp.aborted) {
137
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
138
+ }
139
+ return resp;
140
+ }
141
+ async getFlightplanVolumes(id, opts) {
142
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}/volumes', { path: { flightplan_id: id } }, opts);
143
+ if (resp.error === undefined && !resp.aborted) {
144
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
145
+ }
146
+ return resp;
147
+ }
148
+ // TODO: make a wrapper for this which updates the existing flightplan to have this new start time
149
+ async getFlightplanDeconflictedStartTime(id, args, opts) {
150
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}/start_time_deconflict', { path: { flightplan_id: id }, query: args }, opts);
151
+ if (resp.error === undefined && !resp.aborted) {
152
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
153
+ }
154
+ return resp;
155
+ }
156
+ async changeFlightplanState(id, state, opts) {
157
+ const resp = await this.fetcher.POST('/flightplans/{flightplan_id}/state', { path: { flightplan_id: id }, body: { state } }, opts);
158
+ if (!resp.error && resp.aborted === false) {
159
+ return Object.assign(Object.assign({}, resp), { data: true });
160
+ }
161
+ return resp;
162
+ }
163
+ // TODO: use `args` instead of fileFormat
164
+ async getFlightplanAsFile(id, opts) {
165
+ const resp = await this.fetcher.GET('/flightplans/{flightplan_id}/content', { path: { flightplan_id: id }, header: { accept: 'application/vnd.google-earth.kml+xml' } }, Object.assign(Object.assign({}, opts), { parseAs: 'blob' }));
166
+ if (resp.error === undefined && !resp.aborted) {
167
+ return Object.assign(Object.assign({}, resp), { data: { file: resp.data, fileName: resp.response.headers.get('filename') } });
168
+ }
169
+ return resp;
170
+ }
171
+ /// airspace constraints
172
+ async createAirspaceConstraint(args, opts) {
173
+ const resp = await this.fetcher.POST('/airspace_constraints/', { body: args }, opts);
174
+ if (resp.error === undefined && !resp.aborted) {
175
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
176
+ }
177
+ return resp;
178
+ }
179
+ async getAllAirspaceConstraints(opts) {
180
+ const resp = await this.fetcher.GET('/airspace_constraints/', {}, opts);
181
+ if (resp.error === undefined && !resp.aborted) {
182
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((constraint) => constraint.data) });
183
+ }
184
+ return resp;
185
+ }
186
+ async getAirspaceConstraint(id, opts) {
187
+ const resp = await this.fetcher.GET('/airspace_constraints/{airspace_constraint_id}', { path: { airspace_constraint_id: id } }, opts);
188
+ if (resp.error === undefined && !resp.aborted) {
189
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
190
+ }
191
+ return resp;
192
+ }
193
+ async modifyAirspaceConstraint(id, args, opts) {
194
+ const resp = await this.fetcher.PUT('/airspace_constraints/{airspace_constraint_id}', { path: { airspace_constraint_id: id }, body: args }, opts);
195
+ if (resp.error === undefined && !resp.aborted) {
196
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
197
+ }
198
+ return resp;
199
+ }
200
+ async changeAirspaceConstraintState(id, state, opts) {
201
+ const resp = await this.fetcher.POST('/airspace_constraints/{airspace_constraints_id}/state', { path: { airspace_constraints_id: id }, body: { state } }, opts);
202
+ if (!resp.error && resp.aborted === false) {
203
+ return Object.assign(Object.assign({}, resp), { data: true });
204
+ }
205
+ return resp;
206
+ }
207
+ /// pathing tasks
208
+ async createPathingTask(args, opts) {
209
+ const resp = await this.fetcher.POST('/pathing_tasks/', { body: args }, opts);
210
+ if (resp.error === undefined && !resp.aborted) {
211
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
212
+ }
213
+ return resp;
214
+ }
215
+ async getPathingTask(id, opts) {
216
+ const resp = await this.fetcher.GET('/pathing_tasks/{pathing_task_id}', { path: { pathing_task_id: id } }, opts);
217
+ if (resp.error === undefined && !resp.aborted) {
218
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
219
+ }
220
+ return resp;
221
+ }
222
+ /// charts
223
+ async getAllCharts(opts) {
224
+ const resp = await this.fetcher.GET('/charts/', {}, opts);
225
+ if (resp.error === undefined && !resp.aborted) {
226
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((chart) => chart.data) });
227
+ }
228
+ return resp;
229
+ }
230
+ async getChart(id, opts) {
231
+ const resp = await this.fetcher.GET('/charts/{chart_id}', { path: { chart_id: id } }, opts);
232
+ if (resp.error === undefined && !resp.aborted) {
233
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
234
+ }
235
+ return resp;
236
+ }
237
+ /// risk assessment
238
+ async getSailV2_5(args, opts) {
239
+ const resp = await this.fetcher.GET('/risk_assessment/sora/v2.5/sail', { query: args }, opts);
240
+ if (resp.error === undefined && !resp.aborted) {
241
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
242
+ }
243
+ return resp;
244
+ }
245
+ async calculateResidualArcV2_5(args, opts) {
246
+ const resp = await this.fetcher.POST('/risk_assessment/sora/v2.5/residual_arc', { body: args }, opts);
247
+ if (resp.error === undefined && !resp.aborted) {
248
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
249
+ }
250
+ return resp;
251
+ }
252
+ async getAllArcsV2_5(opts) {
253
+ const resp = await this.fetcher.GET('/risk_assessment/sora/v2.5/air_risk_classifications', {}, opts);
254
+ if (resp.error === undefined && !resp.aborted) {
255
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((arc) => arc.data) });
256
+ }
257
+ return resp;
258
+ }
259
+ async getArcV2_5(args, opts) {
260
+ const resp = await this.fetcher.GET('/risk_assessment/sora/v2.5/air_risk_classifications/{arc_id}', { path: args }, opts);
261
+ if (resp.error === undefined && !resp.aborted) {
262
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
263
+ }
264
+ return resp;
265
+ }
266
+ async generateSoraReportV2_5(args, opts) {
267
+ const resp = await this.fetcher.POST('/risk_assessment/sora/v2.5/report', { body: args }, opts);
268
+ if (resp.error === undefined && !resp.aborted) {
269
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
270
+ }
271
+ return resp;
272
+ }
273
+ async generateSoraSemanticModelVolumesV2_5(args, opts) {
274
+ const resp = await this.fetcher.POST('/risk_assessment/sora/v2.5/semantic_model_volumes', { body: args }, opts);
275
+ if (resp.error === undefined && !resp.aborted) {
276
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
277
+ }
278
+ return resp;
279
+ }
280
+ async getAllArcsUk(opts) {
281
+ const resp = await this.fetcher.GET('/risk_assessment/sora/uk/air_risk_classifications', {}, opts);
282
+ if (resp.error === undefined && !resp.aborted) {
283
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((arc) => arc.data) });
284
+ }
285
+ return resp;
286
+ }
287
+ async getArcUk(args, opts) {
288
+ const resp = await this.fetcher.GET('/risk_assessment/sora/uk/air_risk_classifications/{arc_id}', { path: args }, opts);
289
+ if (resp.error === undefined && !resp.aborted) {
290
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
291
+ }
292
+ return resp;
293
+ }
294
+ async getSailUk(args, opts) {
295
+ const resp = await this.fetcher.GET('/risk_assessment/sora/uk/sail', { query: args }, opts);
296
+ if (resp.error === undefined && !resp.aborted) {
297
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
298
+ }
299
+ return resp;
300
+ }
301
+ async calculateResidualArcUk(args, opts) {
302
+ const resp = await this.fetcher.POST('/risk_assessment/sora/uk/residual_arc', { body: args }, opts);
303
+ if (resp.error === undefined && !resp.aborted) {
304
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
305
+ }
306
+ return resp;
307
+ }
308
+ async generateSoraReportUk(args, opts) {
309
+ const resp = await this.fetcher.POST('/risk_assessment/sora/uk/report', { body: args }, opts);
310
+ if (resp.error === undefined && !resp.aborted) {
311
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
312
+ }
313
+ return resp;
314
+ }
315
+ async generateSoraSemanticModelVolumesUk(args, opts) {
316
+ const resp = await this.fetcher.POST('/risk_assessment/sora/uk/semantic_model_volumes', { body: args }, opts);
317
+ if (resp.error === undefined && !resp.aborted) {
318
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
319
+ }
320
+ return resp;
321
+ }
322
+ async createSoraClassification(args, opts) {
323
+ const resp = await this.fetcher.POST('/risk_assessment/sora/classifications', { body: args }, opts);
324
+ if (resp.error === undefined && !resp.aborted) {
325
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
326
+ }
327
+ return resp;
328
+ }
329
+ async updateSoraClassification(id, args, opts) {
330
+ const resp = await this.fetcher.PUT('/risk_assessment/sora/classifications/{classification_id}', { body: args, path: { classification_id: id } }, opts);
331
+ if (resp.error === undefined && !resp.aborted) {
332
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
333
+ }
334
+ return resp;
335
+ }
336
+ async getSoraClassification(id, opts) {
337
+ const resp = await this.fetcher.GET('/risk_assessment/sora/classifications/{classification_id}', { path: { classification_id: id } }, opts);
338
+ if (resp.error === undefined && !resp.aborted) {
339
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
340
+ }
341
+ return resp;
342
+ }
343
+ /// controlled ground areas
344
+ async getAllControlledGroundAreas(args, opts) {
345
+ const resp = await this.fetcher.GET('/risk_assessment/sora/controlled_ground_areas/', { query: args }, opts);
346
+ if (resp.error === undefined && !resp.aborted) {
347
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((controlledGroundArea) => controlledGroundArea.data) });
348
+ }
349
+ else {
350
+ return resp;
351
+ }
352
+ }
353
+ async createControlledGroundArea(args, opts) {
354
+ const resp = await this.fetcher.POST('/risk_assessment/sora/controlled_ground_areas/', { body: args }, opts);
355
+ if (resp.error === undefined && !resp.aborted) {
356
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
357
+ }
358
+ return resp;
359
+ }
360
+ async getControlledGroundArea(args, opts) {
361
+ const resp = await this.fetcher.GET('/risk_assessment/sora/controlled_ground_areas/{controlled_ground_area_id}', { path: args }, opts);
362
+ if (resp.error === undefined && !resp.aborted) {
363
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
364
+ }
365
+ return resp;
366
+ }
367
+ async updateControlledGroundArea(id, args, opts) {
368
+ const resp = await this.fetcher.PUT('/risk_assessment/sora/controlled_ground_areas/{controlled_ground_area_id}', { body: args, path: { controlled_ground_area_id: id } }, opts);
369
+ if (resp.error === undefined && !resp.aborted) {
370
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
371
+ }
372
+ return resp;
373
+ }
374
+ async deleteControlledGroundArea(args, opts) {
375
+ const resp = await this.fetcher.DELETE('/risk_assessment/sora/controlled_ground_areas/{controlled_ground_area_id}', { path: args }, opts);
376
+ if (resp.error === undefined && !resp.aborted) {
377
+ return Object.assign(Object.assign({}, resp), { data: true });
378
+ }
379
+ return resp;
380
+ }
381
+ /// atypical airspaces
382
+ async getAllAtypicalAirspaces(args, opts) {
383
+ const resp = await this.fetcher.GET('/risk_assessment/sora/atypical_airspaces/', { query: args }, opts);
384
+ if (resp.error === undefined && !resp.aborted) {
385
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data.map((atypicalAirspace) => atypicalAirspace.data) });
386
+ }
387
+ else {
388
+ return resp;
389
+ }
390
+ }
391
+ async createAtypicalAirspace(args, opts) {
392
+ const resp = await this.fetcher.POST('/risk_assessment/sora/atypical_airspaces/', { body: args }, opts);
393
+ if (resp.error === undefined && !resp.aborted) {
394
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
395
+ }
396
+ return resp;
397
+ }
398
+ async getAtypicalAirspace(args, opts) {
399
+ const resp = await this.fetcher.GET('/risk_assessment/sora/atypical_airspaces/{atypical_airspace_id}', { path: args }, opts);
400
+ if (resp.error === undefined && !resp.aborted) {
401
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
402
+ }
403
+ return resp;
404
+ }
405
+ async updateAtypicalAirspace(id, args, opts) {
406
+ const resp = await this.fetcher.PUT('/risk_assessment/sora/atypical_airspaces/{atypical_airspace_id}', { body: args, path: { atypical_airspace_id: id } }, opts);
407
+ if (resp.error === undefined && !resp.aborted) {
408
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
409
+ }
410
+ return resp;
411
+ }
412
+ async deleteAtypicalAirspace(args, opts) {
413
+ const resp = await this.fetcher.DELETE('/risk_assessment/sora/atypical_airspaces/{atypical_airspace_id}', { path: args }, opts);
414
+ if (resp.error === undefined && !resp.aborted) {
415
+ return Object.assign(Object.assign({}, resp), { data: true });
416
+ }
417
+ return resp;
418
+ }
419
+ /// geocages
420
+ async createGeocage(args, opts) {
421
+ const resp = await this.fetcher.POST('/geocages/', { body: args }, opts);
422
+ if (resp.error === undefined && !resp.aborted) {
423
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
424
+ }
425
+ return resp;
426
+ }
427
+ async getGeocage(args, opts) {
428
+ const resp = await this.fetcher.GET('/geocages/{geocage_id}', { path: args }, opts);
429
+ if (resp.error === undefined && !resp.aborted) {
430
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
431
+ }
432
+ return resp;
433
+ }
434
+ async getAllGeocages(args, opts) {
435
+ const resp = await this.fetcher.GET('/geocages/', { query: args }, opts);
436
+ if (resp.error === undefined && !resp.aborted) {
437
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
438
+ }
439
+ else {
440
+ return resp;
441
+ }
442
+ }
443
+ async updateGeocage(id, args, opts) {
444
+ const resp = await this.fetcher.PUT('/geocages/{geocage_id}', { body: args, path: { geocage_id: id } }, opts);
445
+ if (resp.error === undefined && !resp.aborted) {
446
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
447
+ }
448
+ return resp;
449
+ }
450
+ async deleteGeocage(args, opts) {
451
+ const resp = await this.fetcher.DELETE('/geocages/{geocage_id}', { path: args }, opts);
452
+ if (resp.error === undefined && !resp.aborted) {
453
+ return Object.assign(Object.assign({}, resp), { data: true });
454
+ }
455
+ return resp;
456
+ }
457
+ /// flight patterns
458
+ async createRasterPattern(args, opts) {
459
+ const resp = await this.fetcher.POST('/flight_patterns/raster', { body: args }, opts);
460
+ if (resp.error === undefined && !resp.aborted) {
461
+ return Object.assign(Object.assign({}, resp), { data: resp.data.data });
462
+ }
463
+ return resp;
464
+ }
465
+ }
466
+
467
+ // settings & const
468
+
469
+ const PATH_PARAM_RE = /\{[^{}]+\}/g;
470
+
471
+ // utils
472
+
473
+ /**
474
+ * Serialize primitive param values
475
+ * @type {import("./index.js").serializePrimitiveParam}
476
+ */
477
+ function serializePrimitiveParam(name, value, options) {
478
+ if (value === undefined || value === null) {
479
+ return "";
480
+ }
481
+ if (typeof value === "object") {
482
+ throw new Error(
483
+ "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.",
484
+ );
485
+ }
486
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
487
+ }
488
+
489
+ /**
490
+ * Serialize object param (shallow only)
491
+ * @type {import("./index.js").serializeObjectParam}
492
+ */
493
+ function serializeObjectParam(name, value, options) {
494
+ if (!value || typeof value !== "object") {
495
+ return "";
496
+ }
497
+ const values = [];
498
+ const joiner =
499
+ {
500
+ simple: ",",
501
+ label: ".",
502
+ matrix: ";",
503
+ }[options.style] || "&";
504
+
505
+ // explode: false
506
+ if (options.style !== "deepObject" && options.explode === false) {
507
+ for (const k in value) {
508
+ values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
509
+ }
510
+ const final = values.join(","); // note: values are always joined by comma in explode: false (but joiner can prefix)
511
+ switch (options.style) {
512
+ case "form": {
513
+ return `${name}=${final}`;
514
+ }
515
+ case "label": {
516
+ return `.${final}`;
517
+ }
518
+ case "matrix": {
519
+ return `;${name}=${final}`;
520
+ }
521
+ default: {
522
+ return final;
523
+ }
524
+ }
525
+ }
526
+
527
+ // explode: true
528
+ for (const k in value) {
529
+ const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
530
+ values.push(serializePrimitiveParam(finalName, value[k], options));
531
+ }
532
+ const final = values.join(joiner);
533
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
534
+ }
535
+
536
+ /**
537
+ * Serialize array param (shallow only)
538
+ * @type {import("./index.js").serializeArrayParam}
539
+ */
540
+ function serializeArrayParam(name, value, options) {
541
+ if (!Array.isArray(value)) {
542
+ return "";
543
+ }
544
+
545
+ // explode: false
546
+ if (options.explode === false) {
547
+ const joiner = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ","; // note: for arrays, joiners vary wildly based on style + explode behavior
548
+ const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner);
549
+ switch (options.style) {
550
+ case "simple": {
551
+ return final;
552
+ }
553
+ case "label": {
554
+ return `.${final}`;
555
+ }
556
+ case "matrix": {
557
+ return `;${name}=${final}`;
558
+ }
559
+ // case "spaceDelimited":
560
+ // case "pipeDelimited":
561
+ default: {
562
+ return `${name}=${final}`;
563
+ }
564
+ }
565
+ }
566
+
567
+ // explode: true
568
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
569
+ const values = [];
570
+ for (const v of value) {
571
+ if (options.style === "simple" || options.style === "label") {
572
+ values.push(options.allowReserved === true ? v : encodeURIComponent(v));
573
+ } else {
574
+ values.push(serializePrimitiveParam(name, v, options));
575
+ }
576
+ }
577
+ return options.style === "label" || options.style === "matrix"
578
+ ? `${joiner}${values.join(joiner)}`
579
+ : values.join(joiner);
580
+ }
581
+
582
+ /**
583
+ * Serialize query params to string
584
+ * @type {import("./index.js").createQuerySerializer}
585
+ */
586
+ function createQuerySerializer(options) {
587
+ return function querySerializer(queryParams) {
588
+ const search = [];
589
+ if (queryParams && typeof queryParams === "object") {
590
+ for (const name in queryParams) {
591
+ const value = queryParams[name];
592
+ if (value === undefined || value === null) {
593
+ continue;
594
+ }
595
+ if (Array.isArray(value)) {
596
+ search.push(
597
+ serializeArrayParam(name, value, {
598
+ style: "form",
599
+ explode: true,
600
+ ...options?.array,
601
+ allowReserved: false,
602
+ }),
603
+ );
604
+ continue;
605
+ }
606
+ if (typeof value === "object") {
607
+ search.push(
608
+ serializeObjectParam(name, value, {
609
+ style: "deepObject",
610
+ explode: true,
611
+ ...options?.object,
612
+ allowReserved: false,
613
+ }),
614
+ );
615
+ continue;
616
+ }
617
+ search.push(serializePrimitiveParam(name, value, options));
618
+ }
619
+ }
620
+ return search.join("&");
621
+ };
622
+ }
623
+
624
+ /**
625
+ * Handle different OpenAPI 3.x serialization styles
626
+ * @type {import("./index.js").defaultPathSerializer}
627
+ * @see https://swagger.io/docs/specification/serialization/#path
628
+ */
629
+ function defaultPathSerializer(pathname, pathParams) {
630
+ let nextURL = pathname;
631
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
632
+ let name = match.substring(1, match.length - 1);
633
+ let explode = false;
634
+ let style = "simple";
635
+ if (name.endsWith("*")) {
636
+ explode = true;
637
+ name = name.substring(0, name.length - 1);
638
+ }
639
+ if (name.startsWith(".")) {
640
+ style = "label";
641
+ name = name.substring(1);
642
+ } else if (name.startsWith(";")) {
643
+ style = "matrix";
644
+ name = name.substring(1);
645
+ }
646
+ if (!pathParams || pathParams[name] === undefined || pathParams[name] === null) {
647
+ continue;
648
+ }
649
+ const value = pathParams[name];
650
+ if (Array.isArray(value)) {
651
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
652
+ continue;
653
+ }
654
+ if (typeof value === "object") {
655
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
656
+ continue;
657
+ }
658
+ if (style === "matrix") {
659
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
660
+ continue;
661
+ }
662
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
663
+ }
664
+ return nextURL;
665
+ }
666
+
667
+ var version = "1.3595.1";
668
+
669
+ const querySerializer = createQuerySerializer();
670
+ class Fetcher {
671
+ constructor(args) {
672
+ var _a, _b, _c, _d;
673
+ this.opts = {
674
+ url: (_a = args.url) !== null && _a !== undefined ? _a : 'https://via.volantautonomy.com/api/v1.0',
675
+ fetchFn: (_b = args.fetchFn) !== null && _b !== undefined ? _b : undefined,
676
+ authFetchFn: (_c = args.authFetchFn) !== null && _c !== undefined ? _c : undefined,
677
+ username: args.username,
678
+ password: args.password,
679
+ ignoreAuth: (_d = args.ignoreAuth) !== null && _d !== undefined ? _d : false
680
+ };
681
+ this.aborts = {};
682
+ this.accessToken = undefined;
683
+ this.expiry = Date.now() - 5;
684
+ }
685
+ async doAuth() {
686
+ var _a;
687
+ // NOTE: THIS REQUEST IS NOT TYPE CHECKED PROPERLY AS paths IS NOT KNOWN HERE!
688
+ if (this.opts.username === undefined || this.opts.password === undefined) {
689
+ throw new UnauthenticatedError('ignoreAuth is not true and either username or password is missing');
690
+ }
691
+ const authFetchFn = (_a = this.opts.authFetchFn) !== null && _a !== undefined ? _a : globalThis.fetch;
692
+ const resp = await authFetchFn(this.opts.url + '/login', {
693
+ body: JSON.stringify({
694
+ username: this.opts.username,
695
+ password: this.opts.password
696
+ }),
697
+ redirect: 'follow',
698
+ method: 'post',
699
+ headers: { 'Content-Type': 'application/json', 'X-Via-Sdk-Version': version }
700
+ });
701
+ if (resp.ok) {
702
+ const data = (await resp.json());
703
+ this.expiry = Date.now() + data.expires_in - 10;
704
+ this.accessToken = data.access_token;
705
+ }
706
+ else {
707
+ throw new UnauthenticatedError('Invalid credentials');
708
+ }
709
+ }
710
+ /** Takes in an abort key to determine what abort signals should be fired and a new signal */
711
+ handleAbortKey(abortKey) {
712
+ var _a;
713
+ if (abortKey) {
714
+ (_a = this.aborts[abortKey]) === null || _a === undefined ? undefined : _a.abort();
715
+ const abortController = new AbortController();
716
+ this.aborts[abortKey] = abortController;
717
+ return abortController.signal;
718
+ }
719
+ return undefined;
720
+ }
721
+ /** Transforms an error from the api into an {@link SdkErrorModel} */
722
+ async parseError(response) {
723
+ var _a;
724
+ const error = (await response.json());
725
+ // NOTE: throws away the status codes inside of the individual errors
726
+ if (((_a = error === null || error === undefined ? undefined : error.errors) === null || _a === undefined ? undefined : _a.length) === 0) {
727
+ return {
728
+ status: String(response.status),
729
+ errors: [
730
+ {
731
+ status: String(response.status),
732
+ detail: ''
733
+ }
734
+ ]
735
+ };
736
+ }
737
+ else {
738
+ return {
739
+ status: String(response.status),
740
+ errors: error === null || error === undefined ? undefined : error.errors.map((err) => {
741
+ return {
742
+ status: String(err.status),
743
+ detail: err.detail
744
+ };
745
+ })
746
+ };
747
+ }
748
+ }
749
+ // source: https://github.com/openapi-ts/openapi-typescript/blob/f21c05b9afcc89ee6ef73edab4045620b410eb01/packages/openapi-fetch/src/index.js#L447
750
+ createFinalURL(path, options) {
751
+ var _a;
752
+ let finalURL = `${this.opts.url}${path}`;
753
+ if (options === null || options === undefined ? undefined : options.path) {
754
+ finalURL = defaultPathSerializer(finalURL, options.path);
755
+ }
756
+ const search = querySerializer((_a = options.query) !== null && _a !== undefined ? _a : {});
757
+ if (search) {
758
+ finalURL += `?${search}`;
759
+ }
760
+ return finalURL;
761
+ }
762
+ /** The actual fetch wrapper. It is type inference blind, beyond the parseAs type */
763
+ async fetcher(method, path, data, opts) {
764
+ var _a, _b, _c;
765
+ if (!this.opts.ignoreAuth) {
766
+ if (!this.accessToken || this.expiry <= Date.now()) {
767
+ await this.doAuth();
768
+ }
769
+ }
770
+ const fetchFn = (_b = (_a = opts === null || opts === undefined ? undefined : opts.fetch) !== null && _a !== undefined ? _a : this.opts.fetchFn) !== null && _b !== undefined ? _b : globalThis.fetch;
771
+ const parseAs = (_c = opts === null || opts === undefined ? undefined : opts.parseAs) !== null && _c !== undefined ? _c : 'json';
772
+ const request = new Request(this.createFinalURL(path, { query: data === null || data === undefined ? undefined : data.query, path: data === null || data === undefined ? undefined : data.path }), {
773
+ redirect: 'follow',
774
+ signal: this.handleAbortKey(opts === null || opts === undefined ? undefined : opts.abortKey),
775
+ body: JSON.stringify(data === null || data === undefined ? undefined : data.body),
776
+ headers: Object.assign({ 'Content-Type': 'application/json', 'X-Via-Sdk-Version': version }, data === null || data === undefined ? undefined : data.header),
777
+ method
778
+ });
779
+ if (!this.opts.ignoreAuth) {
780
+ request.headers.set('Authorization', `Bearer ${this.accessToken}`);
781
+ }
782
+ let response;
783
+ try {
784
+ response = await fetchFn(request);
785
+ }
786
+ catch (err) {
787
+ if (err.name === 'AbortError') {
788
+ return { aborted: true };
789
+ }
790
+ throw err;
791
+ }
792
+ if (response.status === 401) {
793
+ throw new UnauthenticatedError('Unauthenticated');
794
+ }
795
+ // handle empty content
796
+ // note: we return `{}` because we want user truthy checks for `.data` or `.error` to succeed
797
+ // NOTE: this does lie to the user, as we say it is undefined
798
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') {
799
+ return response.ok
800
+ ? { data: {}, aborted: false, response }
801
+ : { error: {}, aborted: false, response };
802
+ }
803
+ if (response.ok) {
804
+ // if "stream", skip parsing entirely
805
+ if (parseAs === 'stream') {
806
+ return { data: response.body, aborted: false, response };
807
+ }
808
+ return { data: await response[parseAs](), aborted: false, response };
809
+ }
810
+ return { error: await this.parseError(response), aborted: false };
811
+ }
812
+ async GET(path, data, opts) {
813
+ return this.fetcher('get', path, data, opts);
814
+ }
815
+ async PUT(path, data, opts) {
816
+ return this.fetcher('put', path, data, opts);
817
+ }
818
+ async POST(path, data, opts) {
819
+ return this.fetcher('post', path, data, opts);
820
+ }
821
+ async DELETE(path, data, opts) {
822
+ return this.fetcher('delete', path, data, opts);
823
+ }
824
+ async OPTIONS(path, data, opts) {
825
+ return this.fetcher('options', path, data, opts);
826
+ }
827
+ async HEAD(path, data, opts) {
828
+ return this.fetcher('post', path, data, opts);
829
+ }
830
+ }
831
+ // indirection is required to get ts to accept the type magic
832
+ //* * `paths` MUST be passed in as a generic type arg or type inference falls apart */
833
+ function createFetcher(...args) {
834
+ return new Fetcher(...args);
835
+ }
836
+
837
+ function createSDK(opts) {
838
+ if (!opts.ignoreAuth && (opts.username === undefined || opts.password === undefined)) {
839
+ throw new UnauthenticatedError('ignoreAuth is not true and either username or password is missing');
840
+ }
841
+ const fetcher = createFetcher(opts);
842
+ const newDirect = new Direct(fetcher);
843
+ return {
844
+ direct: newDirect,
845
+ composite: new Composite(newDirect)
846
+ };
847
+ }
848
+
849
+ /** Takes in an array of coordinates and flight options, and returns an array of checkpoints for use in the other functions */
850
+ function generateCheckpointsFromCoordinates(args) {
851
+ const { coordinates, options } = args;
852
+ if (coordinates.length <= 2) {
853
+ throw Error('Must have at least two coordinates');
854
+ }
855
+ const waypoints = [
856
+ {
857
+ type: 'start',
858
+ position: coordinates[0] // first coord exists because of length check above
859
+ }
860
+ ];
861
+ for (const position of coordinates.slice(1)) {
862
+ waypoints.push({
863
+ type: 'goto',
864
+ position,
865
+ parameters: options
866
+ });
867
+ }
868
+ return waypoints;
869
+ }
870
+ /** Takes in an array of coordinates and flight options, and returns an array of waypoints for use in the other functions */
871
+ function generateWaypointsFromCoordinates(args) {
872
+ const { coordinates, options } = args;
873
+ if (coordinates.length <= 2) {
874
+ throw Error('Must have at least two coordinates');
875
+ }
876
+ const waypoints = [
877
+ {
878
+ type: 'start',
879
+ position: coordinates[0] // first coord exists because of length check above
880
+ }
881
+ ];
882
+ for (const position of coordinates.slice(1)) {
883
+ if (options.wind_parameters)
884
+ waypoints.push({
885
+ type: 'goto',
886
+ position,
887
+ flight_parameters: options.flight_parameters,
888
+ wind_parameters: options.wind_parameters
889
+ });
890
+ else
891
+ waypoints.push({
892
+ type: 'goto',
893
+ position,
894
+ flight_parameters: options.flight_parameters
895
+ });
896
+ }
897
+ return waypoints;
898
+ }
899
+ /** Converts from seconds since epoch to a RFC3339-formatted datetime string */
900
+ function rfcDateTime(secondsEpoch) {
901
+ return new Date(secondsEpoch * 1000).toISOString().slice(0, 16) + 'Z';
902
+ }
903
+
904
+ export { createSDK, generateCheckpointsFromCoordinates, generateWaypointsFromCoordinates, rfcDateTime };
905
+ //# sourceMappingURL=index.esm.js.map