Spaces:
Sleeping
Sleeping
File size: 3,296 Bytes
98fbc6d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | import { z } from 'zod';
/**
* AirTrail integration contracts (#214).
*
* AirTrail is a self-hosted flight tracker (github.com/johanohly/AirTrail).
* The connection is per-user (Settings β Integrations); the global on/off is the
* `airtrail` addon. Each user stores their instance URL + a personal Bearer API
* key, which only ever exposes that user's own flights.
*/
// ββ Per-user connection ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
/** Placeholder the server returns instead of the real key once one is stored. */
export const AIRTRAIL_KEY_MASK = 'β’β’β’β’β’β’β’β’';
export const airtrailSettingsSchema = z.object({
/** Instance origin, e.g. https://flights.example.com β TREK appends /api itself. */
url: z.string().trim().max(2048),
/** Bearer API key. Omitted / blank / the mask keeps the stored key unchanged. */
apiKey: z.string().max(512).optional(),
/** Allow self-signed TLS certs (common on LAN instances). */
allowInsecureTls: z.boolean().optional().default(false),
});
export type AirtrailSettings = z.infer<typeof airtrailSettingsSchema>;
export const airtrailConnectionSchema = z.object({
url: z.string(),
apiKeyMasked: z.string(),
allowInsecureTls: z.boolean(),
connected: z.boolean(),
});
export type AirtrailConnection = z.infer<typeof airtrailConnectionSchema>;
export const airtrailStatusSchema = z.object({
connected: z.boolean(),
flightCount: z.number().optional(),
error: z.string().optional(),
});
export type AirtrailStatus = z.infer<typeof airtrailStatusSchema>;
// ββ Flight list (picker) βββββββββββββββββββββββββββββββββββββββββββββββββββββ
/** A normalized AirTrail flight as surfaced to the import picker. */
export const airtrailFlightSchema = z.object({
id: z.string(),
fromCode: z.string().nullable(),
fromName: z.string().nullable(),
toCode: z.string().nullable(),
toName: z.string().nullable(),
date: z.string().nullable(),
departure: z.string().nullable(),
arrival: z.string().nullable(),
airline: z.string().nullable(),
flightNumber: z.string().nullable(),
aircraft: z.string().nullable(),
seatClass: z.string().nullable(),
});
export type AirtrailFlight = z.infer<typeof airtrailFlightSchema>;
// ββ Import βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
export const airtrailImportSchema = z.object({
flightIds: z.array(z.string()).min(1, 'Select at least one flight'),
});
export type AirtrailImport = z.infer<typeof airtrailImportSchema>;
/** Per-flight outcome of an import (so the picker can show what was skipped). */
export const airtrailImportResultSchema = z.object({
imported: z.array(z.string()),
skipped: z.array(
z.object({
flightId: z.string(),
reason: z.enum(['already-imported', 'already-in-trip', 'invalid']),
detail: z.string().optional(),
}),
),
});
export type AirtrailImportResult = z.infer<typeof airtrailImportResultSchema>;
|