@updraft-solutions/mcrit-sdk 0.4.0 → 0.6.0

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.
Files changed (47) hide show
  1. package/dist/chunk-EE4YY3AU.js +2620 -0
  2. package/dist/chunk-H4CJ2YEQ.cjs +2620 -0
  3. package/dist/courses/index.d.cts +2 -2
  4. package/dist/courses/index.d.ts +2 -2
  5. package/dist/index.cjs +201 -5
  6. package/dist/index.d.cts +3 -3
  7. package/dist/index.d.ts +3 -3
  8. package/dist/index.js +207 -11
  9. package/dist/schemas/index.cjs +198 -2
  10. package/dist/schemas/index.d.cts +3157 -128
  11. package/dist/schemas/index.d.ts +3157 -128
  12. package/dist/schemas/index.js +201 -5
  13. package/dist/training-C9rIBUeV.d.cts +101685 -0
  14. package/dist/training-C9rIBUeV.d.ts +101685 -0
  15. package/dist/types/index.cjs +1 -1
  16. package/dist/types/index.d.cts +278 -6
  17. package/dist/types/index.d.ts +278 -6
  18. package/dist/types/index.js +1 -1
  19. package/package.json +1 -1
  20. package/src/courses/index.ts +2 -2
  21. package/src/index.ts +42 -0
  22. package/src/schemas/common.ts +69 -5
  23. package/src/schemas/course-milestone.ts +78 -0
  24. package/src/schemas/equipment.ts +27 -0
  25. package/src/schemas/form-template.ts +416 -0
  26. package/src/schemas/index.ts +7 -1
  27. package/src/schemas/location-map.ts +175 -0
  28. package/src/schemas/models.ts +201 -100
  29. package/src/schemas/newsletter.ts +362 -0
  30. package/src/schemas/todo.ts +46 -0
  31. package/src/schemas/training.ts +500 -0
  32. package/src/types/ai.ts +85 -0
  33. package/src/types/aircraft-block.ts +23 -0
  34. package/src/types/api.ts +3 -1
  35. package/src/types/background-task.ts +28 -0
  36. package/src/types/compliance.ts +27 -3
  37. package/src/types/index.ts +5 -0
  38. package/src/types/landing-fee.ts +92 -0
  39. package/src/types/models.ts +46 -3
  40. package/src/types/roles.ts +26 -0
  41. package/dist/chunk-RC2BBT6H.cjs +0 -1384
  42. package/dist/chunk-WQLDSZNN.js +0 -1384
  43. package/dist/models-Bc5BKYuI.d.cts +0 -36898
  44. package/dist/models-Bc5BKYuI.d.ts +0 -36898
  45. package/src/schemas/fee.ts +0 -37
  46. /package/dist/{chunk-LXNCAKJZ.js → chunk-2WJHTRIE.js} +0 -0
  47. /package/dist/{chunk-MOOGM3DW.cjs → chunk-DCEOET63.cjs} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { a as addressSchema, b as aircraftRatingSchema, g as airplaneSchema, f as airplanePermissionSchema, h as airplaneShareInviteSchema, i as airportSchema, j as alertSchema, k as allowedDocumentTypeSchema, l as approachTypeSchema, m as availSchema, n as baseMembershipSchema, o as bookingSchema, q as commentSchema, r as companySchema, x as courseSchema, v as courseEnrollmentSchema, w as courseFeeSchema, D as documentSchema, y as documentComplianceStatus, z as documentRequirement, A as documentRequirementGroup, C as documentRequirementGroupAssignment, E as documentShareSchema, F as documentType, G as eventSchema, I as expenseSchema, H as expenseItemSchema, J as extendedAirplaneSchema, L as flightLogSchema, M as invoiceSchema, O as landingSchema, N as landingFeeSchema, Q as maintenanceEventSchema, P as maintenanceEventEstimationSchema, R as maintenanceStatusSchema, S as mediaCollection, U as membershipSchema, V as postSchema, W as prePaidPackageSchema, X as priceSchema, Y as qualificationSchema, Z as recurringFlightSchema, _ as roleSchema, $ as runwaySchema, a0 as scheduledFlightSchema, a1 as settingSchema, a2 as specialFlightSchema, a4 as ticketSchema, a7 as userSchema, a5 as userAircraftRatingSchema, a6 as userQualificationSchema, a8 as waypointSchema, c as airplaneIssueSchema, d as airplaneIssueSeverityEnum, e as airplaneIssueStatusEnum, B as BaseModel$1, t as courseCheckSyllabusSchema, u as courseEnrollmentMetricsSchema, K as feeSchema, T as mediaSchema, a3 as tagSchema } from '../models-Bc5BKYuI.js';
2
+ import { aA as activitySchema, aB as addressSchema, aC as aircraftPositionSchema, aD as aircraftRatingSchema, aI as airplaneSchema, aH as airplanePermissionSchema, aJ as airplaneShareInviteSchema, aK as airportSchema, aL as alertSchema, aM as allowedDocumentTypeSchema, aN as approachTypeSchema, aO as availSchema, aP as baseMembershipSchema, aQ as bookingSchema, aS as commentSchema, aT as companySchema, aZ as courseSchema, aX as courseEnrollmentSchema, aY as courseFeeSchema, aF as airplaneIssueSeverityEnum, b3 as documentSchema, a$ as documentComplianceStatus, b0 as documentRequirement, b1 as documentRequirementGroup, b2 as documentRequirementGroupAssignment, b4 as documentShareSchema, b5 as documentType, b7 as eventSchema, b9 as expenseSchema, b8 as expenseItemSchema, ba as extendedAirplaneSchema, bc as feeSchema, bb as feeCategoryOptionsSchema, bd as flightLogSchema, bj as invoiceSchema, bl as landingSchema, bk as landingFeeSchema, bn as maintenanceEventSchema, bm as maintenanceEventEstimationSchema, bo as maintenanceStatusSchema, bp as mediaCollection, br as membershipSchema, bs as membershipSignupSchema, bt as postSchema, bu as prePaidPackageSchema, bv as priceSchema, bw as qualificationSchema, bx as recurringFlightSchema, by as roleSchema, bz as runwaySchema, bA as scheduledFlightSchema, bB as settingSchema, bC as specialFlightSchema, bJ as tagSchema, bK as ticketSchema, bU as userSchema, bS as userAircraftRatingSchema, bT as userQualificationSchema, bV as waypointSchema, aE as airplaneIssueSchema, aG as airplaneIssueStatusEnum, B as BaseModel$1, aV as courseCheckSyllabusSchema, aW as courseEnrollmentMetricsSchema, bq as mediaSchema, l as FormSubmission } from '../training-C9rIBUeV.js';
3
3
 
4
4
  type BaseModel = z.infer<typeof BaseModel$1>;
5
5
  type User = z.infer<typeof userSchema>;
@@ -20,12 +20,16 @@ type Airport = z.infer<typeof airportSchema>;
20
20
  type RecurringFlight = z.infer<typeof recurringFlightSchema>;
21
21
  type Fee = z.infer<typeof feeSchema>;
22
22
  type CourseFee = z.infer<typeof courseFeeSchema>;
23
+ type FeeCategoryOptions = z.infer<typeof feeCategoryOptionsSchema>;
23
24
  type Tag = z.infer<typeof tagSchema>;
24
25
  type CourseCheckSyllabus = z.infer<typeof courseCheckSyllabusSchema>;
25
26
  type Price = z.infer<typeof priceSchema>;
26
27
  type MaintenanceEvent = z.infer<typeof maintenanceEventSchema>;
27
28
  type MaintenanceStatus = z.infer<typeof maintenanceStatusSchema>;
28
29
  type MaintenanceEventEstimation = z.infer<typeof maintenanceEventEstimationSchema>;
30
+ type Activity = z.infer<typeof activitySchema>;
31
+ type MembershipSignup = z.infer<typeof membershipSignupSchema>;
32
+ type AircraftPosition = z.infer<typeof aircraftPositionSchema>;
29
33
  type Avail = z.infer<typeof availSchema>;
30
34
  type Alert = z.infer<typeof alertSchema>;
31
35
  type Booking = z.infer<typeof bookingSchema>;
@@ -57,6 +61,37 @@ type AirplaneIssueStatus = z.infer<typeof airplaneIssueStatusEnum>;
57
61
  type Event = z.infer<typeof eventSchema>;
58
62
  type Ticket = z.infer<typeof ticketSchema>;
59
63
  type Post = z.infer<typeof postSchema>;
64
+ interface CreatePostInput {
65
+ title?: string | null;
66
+ content: string;
67
+ sticky?: boolean;
68
+ public?: boolean;
69
+ }
70
+ interface UpdatePostInput {
71
+ title?: string | null;
72
+ content: string;
73
+ sticky?: boolean;
74
+ public?: boolean;
75
+ }
76
+ interface CreateAirplaneIssueInput {
77
+ title?: string | null;
78
+ body: string;
79
+ severity?: AirplaneIssueSeverity;
80
+ ata_chapter?: string | null;
81
+ }
82
+ interface UpdateAirplaneIssueInput {
83
+ title?: string | null;
84
+ body?: string;
85
+ severity?: AirplaneIssueSeverity;
86
+ ata_chapter?: string | null;
87
+ }
88
+ interface ResolveAirplaneIssueInput {
89
+ resolution_notes?: string | null;
90
+ }
91
+ interface DeferAirplaneIssueInput {
92
+ deferred_until?: string | null;
93
+ deferral_notes?: string | null;
94
+ }
60
95
  type Comment = z.infer<typeof commentSchema>;
61
96
  interface CreateCommentInput {
62
97
  body: string;
@@ -81,7 +116,8 @@ interface DataWrappedResponse<T, M = undefined> {
81
116
  data: T;
82
117
  meta?: M;
83
118
  }
84
- interface PaginatedResponse<T = any> {
119
+ type ApiResponse<T> = DataWrappedResponse<T>;
120
+ interface PaginatedResponse<T = unknown> {
85
121
  data: T[];
86
122
  meta: {
87
123
  current_page: number;
@@ -109,11 +145,12 @@ interface ToggleFavoriteResponse {
109
145
 
110
146
  interface ComplianceRequirement {
111
147
  requirement_id: number;
112
- document_type_class: string;
113
- document_type_label: string;
148
+ form_template_id: number;
149
+ form_template_name: string;
114
150
  logical_group: string;
115
151
  is_satisfied: boolean;
116
- document: any | null;
152
+ awaiting_countersignature?: boolean;
153
+ submission: FormSubmission | null;
117
154
  }
118
155
  interface ComplianceRequirementGroup {
119
156
  group_name: string;
@@ -121,11 +158,22 @@ interface ComplianceRequirementGroup {
121
158
  group_satisfied: boolean;
122
159
  requirements: ComplianceRequirement[];
123
160
  }
161
+ type ComplianceGroupSource = {
162
+ type: "direct";
163
+ } | {
164
+ type: "role";
165
+ role: string;
166
+ } | {
167
+ type: "airplane";
168
+ airplane_id: number;
169
+ registration: string;
170
+ };
124
171
  interface ComplianceGroup {
125
172
  group_id: number;
126
173
  group_name: string;
127
174
  overall_satisfied: boolean;
128
175
  requirement_groups: ComplianceRequirementGroup[];
176
+ sources?: ComplianceGroupSource[];
129
177
  }
130
178
  interface ComplianceSummary {
131
179
  total_groups: number;
@@ -147,4 +195,228 @@ interface ComplianceResponse {
147
195
  };
148
196
  }
149
197
 
150
- export type { Address, AircraftRating, Airplane, AirplaneIssue, AirplaneIssueSeverity, AirplaneIssueStatus, AirplanePermission, AirplaneShareInvite, Airport, Alert, AllowedDocumentType, ApproachType, Avail, BaseMembership, BaseModel, Booking, Comment, Company, ComplianceData, ComplianceGroup, ComplianceRequirement, ComplianceRequirementGroup, ComplianceResponse, ComplianceSummary, Course, CourseCheckSyllabus, CourseEnrollment, CourseEnrollmentMetrics, CourseFee, CreateCommentInput, DataWrappedResponse, Document, DocumentComplianceStatus, DocumentRequirement, DocumentRequirementGroup, DocumentRequirementGroupAssignment, DocumentShare, DocumentType, Event, Expense, ExpenseItem, ExtendedAirplane, Fee, FlightLog, Invoice, Landing, LandingFee, MaintenanceEvent, MaintenanceEventEstimation, MaintenanceStatus, Media, MediaCollection, Membership, PaginatedResponse, Post, PrePaidPackage, Price, Qualification, RecurringFlight, Resource, Role, Runway, ScheduledFlight, Setting, SpecialFlight, Tag, Ticket, ToggleFavoriteResponse, UpdateCommentInput, User, UserAircraftRating, UserQualification, Waypoint };
198
+ type AircraftBlockReason = "general" | "ferry" | "weather" | "private" | "aog" | "other";
199
+ interface AircraftBlock {
200
+ type: "aircraftBlock";
201
+ id: number;
202
+ airplane_id: number;
203
+ company_id: number;
204
+ starts_at: string;
205
+ ends_at: string;
206
+ reason: AircraftBlockReason;
207
+ note: string | null;
208
+ is_maintenance: boolean;
209
+ maintenance_event_id: number | null;
210
+ created_at: string;
211
+ updated_at: string;
212
+ can?: Record<string, boolean | null>;
213
+ }
214
+
215
+ type BackgroundTaskStatus = "queued" | "processing" | "completed" | "failed" | "canceled";
216
+ interface BackgroundTask<TResult = unknown> {
217
+ type: "background_task";
218
+ /** Store key — mirrors `uuid` (the API has no client-facing integer id). */
219
+ id: string;
220
+ uuid: string;
221
+ task_type: string;
222
+ status: BackgroundTaskStatus;
223
+ progress: number | null;
224
+ progress_label: string | null;
225
+ company_id: number | null;
226
+ user_id: number | null;
227
+ result: TResult | null;
228
+ error: string | null;
229
+ started_at: string | null;
230
+ finished_at: string | null;
231
+ created_at: string | null;
232
+ }
233
+
234
+ type AiSuggestionStatus = "pending" | "ready" | "applied" | "dismissed" | "failed";
235
+ interface AiSuggestion<TPayload = unknown> {
236
+ type: "ai_suggestion";
237
+ id: number;
238
+ subject_type: string;
239
+ subject_id: number;
240
+ company_id: number | null;
241
+ suggestion_type: string;
242
+ locale: string;
243
+ payload: TPayload;
244
+ meta?: unknown;
245
+ status: AiSuggestionStatus;
246
+ requested_by: number | null;
247
+ applied_at: string | null;
248
+ dismissed_at: string | null;
249
+ created_at: string;
250
+ }
251
+ interface AiSuggestedMilestone {
252
+ name: string;
253
+ description?: string | null;
254
+ kind: "progress" | "prerequisite" | "solo" | "cross_country";
255
+ is_prerequisite: boolean;
256
+ sort_order: number;
257
+ }
258
+ interface CourseDescriptionSuggestionPayload {
259
+ title: string;
260
+ subtitle: string;
261
+ summary: string;
262
+ html: string;
263
+ milestones: AiSuggestedMilestone[];
264
+ }
265
+ interface LogbookFlightLogPayload {
266
+ etdZ: string | null;
267
+ etaZ: string | null;
268
+ departure_airport_id: number | null;
269
+ destination_airport_id: number | null;
270
+ departure_airport_icao: string | null;
271
+ destination_airport_icao: string | null;
272
+ full_stop_landings: number;
273
+ touch_and_gos: number;
274
+ low_approaches: number;
275
+ crew_assignments: {
276
+ membership_id: number;
277
+ role: string;
278
+ }[];
279
+ membership_id: number | null;
280
+ }
281
+ interface LogbookSuggestionMeta {
282
+ flags?: string[];
283
+ match?: {
284
+ confidence: string;
285
+ reasoning: string;
286
+ };
287
+ extraction?: {
288
+ valid: boolean | null;
289
+ discrepancy_minutes: number | null;
290
+ };
291
+ crew_text?: string | null;
292
+ }
293
+ type LogbookSuggestion = AiSuggestion<LogbookFlightLogPayload> & {
294
+ meta?: LogbookSuggestionMeta;
295
+ };
296
+ interface DiscardedRow {
297
+ reason: string;
298
+ flight: Record<string, unknown>;
299
+ }
300
+ interface LogbookStageResult {
301
+ booking_id: number;
302
+ suggestion_ids: number[];
303
+ staged: number;
304
+ routed: Record<string, number> | number[];
305
+ discarded: DiscardedRow[];
306
+ }
307
+
308
+ interface RoleListItem {
309
+ id: number;
310
+ name: string;
311
+ description: string | null;
312
+ is_system: boolean;
313
+ has_duties: boolean;
314
+ company_id: number | null;
315
+ permissions_count: number;
316
+ }
317
+ interface PermissionItem {
318
+ id: number;
319
+ name: string;
320
+ description: string | null;
321
+ group: string;
322
+ }
323
+ interface RoleDetail extends Omit<RoleListItem, "permissions_count"> {
324
+ permissions: PermissionItem[];
325
+ }
326
+ interface GroupedPermissions {
327
+ [group: string]: PermissionItem[];
328
+ }
329
+
330
+ interface LandingFeeTemplateParams {
331
+ landing_type: "FULLSTOP" | "TOUCHANDGO" | "LOWAPPROACH";
332
+ net_gross: "net" | "gross";
333
+ valid_from: string;
334
+ tax_percentage?: number;
335
+ approach_type_id?: number;
336
+ }
337
+ interface LandingFeeImportResult {
338
+ created: number;
339
+ updated: number;
340
+ unchanged: number;
341
+ prices_added: number;
342
+ skipped: number;
343
+ issues: string[];
344
+ preview: Array<[
345
+ string,
346
+ string,
347
+ string,
348
+ string,
349
+ string,
350
+ "new" | "update" | "unchanged"
351
+ ]>;
352
+ meta: {
353
+ landing_type: string;
354
+ approach_type_id: number;
355
+ net_gross: string;
356
+ tax_percentage: number;
357
+ valid_from: string;
358
+ };
359
+ }
360
+ interface LandingFeeInvoicePreviewRow {
361
+ registration: string;
362
+ airplane_id: number | null;
363
+ fee_type: string;
364
+ landing_type: string | null;
365
+ unit_price: number;
366
+ price_basis: "net" | "gross";
367
+ vat_rate: number | null;
368
+ net_total: number | null;
369
+ gross_total: number | null;
370
+ current_price: number | null;
371
+ current_net_total: number | null;
372
+ current_gross_total: number | null;
373
+ date: string | null;
374
+ start_time: string | null;
375
+ landing_time: string | null;
376
+ status: "new" | "changed" | "unchanged" | "unmatched-aircraft" | "unmapped-fee-type" | "airport-unknown";
377
+ }
378
+ interface LandingFeeInvoicePreview {
379
+ rejected: boolean;
380
+ message: string | null;
381
+ company_id: number;
382
+ airport: {
383
+ id: number;
384
+ ident: string;
385
+ name: string;
386
+ } | null;
387
+ invoice: {
388
+ number: string | null;
389
+ date: string | null;
390
+ currency: string | null;
391
+ issuing_airport_name: string | null;
392
+ suggested_airport_icao_ident: string | null;
393
+ };
394
+ landing_fee_rows: LandingFeeInvoicePreviewRow[];
395
+ other_fees: Array<Record<string, unknown>>;
396
+ warnings: Array<{
397
+ type: string;
398
+ message: string;
399
+ }>;
400
+ }
401
+ interface LandingFeeInvoiceApplyPayload {
402
+ airport_id: number;
403
+ valid_from: string;
404
+ tax_percentage: number;
405
+ approach_type_id: number;
406
+ rows: Array<{
407
+ airplane_id: number;
408
+ landing_type: string;
409
+ unit_price: number;
410
+ price_basis: "net" | "gross";
411
+ vat_rate: number | null;
412
+ }>;
413
+ }
414
+ interface LandingFeeInvoiceApplyResult {
415
+ created: number;
416
+ updated: number;
417
+ unchanged: number;
418
+ prices_added: number;
419
+ issues: string[];
420
+ }
421
+
422
+ export type { Activity, Address, AiSuggestedMilestone, AiSuggestion, AiSuggestionStatus, AircraftBlock, AircraftBlockReason, AircraftPosition, AircraftRating, Airplane, AirplaneIssue, AirplaneIssueSeverity, AirplaneIssueStatus, AirplanePermission, AirplaneShareInvite, Airport, Alert, AllowedDocumentType, ApiResponse, ApproachType, Avail, BackgroundTask, BackgroundTaskStatus, BaseMembership, BaseModel, Booking, Comment, Company, ComplianceData, ComplianceGroup, ComplianceGroupSource, ComplianceRequirement, ComplianceRequirementGroup, ComplianceResponse, ComplianceSummary, Course, CourseCheckSyllabus, CourseDescriptionSuggestionPayload, CourseEnrollment, CourseEnrollmentMetrics, CourseFee, CreateAirplaneIssueInput, CreateCommentInput, CreatePostInput, DataWrappedResponse, DeferAirplaneIssueInput, DiscardedRow, Document, DocumentComplianceStatus, DocumentRequirement, DocumentRequirementGroup, DocumentRequirementGroupAssignment, DocumentShare, DocumentType, Event, Expense, ExpenseItem, ExtendedAirplane, Fee, FeeCategoryOptions, FlightLog, GroupedPermissions, Invoice, Landing, LandingFee, LandingFeeImportResult, LandingFeeInvoiceApplyPayload, LandingFeeInvoiceApplyResult, LandingFeeInvoicePreview, LandingFeeInvoicePreviewRow, LandingFeeTemplateParams, LogbookFlightLogPayload, LogbookStageResult, LogbookSuggestion, LogbookSuggestionMeta, MaintenanceEvent, MaintenanceEventEstimation, MaintenanceStatus, Media, MediaCollection, Membership, MembershipSignup, PaginatedResponse, PermissionItem, Post, PrePaidPackage, Price, Qualification, RecurringFlight, ResolveAirplaneIssueInput, Resource, Role, RoleDetail, RoleListItem, Runway, ScheduledFlight, Setting, SpecialFlight, Tag, Ticket, ToggleFavoriteResponse, UpdateAirplaneIssueInput, UpdateCommentInput, UpdatePostInput, User, UserAircraftRating, UserQualification, Waypoint };
@@ -1 +1 @@
1
- import "../chunk-LXNCAKJZ.js";
1
+ import "../chunk-2WJHTRIE.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@updraft-solutions/mcrit-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared TypeScript types, Zod schemas, and pure helpers for the MCRIT aviation fleet management platform",
5
5
  "homepage": "https://github.com/updraft-solutions/mcrit-sdk#readme",
6
6
  "bugs": {
@@ -20,12 +20,12 @@ export interface CourseFeeLike extends FeeLike {
20
20
  count?: number;
21
21
  variant?: string | null;
22
22
  is_optional?: boolean;
23
- sort_order?: number;
23
+ sort_order?: number | null;
24
24
  };
25
25
  count?: number;
26
26
  variant?: string | null;
27
27
  is_optional?: boolean;
28
- sort_order?: number;
28
+ sort_order?: number | null;
29
29
  fee?: FeeLike;
30
30
  }
31
31
 
package/src/index.ts CHANGED
@@ -11,6 +11,9 @@ export {
11
11
  type AirplanePermission,
12
12
  type AirplaneShareInvite,
13
13
  type LandingFee,
14
+ type Fee,
15
+ type FeeCategoryOptions,
16
+ type Tag,
14
17
  type AircraftRating,
15
18
  type UserAircraftRating,
16
19
  type UserQualification,
@@ -21,6 +24,9 @@ export {
21
24
  type MaintenanceEvent,
22
25
  type MaintenanceStatus,
23
26
  type MaintenanceEventEstimation,
27
+ type Activity,
28
+ type MembershipSignup,
29
+ type AircraftPosition,
24
30
  type Avail,
25
31
  type Alert,
26
32
  type Booking,
@@ -48,6 +54,12 @@ export {
48
54
  type Event,
49
55
  type Ticket,
50
56
  type Post,
57
+ type CreatePostInput,
58
+ type UpdatePostInput,
59
+ type CreateAirplaneIssueInput,
60
+ type UpdateAirplaneIssueInput,
61
+ type ResolveAirplaneIssueInput,
62
+ type DeferAirplaneIssueInput,
51
63
  type Comment,
52
64
  type CreateCommentInput,
53
65
  type UpdateCommentInput,
@@ -57,6 +69,7 @@ export {
57
69
  type Setting,
58
70
  // types/api.ts
59
71
  type DataWrappedResponse,
72
+ type ApiResponse,
60
73
  type PaginatedResponse,
61
74
  type Resource,
62
75
  type ToggleFavoriteResponse,
@@ -64,9 +77,38 @@ export {
64
77
  type ComplianceRequirement,
65
78
  type ComplianceRequirementGroup,
66
79
  type ComplianceGroup,
80
+ type ComplianceGroupSource,
67
81
  type ComplianceSummary,
68
82
  type ComplianceData,
69
83
  type ComplianceResponse,
84
+ // types/aircraft-block.ts
85
+ type AircraftBlock,
86
+ type AircraftBlockReason,
87
+ // types/background-task.ts
88
+ type BackgroundTask,
89
+ type BackgroundTaskStatus,
90
+ // types/ai.ts
91
+ type AiSuggestion,
92
+ type AiSuggestionStatus,
93
+ type AiSuggestedMilestone,
94
+ type CourseDescriptionSuggestionPayload,
95
+ type LogbookFlightLogPayload,
96
+ type LogbookSuggestionMeta,
97
+ type LogbookSuggestion,
98
+ type DiscardedRow,
99
+ type LogbookStageResult,
100
+ // types/roles.ts
101
+ type RoleListItem,
102
+ type PermissionItem,
103
+ type RoleDetail,
104
+ type GroupedPermissions,
105
+ // types/landing-fee.ts
106
+ type LandingFeeTemplateParams,
107
+ type LandingFeeImportResult,
108
+ type LandingFeeInvoicePreviewRow,
109
+ type LandingFeeInvoicePreview,
110
+ type LandingFeeInvoiceApplyPayload,
111
+ type LandingFeeInvoiceApplyResult,
70
112
  } from "./types/index.js";
71
113
 
72
114
  export * from "./money/index.js";
@@ -3,10 +3,13 @@ import { z } from "zod";
3
3
  // Shared helpers
4
4
  export const zNullableBool = z.boolean().nullable().optional();
5
5
  export const zNetGross = z.enum(["net", "gross"]).optional();
6
+ // Mirrors backend ContactData (all members null|string|Optional).
6
7
  export const zContactDTO = z.object({
7
- name: z.string().optional(),
8
- email: z.string().email().optional(),
9
- phone: z.string().optional(),
8
+ name: z.string().nullable().optional(),
9
+ email: z.string().nullable().optional(),
10
+ phone: z.string().nullable().optional(),
11
+ company: z.string().nullable().optional(),
12
+ fax: z.string().nullable().optional(),
10
13
  });
11
14
  export const zPhpMoneyObject = z.object({
12
15
  amount: z.number(),
@@ -57,12 +60,52 @@ export const mediaCollection = z
57
60
  .optional();
58
61
 
59
62
  // User & Company
63
+ /** Minimal participant shape used in the impersonation payload. */
64
+ export const impersonationParticipantSchema = z.object({
65
+ id: z.number(),
66
+ name: z.string(),
67
+ email: z.string(),
68
+ });
69
+ export type ImpersonationParticipant = z.infer<
70
+ typeof impersonationParticipantSchema
71
+ >;
72
+
73
+ /**
74
+ * Impersonation state. Rides along on the authenticated user payload
75
+ * (`/auth/user` → `user.impersonation`), so it is the single source of
76
+ * truth — no polling required. The backend's `HandleImpersonation`
77
+ * middleware also stamps an `X-Impersonating` header on every non-admin
78
+ * response, which clients use to detect a session that ended server-side.
79
+ */
80
+ export const impersonationStateSchema = z.object({
81
+ is_impersonating: z.boolean(),
82
+ impersonator: impersonationParticipantSchema.optional(),
83
+ impersonated: impersonationParticipantSchema.optional(),
84
+ started_at: z.string().optional(),
85
+ expires_at: z.string().optional(),
86
+ });
87
+ export type ImpersonationState = z.infer<typeof impersonationStateSchema>;
88
+
60
89
  export const userSchema = z.object({
61
90
  type: z.literal("user"),
62
91
  id: z.number(),
63
92
  name: z.string(),
64
- email: z.string().optional(),
65
- mobile: z.string().optional(),
93
+ firstname: z.string().nullable().optional(),
94
+ lastname: z.string().nullable().optional(),
95
+ // email/mobile are gate-guarded server-side (viewMail/viewMobile) and come
96
+ // back null when denied.
97
+ email: z.string().nullable().optional(),
98
+ mobile: z.string().nullable().optional(),
99
+ // UserResource media envelope (avatar/header, present when loaded).
100
+ media: z
101
+ .object({
102
+ avatar: mediaSchema.nullable().optional(),
103
+ header: mediaSchema.nullable().optional(),
104
+ })
105
+ .optional(),
106
+ // Present only on the authenticated-user payload while an admin
107
+ // impersonation session is active.
108
+ impersonation: impersonationStateSchema.optional(),
66
109
  });
67
110
 
68
111
  export const companySchema = z.object({
@@ -77,4 +120,25 @@ export const companySchema = z.object({
77
120
  // slim company payloads may omit it.
78
121
  timezone: z.string().optional(),
79
122
  ai_landing_fee_invoices_enabled: z.boolean().optional(),
123
+ // Active AI-feature entitlement keys (per-company subscription gating,
124
+ // e.g. "ai.logbook_import"). Serialized by CompanyResource alongside
125
+ // `permissions[]`; slim payloads may omit it.
126
+ entitlements: z.array(z.string()).optional(),
127
+ // BaseCompanyResource extras: cached-minified home airport + the
128
+ // distance computed on radius-filtered public listings.
129
+ airport_id: z.number().nullable().optional(),
130
+ airport: z
131
+ .object({
132
+ id: z.number(),
133
+ ident: z.string(),
134
+ name: z.string(),
135
+ municipality: z.string().nullable().optional(),
136
+ iso_country: z.string().nullable().optional(),
137
+ latitude_deg: z.number().nullable().optional(),
138
+ longitude_deg: z.number().nullable().optional(),
139
+ })
140
+ .nullable()
141
+ .optional(),
142
+ icao: z.string().nullable().optional(),
143
+ distance_in_km: z.number().optional(),
80
144
  });
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+
3
+ export const CourseMilestoneKindEnum = z.enum([
4
+ "progress",
5
+ "solo",
6
+ "cross_country",
7
+ "theory",
8
+ "practical",
9
+ "prerequisite",
10
+ "custom",
11
+ ]);
12
+ export type CourseMilestoneKind = z.infer<typeof CourseMilestoneKindEnum>;
13
+
14
+ export const courseMilestoneSchema = z.object({
15
+ type: z.literal("courseMilestone").optional(),
16
+ id: z.number(),
17
+ course_id: z.number(),
18
+ name: z.string(),
19
+ description: z.string().nullable().optional(),
20
+ kind: z.string(),
21
+ is_prerequisite: z.boolean(),
22
+ requires_form_template_id: z.number().nullable().optional(),
23
+ required_form_template: z
24
+ .object({ id: z.number(), name: z.string().optional() })
25
+ .nullable()
26
+ .optional(),
27
+ completion_rule: z.record(z.string(), z.unknown()).nullable().optional(),
28
+ sort_order: z.number(),
29
+ created_at: z.string().optional(),
30
+ updated_at: z.string().optional(),
31
+ can: z
32
+ .object({
33
+ update: z.boolean().nullable().optional(),
34
+ delete: z.boolean().nullable().optional(),
35
+ })
36
+ .optional(),
37
+ });
38
+ export type CourseMilestone = z.infer<typeof courseMilestoneSchema>;
39
+
40
+ export const CourseMilestoneFormSchema = z.object({
41
+ name: z.string().min(2).max(191),
42
+ description: z.string().nullable().optional(),
43
+ kind: z.string().max(64).default("progress"),
44
+ is_prerequisite: z.boolean().default(false),
45
+ requires_form_template_id: z.number().nullable().optional(),
46
+ completion_rule: z.record(z.string(), z.unknown()).nullable().optional(),
47
+ sort_order: z.number().int().min(0).optional(),
48
+ });
49
+ export type CourseMilestoneForm = z.infer<typeof CourseMilestoneFormSchema>;
50
+
51
+ export const courseEnrollmentMilestoneSchema = z.object({
52
+ type: z.literal("courseEnrollmentMilestone").optional(),
53
+ id: z.number(),
54
+ course_enrollment_id: z.number(),
55
+ course_milestone_id: z.number(),
56
+ milestone: courseMilestoneSchema.optional(),
57
+ achieved_at: z.string().nullable().optional(),
58
+ achieved_by_membership_id: z.number().nullable().optional(),
59
+ achieved_by: z
60
+ .object({
61
+ id: z.number(),
62
+ user: z.object({ name: z.string().optional() }).optional(),
63
+ })
64
+ .nullable()
65
+ .optional(),
66
+ notes: z.string().nullable().optional(),
67
+ is_achieved: z.boolean(),
68
+ can_be_achieved: z.boolean(),
69
+ can: z
70
+ .object({
71
+ achieve: z.boolean().nullable().optional(),
72
+ revoke: z.boolean().nullable().optional(),
73
+ })
74
+ .optional(),
75
+ });
76
+ export type CourseEnrollmentMilestone = z.infer<
77
+ typeof courseEnrollmentMilestoneSchema
78
+ >;
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Company-scoped equipment catalog entry (m-crit-api
5
+ * docs/features/airplane-equipment.md). Assigned to airplanes via the
6
+ * airplane PATCH `equipment` array.
7
+ */
8
+ export const equipmentSchema = z.object({
9
+ type: z.literal("equipment").optional(),
10
+ id: z.number(),
11
+ name: z.string(),
12
+ description: z.string().nullable().optional(),
13
+ manual_url: z.string().nullable().optional(),
14
+ });
15
+ export type Equipment = z.infer<typeof equipmentSchema>;
16
+
17
+ /**
18
+ * Write shape for the airplane PATCH: existing entries carry their id
19
+ * (description/manual_url on an id entry UPDATE the catalog entry);
20
+ * id-less entries are created on the fly by name.
21
+ */
22
+ export interface EquipmentEntry {
23
+ id?: number;
24
+ name: string;
25
+ description?: string | null;
26
+ manual_url?: string | null;
27
+ }