@vulog/aima-vehicle 1.1.50 → 1.1.52

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.
package/README.md CHANGED
@@ -1,12 +1,20 @@
1
- # @vulog/aima-booking
1
+ # @vulog/aima-vehicle
2
+
3
+ Vehicle management module for AIMA platform.
4
+
5
+ ## Installation
2
6
 
3
7
  ```bash
4
8
  npm i @vulog/aima-client @vulog/aima-core @vulog/aima-vehicle
5
9
  ```
6
10
 
11
+ ## Usage
12
+
13
+ ### Initialize Client
14
+
7
15
  ```javascript
8
16
  import { getClient } from '@vulog/aima-client';
9
- import { getModelById } from '@vulog/aima-vehicle';
17
+ import { getVehicles, getModelById, getModels, getVehicleById, getVehiclesRealTime } from '@vulog/aima-vehicle';
10
18
 
11
19
  const client = getClient({
12
20
  apiKey: '...',
@@ -15,7 +23,240 @@ const client = getClient({
15
23
  clientSecret: '...',
16
24
  fleetId: '...',
17
25
  });
26
+ ```
27
+
28
+ ### Get All Vehicles
29
+
30
+ Fetches all vehicles with pagination (default page size: 500). The implementation uses an internal `getVehiclesPage` function to fetch individual pages of vehicles.
31
+
32
+ ```javascript
33
+ // Get all vehicles
34
+ const vehicles = await getVehicles(client);
35
+
36
+ // Get all vehicles with custom page size
37
+ const vehicles = await getVehicles(client, 1000);
38
+ ```
39
+
40
+ The `getVehicles` function automatically handles pagination and will fetch all available vehicles up to a maximum of 50 pages. If you need to fetch a specific page of vehicles, you can use the internal `getVehiclesPage` function:
41
+
42
+ ```javascript
43
+ // Get a specific page of vehicles
44
+ const vehiclesPage = await getVehiclesPage(client, 0, 100); // First page, 100 vehicles per page
45
+ ```
46
+
47
+ Note: `getVehiclesPage` is an internal function and is not exported from the package. It's used internally by `getVehicles` to handle the pagination logic.
48
+
49
+ ### Get Vehicle by ID
50
+
51
+ Fetches a specific vehicle by its ID.
52
+
53
+ ```javascript
54
+ const vehicle = await getVehicleById(client, 'dcb0c41e-4be3-11ea-83a5-024d0cba6da4');
55
+ ```
56
+
57
+ ### Get All Models
58
+
59
+ Fetches all vehicle models.
60
+
61
+ ```javascript
62
+ const models = await getModels(client);
63
+ ```
64
+
65
+ ### Get Model by ID
66
+
67
+ Fetches a specific model by its ID.
68
+
69
+ ```javascript
70
+ const model = await getModelById(client, 372);
71
+ ```
72
+
73
+ ### Get Real-Time Vehicle Data
74
+
75
+ Fetches real-time data for all vehicles with pagination (default page size: 500). The implementation uses an internal `getVehiclesRealTimePage` function to fetch individual pages of real-time vehicle data.
76
+
77
+ ```javascript
78
+ // Get real-time data for all vehicles
79
+ const realTimeVehicles = await getVehiclesRealTime(client);
80
+
81
+ // Get real-time data with custom page size
82
+ const realTimeVehicles = await getVehiclesRealTime(client, 1000);
83
+
84
+ // Get only vehicles updated after a specific timestamp (in UTC milliseconds)
85
+ const lastSyncTime = Date.now() - 24 * 60 * 60 * 1000; // 24 hours ago
86
+ const updatedVehicles = await getVehiclesRealTime(client, 500, lastSyncTime);
87
+ ```
88
+
89
+ The `getVehiclesRealTime` function automatically handles pagination and will fetch all available vehicles up to a maximum of 50 pages. If you need to fetch a specific page of real-time vehicle data, you can use the internal `getVehiclesRealTimePage` function:
90
+
91
+ ```javascript
92
+ // Get a specific page of real-time vehicle data
93
+ const realTimeVehiclesPage = await getVehiclesRealTimePage(client, 0, 100); // First page, 100 vehicles per page
94
+
95
+ // Get a specific page with lastUpdatedMillis filter
96
+ const updatedVehiclesPage = await getVehiclesRealTimePage(client, 0, 100, lastSyncTime);
97
+ ```
98
+
99
+ Note: `getVehiclesRealTimePage` is an internal function and is not exported from the package. It's used internally by `getVehiclesRealTime` to handle the pagination logic.
100
+
101
+ ## Types
102
+
103
+ ### Vehicle
104
+
105
+ ```typescript
106
+ interface Vehicle {
107
+ id: string;
108
+ name: string;
109
+ plate: string;
110
+ vin: string;
111
+ model: Model;
112
+ options: Options[];
113
+ createDate: string;
114
+ updateDate: string;
115
+ fleetId: string;
116
+ externalId: string;
117
+ wakeupProvider?: string;
118
+ msisdn: string;
119
+ iccid: string;
120
+ imsi?: string;
121
+ published: boolean;
122
+ noBox: boolean;
123
+ archived: boolean;
124
+ }
125
+ ```
126
+
127
+ ### Model
128
+
129
+ ```typescript
130
+ interface Model {
131
+ id: number;
132
+ name: string;
133
+ energyType: string;
134
+ status: string;
135
+ nbOfSeats: number;
136
+ autonomy: number;
137
+ creationDate: string;
138
+ updateDate: string;
139
+ description: string;
140
+ fleetId: string;
141
+ vehicleType: string;
142
+ transmission: string;
143
+ outOfServiceRange: string;
144
+ recoveryRange: string;
145
+ incentiveThresholds: any[];
146
+ redistributeVehicleChargedEnoughRange: string;
147
+ odometerReliable?: boolean;
148
+ }
149
+ ```
150
+
151
+ ### Options
152
+
153
+ ```typescript
154
+ interface Options {
155
+ id: number;
156
+ fleetId: string;
157
+ name: string;
158
+ type: string;
159
+ description: string;
160
+ }
161
+ ```
18
162
 
19
- const response = await getModelById(client, 25);
163
+ ### VehicleRealTime
20
164
 
165
+ ```typescript
166
+ interface VehicleRealTime {
167
+ id: string;
168
+ name: string;
169
+ plate: string;
170
+ vin: string;
171
+ fleetid: string;
172
+ boxid: string;
173
+ vehicle_status: number;
174
+ zones: Zone[];
175
+ releasable: boolean;
176
+ box_status: number;
177
+ autonomy: number;
178
+ autonomy2: number;
179
+ isCharging: boolean;
180
+ battery: number;
181
+ km: number;
182
+ speed: number;
183
+ location: {
184
+ geohash: string;
185
+ cap: number;
186
+ latitude: number;
187
+ longitude: number;
188
+ gpsDate: string;
189
+ lastMovingDate: string;
190
+ };
191
+ endTripLocation: {
192
+ latitude: number;
193
+ longitude: number;
194
+ };
195
+ endZoneIds: [];
196
+ productIds: [];
197
+ isDoorClosed: boolean;
198
+ isDoorLocked: boolean;
199
+ engineOn: boolean;
200
+ immobilizerOn: boolean;
201
+ secureOn: boolean;
202
+ spareLockOn: boolean | null;
203
+ pileLockOn: boolean | null;
204
+ helmetPresent: boolean | null;
205
+ helmet2Present: boolean | null;
206
+ helmetBoxLockOn: boolean | null;
207
+ helmet2LockOn: boolean | null;
208
+ userId: string | null;
209
+ user_locale: string | null;
210
+ rfid: string | null;
211
+ orderId: string | null;
212
+ gatewayUrl: string | null;
213
+ booking_status: number;
214
+ booking_date: string | null;
215
+ expiresOn: boolean | null;
216
+ last_active_date: string;
217
+ last_wakeUp_date: string;
218
+ version: string;
219
+ pricingId: string | null;
220
+ start_date: string | null;
221
+ theorStartDate: string | null;
222
+ theorEndDate: string | null;
223
+ startZones: Zone[];
224
+ endZones: Zone[];
225
+ disabled: boolean;
226
+ outOfServiceReason: string;
227
+ ignitionOffGeohash: string | null;
228
+ geohashNeighbours: string[];
229
+ cleanlinessStatus: boolean;
230
+ needsRedistribution: boolean;
231
+ batteryUnderThreshold: boolean;
232
+ isBeingTowed: boolean;
233
+ automaticallyEnableVehicleAfterRangeRecovery: boolean;
234
+ key: {
235
+ deviceName: string;
236
+ };
237
+ doNotTrack: boolean;
238
+ energyLevel: number;
239
+ lastOosDate: string;
240
+ hasAlerts: boolean;
241
+ firmwareModel: string;
242
+ comeFromApp: string;
243
+ doors: {
244
+ frontLeftClosed: boolean;
245
+ frontRightClosed: boolean;
246
+ rearLeftClosed: boolean;
247
+ rearRightClosed: boolean;
248
+ trunkClosed: boolean;
249
+ hoodClosed: boolean;
250
+ };
251
+ windows: {
252
+ frontLeftClosed: boolean;
253
+ frontRightClosed: boolean;
254
+ rearLeftClosed: boolean;
255
+ rearRightClosed: boolean;
256
+ trunkClosed: boolean;
257
+ };
258
+ doorsAndWindowsClosed: boolean;
259
+ vpChecksum: string;
260
+ firmwareBuildDate: string;
261
+ }
21
262
  ```
package/dist/index.d.mts CHANGED
@@ -1,23 +1,99 @@
1
1
  import { Client } from '@vulog/aima-client';
2
2
 
3
+ /**
4
+ * Represents a vehicle model with its specifications and characteristics
5
+ */
3
6
  type Model = {
7
+ /** Unique identifier of the model */
4
8
  id: number;
9
+ /** Name of the model (e.g., "C-Zero") */
5
10
  name: string;
6
- brand: string;
11
+ /** Type of energy used by the vehicle (e.g., "ELECTRIC") */
7
12
  energyType: string;
13
+ /** Current status of the model (e.g., "ACTIVE") */
8
14
  status: string;
15
+ /** Number of seats in the vehicle */
9
16
  nbOfSeats: number;
17
+ /** Maximum range/autonomy of the vehicle in kilometers */
10
18
  autonomy: number;
19
+ /** Date when the model was created */
11
20
  creationDate: string;
21
+ /** Date when the model was last updated */
12
22
  updateDate: string;
23
+ /** Description of the model (e.g., brand name) */
13
24
  description: string;
25
+ /** ID of the fleet this model belongs to */
14
26
  fleetId: string;
27
+ /** Type of vehicle (e.g., "CAR") */
15
28
  vehicleType: string;
29
+ /** Type of transmission (e.g., "UNDEFINED") */
16
30
  transmission: string;
31
+ /** Range threshold for out of service status */
17
32
  outOfServiceRange: string;
33
+ /** Range threshold for recovery */
18
34
  recoveryRange: string;
19
- incentiveThresholds: [];
35
+ /** Array of incentive thresholds */
36
+ incentiveThresholds: any[];
37
+ /** Range threshold for vehicle redistribution */
20
38
  redistributeVehicleChargedEnoughRange: string;
39
+ /** Indicates if the odometer readings are reliable */
40
+ odometerReliable?: boolean;
41
+ [key: string]: any;
42
+ };
43
+ /**
44
+ * Represents a vehicle in the system
45
+ */
46
+ type Vehicle = {
47
+ /** Unique identifier of the vehicle */
48
+ id: string;
49
+ /** Name of the vehicle */
50
+ name: string;
51
+ /** License plate number */
52
+ plate: string;
53
+ /** Vehicle Identification Number */
54
+ vin: string;
55
+ /** Model information of the vehicle */
56
+ model: Model;
57
+ /** List of options/features installed on the vehicle */
58
+ options: Options[];
59
+ /** Date when the vehicle was created */
60
+ createDate: string;
61
+ /** Date when the vehicle was last updated */
62
+ updateDate: string;
63
+ /** ID of the fleet this vehicle belongs to */
64
+ fleetId: string;
65
+ /** External system identifier */
66
+ externalId: string;
67
+ /** Provider used for vehicle wakeup */
68
+ wakeupProvider?: string;
69
+ /** Mobile Subscriber Integrated Services Digital Network Number */
70
+ msisdn: string;
71
+ /** Integrated Circuit Card Identifier */
72
+ iccid: string;
73
+ /** International Mobile Subscriber Identity */
74
+ imsi?: string;
75
+ /** Whether the vehicle is published in the system */
76
+ published: boolean;
77
+ /** Whether the vehicle has no box installed */
78
+ noBox: boolean;
79
+ /** Whether the vehicle is archived */
80
+ archived: boolean;
81
+ [key: string]: any;
82
+ };
83
+ /**
84
+ * Represents a vehicle option or feature
85
+ */
86
+ type Options = {
87
+ /** Unique identifier of the option */
88
+ id: number;
89
+ /** ID of the fleet this option belongs to */
90
+ fleetId: string;
91
+ /** Name of the option */
92
+ name: string;
93
+ /** Type of the option (e.g., "Color", "Gearbox") */
94
+ type: string;
95
+ /** Description of the option */
96
+ description: string;
21
97
  [key: string]: any;
22
98
  };
23
99
  type Zone = {
@@ -133,6 +209,25 @@ declare const getModelsById: (client: Client, id: number) => Promise<Model>;
133
209
 
134
210
  declare const getModels: (client: Client) => Promise<Model[]>;
135
211
 
136
- declare const getVehicleRealTimeById: (client: Client, id: string) => Promise<VehicleRealTime | null>;
212
+ /**
213
+ * Fetches all vehicles from the API using pagination
214
+ * @param client - The AIMA client instance
215
+ * @param pageSize - Number of vehicles per page (default: 500)
216
+ * @returns Promise that resolves to an array of all vehicles
217
+ * @throws Error if more than 50 pages are required to fetch all vehicles
218
+ */
219
+ declare const getVehicles: (client: Client, pageSize?: number) => Promise<Vehicle[]>;
220
+ /**
221
+ * Fetches all real-time vehicle data from the API using pagination
222
+ * @param client - The AIMA client instance
223
+ * @param pageSize - Number of vehicles per page (default: 500)
224
+ * @param lastUpdatedMillis - Optional timestamp in UTC milliseconds. If provided, only vehicles updated after this timestamp will be returned.
225
+ * @returns Promise that resolves to an array of all real-time vehicle data
226
+ * @throws Error if more than 50 pages are required to fetch all vehicles
227
+ * @throws Error if lastUpdatedMillis is in the future
228
+ */
229
+ declare const getVehiclesRealTime: (client: Client, pageSize?: number, lastUpdatedMillis?: number) => Promise<VehicleRealTime[]>;
230
+
231
+ declare const getVehicleById: (client: Client, id: string) => Promise<Vehicle | null>;
137
232
 
138
- export { type Model, getModels, getModelsById, getVehicleRealTimeById };
233
+ export { type Model, type Vehicle, getModels, getModelsById, getVehicleById, getVehicles, getVehiclesRealTime };
package/dist/index.d.ts CHANGED
@@ -1,23 +1,99 @@
1
1
  import { Client } from '@vulog/aima-client';
2
2
 
3
+ /**
4
+ * Represents a vehicle model with its specifications and characteristics
5
+ */
3
6
  type Model = {
7
+ /** Unique identifier of the model */
4
8
  id: number;
9
+ /** Name of the model (e.g., "C-Zero") */
5
10
  name: string;
6
- brand: string;
11
+ /** Type of energy used by the vehicle (e.g., "ELECTRIC") */
7
12
  energyType: string;
13
+ /** Current status of the model (e.g., "ACTIVE") */
8
14
  status: string;
15
+ /** Number of seats in the vehicle */
9
16
  nbOfSeats: number;
17
+ /** Maximum range/autonomy of the vehicle in kilometers */
10
18
  autonomy: number;
19
+ /** Date when the model was created */
11
20
  creationDate: string;
21
+ /** Date when the model was last updated */
12
22
  updateDate: string;
23
+ /** Description of the model (e.g., brand name) */
13
24
  description: string;
25
+ /** ID of the fleet this model belongs to */
14
26
  fleetId: string;
27
+ /** Type of vehicle (e.g., "CAR") */
15
28
  vehicleType: string;
29
+ /** Type of transmission (e.g., "UNDEFINED") */
16
30
  transmission: string;
31
+ /** Range threshold for out of service status */
17
32
  outOfServiceRange: string;
33
+ /** Range threshold for recovery */
18
34
  recoveryRange: string;
19
- incentiveThresholds: [];
35
+ /** Array of incentive thresholds */
36
+ incentiveThresholds: any[];
37
+ /** Range threshold for vehicle redistribution */
20
38
  redistributeVehicleChargedEnoughRange: string;
39
+ /** Indicates if the odometer readings are reliable */
40
+ odometerReliable?: boolean;
41
+ [key: string]: any;
42
+ };
43
+ /**
44
+ * Represents a vehicle in the system
45
+ */
46
+ type Vehicle = {
47
+ /** Unique identifier of the vehicle */
48
+ id: string;
49
+ /** Name of the vehicle */
50
+ name: string;
51
+ /** License plate number */
52
+ plate: string;
53
+ /** Vehicle Identification Number */
54
+ vin: string;
55
+ /** Model information of the vehicle */
56
+ model: Model;
57
+ /** List of options/features installed on the vehicle */
58
+ options: Options[];
59
+ /** Date when the vehicle was created */
60
+ createDate: string;
61
+ /** Date when the vehicle was last updated */
62
+ updateDate: string;
63
+ /** ID of the fleet this vehicle belongs to */
64
+ fleetId: string;
65
+ /** External system identifier */
66
+ externalId: string;
67
+ /** Provider used for vehicle wakeup */
68
+ wakeupProvider?: string;
69
+ /** Mobile Subscriber Integrated Services Digital Network Number */
70
+ msisdn: string;
71
+ /** Integrated Circuit Card Identifier */
72
+ iccid: string;
73
+ /** International Mobile Subscriber Identity */
74
+ imsi?: string;
75
+ /** Whether the vehicle is published in the system */
76
+ published: boolean;
77
+ /** Whether the vehicle has no box installed */
78
+ noBox: boolean;
79
+ /** Whether the vehicle is archived */
80
+ archived: boolean;
81
+ [key: string]: any;
82
+ };
83
+ /**
84
+ * Represents a vehicle option or feature
85
+ */
86
+ type Options = {
87
+ /** Unique identifier of the option */
88
+ id: number;
89
+ /** ID of the fleet this option belongs to */
90
+ fleetId: string;
91
+ /** Name of the option */
92
+ name: string;
93
+ /** Type of the option (e.g., "Color", "Gearbox") */
94
+ type: string;
95
+ /** Description of the option */
96
+ description: string;
21
97
  [key: string]: any;
22
98
  };
23
99
  type Zone = {
@@ -133,6 +209,25 @@ declare const getModelsById: (client: Client, id: number) => Promise<Model>;
133
209
 
134
210
  declare const getModels: (client: Client) => Promise<Model[]>;
135
211
 
136
- declare const getVehicleRealTimeById: (client: Client, id: string) => Promise<VehicleRealTime | null>;
212
+ /**
213
+ * Fetches all vehicles from the API using pagination
214
+ * @param client - The AIMA client instance
215
+ * @param pageSize - Number of vehicles per page (default: 500)
216
+ * @returns Promise that resolves to an array of all vehicles
217
+ * @throws Error if more than 50 pages are required to fetch all vehicles
218
+ */
219
+ declare const getVehicles: (client: Client, pageSize?: number) => Promise<Vehicle[]>;
220
+ /**
221
+ * Fetches all real-time vehicle data from the API using pagination
222
+ * @param client - The AIMA client instance
223
+ * @param pageSize - Number of vehicles per page (default: 500)
224
+ * @param lastUpdatedMillis - Optional timestamp in UTC milliseconds. If provided, only vehicles updated after this timestamp will be returned.
225
+ * @returns Promise that resolves to an array of all real-time vehicle data
226
+ * @throws Error if more than 50 pages are required to fetch all vehicles
227
+ * @throws Error if lastUpdatedMillis is in the future
228
+ */
229
+ declare const getVehiclesRealTime: (client: Client, pageSize?: number, lastUpdatedMillis?: number) => Promise<VehicleRealTime[]>;
230
+
231
+ declare const getVehicleById: (client: Client, id: string) => Promise<Vehicle | null>;
137
232
 
138
- export { type Model, getModels, getModelsById, getVehicleRealTimeById };
233
+ export { type Model, type Vehicle, getModels, getModelsById, getVehicleById, getVehicles, getVehiclesRealTime };
package/dist/index.js CHANGED
@@ -22,7 +22,9 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  getModels: () => getModels,
24
24
  getModelsById: () => getModelsById,
25
- getVehicleRealTimeById: () => getVehicleRealTimeById
25
+ getVehicleById: () => getVehicleById,
26
+ getVehicles: () => getVehicles,
27
+ getVehiclesRealTime: () => getVehiclesRealTime
26
28
  });
27
29
  module.exports = __toCommonJS(index_exports);
28
30
 
@@ -36,21 +38,107 @@ var getModels = async (client) => {
36
38
  return client.get(`boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles/models`).then(({ data }) => data);
37
39
  };
38
40
 
39
- // src/getVehicle.ts
41
+ // src/getVehicles.ts
40
42
  var import_zod = require("zod");
41
- var schema = import_zod.z.object({
42
- id: import_zod.z.string().trim().min(1).uuid()
43
+ var getVehiclesPage = async (client, page, pageSize) => {
44
+ const response = await client.get(
45
+ `boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles?page=${page}&size=${pageSize}`
46
+ );
47
+ return response.data;
48
+ };
49
+ var getVehicles = async (client, pageSize = 500) => {
50
+ const schema2 = import_zod.z.object({
51
+ pageSize: import_zod.z.number().min(1).default(500)
52
+ });
53
+ const result = schema2.safeParse({ pageSize });
54
+ if (!result.success) {
55
+ throw new TypeError("Invalid args", {
56
+ cause: result.error.issues
57
+ });
58
+ }
59
+ const allVehicles = [];
60
+ let currentPage = 0;
61
+ let hasMorePages = true;
62
+ const MAX_PAGES = 50;
63
+ while (hasMorePages) {
64
+ if (currentPage >= MAX_PAGES) {
65
+ throw new Error(
66
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
67
+ );
68
+ }
69
+ const vehicles = await getVehiclesPage(client, currentPage, result.data.pageSize);
70
+ allVehicles.push(...vehicles);
71
+ hasMorePages = vehicles.length === result.data.pageSize;
72
+ currentPage += 1;
73
+ }
74
+ return allVehicles;
75
+ };
76
+ var getVehiclesRealTimePage = async (client, page, pageSize, lastUpdatedMillis) => {
77
+ const queryParams = new URLSearchParams({
78
+ page: page.toString(),
79
+ size: pageSize.toString()
80
+ });
81
+ if (lastUpdatedMillis !== void 0) {
82
+ queryParams.append("lastUpdatedMillis", lastUpdatedMillis.toString());
83
+ }
84
+ const response = await client.get(
85
+ `boapi/proxy/fleetmanager/public/fleets/${client.clientOptions.fleetId}/vehicles?${queryParams.toString()}`
86
+ );
87
+ return response.data;
88
+ };
89
+ var getVehiclesRealTime = async (client, pageSize = 500, lastUpdatedMillis) => {
90
+ const schema2 = import_zod.z.object({
91
+ pageSize: import_zod.z.number().min(1).default(500),
92
+ lastUpdatedMillis: import_zod.z.number().positive().optional()
93
+ });
94
+ const result = schema2.safeParse({ pageSize, lastUpdatedMillis });
95
+ if (!result.success) {
96
+ throw new TypeError("Invalid args", {
97
+ cause: result.error.issues
98
+ });
99
+ }
100
+ const allVehicles = [];
101
+ let currentPage = 0;
102
+ let hasMorePages = true;
103
+ const MAX_PAGES = 50;
104
+ if (lastUpdatedMillis !== void 0) {
105
+ const now = Date.now();
106
+ if (lastUpdatedMillis > now) {
107
+ throw new Error("lastUpdatedMillis must be in the past");
108
+ }
109
+ }
110
+ while (hasMorePages) {
111
+ if (currentPage >= MAX_PAGES) {
112
+ throw new Error(
113
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
114
+ );
115
+ }
116
+ const vehicles = await getVehiclesRealTimePage(
117
+ client,
118
+ currentPage,
119
+ result.data.pageSize,
120
+ result.data.lastUpdatedMillis
121
+ );
122
+ allVehicles.push(...vehicles);
123
+ hasMorePages = vehicles.length === result.data.pageSize;
124
+ currentPage += 1;
125
+ }
126
+ return allVehicles;
127
+ };
128
+
129
+ // src/getVehicle.ts
130
+ var import_zod2 = require("zod");
131
+ var schema = import_zod2.z.object({
132
+ id: import_zod2.z.string().trim().min(1).uuid()
43
133
  });
44
- var getVehicleRealTimeById = async (client, id) => {
134
+ var getVehicleById = async (client, id) => {
45
135
  const result = schema.safeParse({ id });
46
136
  if (!result.success) {
47
137
  throw new TypeError("Invalid args", {
48
138
  cause: result.error.issues
49
139
  });
50
140
  }
51
- return client.get(
52
- `boapi/proxy/fleetmanager/public/fleets/${client.clientOptions.fleetId}/vehicles/${result.data.id}`
53
- ).then(({ data }) => data).catch((error) => {
141
+ return client.get(`boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles/${result.data.id}`).then(({ data }) => data).catch((error) => {
54
142
  if (error.formattedError?.status === 404) {
55
143
  return null;
56
144
  }
@@ -61,5 +149,7 @@ var getVehicleRealTimeById = async (client, id) => {
61
149
  0 && (module.exports = {
62
150
  getModels,
63
151
  getModelsById,
64
- getVehicleRealTimeById
152
+ getVehicleById,
153
+ getVehicles,
154
+ getVehiclesRealTime
65
155
  });
package/dist/index.mjs CHANGED
@@ -8,21 +8,107 @@ var getModels = async (client) => {
8
8
  return client.get(`boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles/models`).then(({ data }) => data);
9
9
  };
10
10
 
11
- // src/getVehicle.ts
11
+ // src/getVehicles.ts
12
12
  import { z } from "zod";
13
- var schema = z.object({
14
- id: z.string().trim().min(1).uuid()
13
+ var getVehiclesPage = async (client, page, pageSize) => {
14
+ const response = await client.get(
15
+ `boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles?page=${page}&size=${pageSize}`
16
+ );
17
+ return response.data;
18
+ };
19
+ var getVehicles = async (client, pageSize = 500) => {
20
+ const schema2 = z.object({
21
+ pageSize: z.number().min(1).default(500)
22
+ });
23
+ const result = schema2.safeParse({ pageSize });
24
+ if (!result.success) {
25
+ throw new TypeError("Invalid args", {
26
+ cause: result.error.issues
27
+ });
28
+ }
29
+ const allVehicles = [];
30
+ let currentPage = 0;
31
+ let hasMorePages = true;
32
+ const MAX_PAGES = 50;
33
+ while (hasMorePages) {
34
+ if (currentPage >= MAX_PAGES) {
35
+ throw new Error(
36
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
37
+ );
38
+ }
39
+ const vehicles = await getVehiclesPage(client, currentPage, result.data.pageSize);
40
+ allVehicles.push(...vehicles);
41
+ hasMorePages = vehicles.length === result.data.pageSize;
42
+ currentPage += 1;
43
+ }
44
+ return allVehicles;
45
+ };
46
+ var getVehiclesRealTimePage = async (client, page, pageSize, lastUpdatedMillis) => {
47
+ const queryParams = new URLSearchParams({
48
+ page: page.toString(),
49
+ size: pageSize.toString()
50
+ });
51
+ if (lastUpdatedMillis !== void 0) {
52
+ queryParams.append("lastUpdatedMillis", lastUpdatedMillis.toString());
53
+ }
54
+ const response = await client.get(
55
+ `boapi/proxy/fleetmanager/public/fleets/${client.clientOptions.fleetId}/vehicles?${queryParams.toString()}`
56
+ );
57
+ return response.data;
58
+ };
59
+ var getVehiclesRealTime = async (client, pageSize = 500, lastUpdatedMillis) => {
60
+ const schema2 = z.object({
61
+ pageSize: z.number().min(1).default(500),
62
+ lastUpdatedMillis: z.number().positive().optional()
63
+ });
64
+ const result = schema2.safeParse({ pageSize, lastUpdatedMillis });
65
+ if (!result.success) {
66
+ throw new TypeError("Invalid args", {
67
+ cause: result.error.issues
68
+ });
69
+ }
70
+ const allVehicles = [];
71
+ let currentPage = 0;
72
+ let hasMorePages = true;
73
+ const MAX_PAGES = 50;
74
+ if (lastUpdatedMillis !== void 0) {
75
+ const now = Date.now();
76
+ if (lastUpdatedMillis > now) {
77
+ throw new Error("lastUpdatedMillis must be in the past");
78
+ }
79
+ }
80
+ while (hasMorePages) {
81
+ if (currentPage >= MAX_PAGES) {
82
+ throw new Error(
83
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
84
+ );
85
+ }
86
+ const vehicles = await getVehiclesRealTimePage(
87
+ client,
88
+ currentPage,
89
+ result.data.pageSize,
90
+ result.data.lastUpdatedMillis
91
+ );
92
+ allVehicles.push(...vehicles);
93
+ hasMorePages = vehicles.length === result.data.pageSize;
94
+ currentPage += 1;
95
+ }
96
+ return allVehicles;
97
+ };
98
+
99
+ // src/getVehicle.ts
100
+ import { z as z2 } from "zod";
101
+ var schema = z2.object({
102
+ id: z2.string().trim().min(1).uuid()
15
103
  });
16
- var getVehicleRealTimeById = async (client, id) => {
104
+ var getVehicleById = async (client, id) => {
17
105
  const result = schema.safeParse({ id });
18
106
  if (!result.success) {
19
107
  throw new TypeError("Invalid args", {
20
108
  cause: result.error.issues
21
109
  });
22
110
  }
23
- return client.get(
24
- `boapi/proxy/fleetmanager/public/fleets/${client.clientOptions.fleetId}/vehicles/${result.data.id}`
25
- ).then(({ data }) => data).catch((error) => {
111
+ return client.get(`boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles/${result.data.id}`).then(({ data }) => data).catch((error) => {
26
112
  if (error.formattedError?.status === 404) {
27
113
  return null;
28
114
  }
@@ -32,5 +118,7 @@ var getVehicleRealTimeById = async (client, id) => {
32
118
  export {
33
119
  getModels,
34
120
  getModelsById,
35
- getVehicleRealTimeById
121
+ getVehicleById,
122
+ getVehicles,
123
+ getVehiclesRealTime
36
124
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulog/aima-vehicle",
3
- "version": "1.1.50",
3
+ "version": "1.1.52",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -19,8 +19,8 @@
19
19
  "author": "Vulog",
20
20
  "license": "ISC",
21
21
  "dependencies": {
22
- "@vulog/aima-client": "1.1.50",
23
- "@vulog/aima-core": "1.1.50"
22
+ "@vulog/aima-client": "1.1.52",
23
+ "@vulog/aima-core": "1.1.52"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "zod": "^3.24.2"
package/src/getVehicle.ts CHANGED
@@ -1,12 +1,30 @@
1
1
  import { Client } from '@vulog/aima-client';
2
2
  import { z } from 'zod';
3
3
 
4
- import { VehicleRealTime } from './types';
4
+ import { Vehicle, VehicleRealTime } from './types';
5
5
 
6
6
  const schema = z.object({
7
7
  id: z.string().trim().min(1).uuid(),
8
8
  });
9
9
 
10
+ export const getVehicleById = async (client: Client, id: string) => {
11
+ const result = schema.safeParse({ id });
12
+ if (!result.success) {
13
+ throw new TypeError('Invalid args', {
14
+ cause: result.error.issues,
15
+ });
16
+ }
17
+ return client
18
+ .get<Vehicle>(`boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles/${result.data.id}`)
19
+ .then(({ data }) => data)
20
+ .catch((error) => {
21
+ if (error.formattedError?.status === 404) {
22
+ return null;
23
+ }
24
+ throw error;
25
+ });
26
+ };
27
+
10
28
  export const getVehicleRealTimeById = async (client: Client, id: string) => {
11
29
  const result = schema.safeParse({ id });
12
30
  if (!result.success) {
@@ -0,0 +1,151 @@
1
+ import { Client } from '@vulog/aima-client';
2
+ import { z } from 'zod';
3
+
4
+ import { Vehicle, VehicleRealTime } from './types';
5
+
6
+ /**
7
+ * Fetches a single page of vehicles from the API
8
+ * @param client - The AIMA client instance
9
+ * @param page - The page number to fetch
10
+ * @param pageSize - Number of vehicles per page
11
+ * @returns Promise that resolves to an array of vehicles for the requested page
12
+ */
13
+ const getVehiclesPage = async (client: Client, page: number, pageSize: number): Promise<Vehicle[]> => {
14
+ const response = await client.get<Vehicle[]>(
15
+ `boapi/proxy/user/vehicle/fleets/${client.clientOptions.fleetId}/vehicles?page=${page}&size=${pageSize}`
16
+ );
17
+ return response.data;
18
+ };
19
+
20
+ /**
21
+ * Fetches all vehicles from the API using pagination
22
+ * @param client - The AIMA client instance
23
+ * @param pageSize - Number of vehicles per page (default: 500)
24
+ * @returns Promise that resolves to an array of all vehicles
25
+ * @throws Error if more than 50 pages are required to fetch all vehicles
26
+ */
27
+ export const getVehicles = async (client: Client, pageSize = 500): Promise<Vehicle[]> => {
28
+ const schema = z.object({
29
+ pageSize: z.number().min(1).default(500),
30
+ });
31
+ const result = schema.safeParse({ pageSize });
32
+ if (!result.success) {
33
+ throw new TypeError('Invalid args', {
34
+ cause: result.error.issues,
35
+ });
36
+ }
37
+ const allVehicles: Vehicle[] = [];
38
+ let currentPage = 0;
39
+ let hasMorePages = true;
40
+ const MAX_PAGES = 50;
41
+
42
+ while (hasMorePages) {
43
+ if (currentPage >= MAX_PAGES) {
44
+ throw new Error(
45
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
46
+ );
47
+ }
48
+
49
+ // eslint-disable-next-line no-await-in-loop -- Pagination requires sequential API calls
50
+ const vehicles = await getVehiclesPage(client, currentPage, result.data.pageSize);
51
+ allVehicles.push(...vehicles);
52
+
53
+ // Stop if we received fewer vehicles than the page size (including 0)
54
+ hasMorePages = vehicles.length === result.data.pageSize;
55
+ currentPage += 1;
56
+ }
57
+
58
+ return allVehicles;
59
+ };
60
+
61
+ /**
62
+ * Fetches a single page of real-time vehicle data from the API
63
+ * @param client - The AIMA client instance
64
+ * @param page - The page number to fetch
65
+ * @param pageSize - Number of vehicles per page
66
+ * @param lastUpdatedMillis - Optional timestamp in UTC milliseconds
67
+ * @returns Promise that resolves to an array of real-time vehicle data for the requested page
68
+ */
69
+ const getVehiclesRealTimePage = async (
70
+ client: Client,
71
+ page: number,
72
+ pageSize: number,
73
+ lastUpdatedMillis?: number
74
+ ): Promise<VehicleRealTime[]> => {
75
+ // Build query parameters
76
+ const queryParams = new URLSearchParams({
77
+ page: page.toString(),
78
+ size: pageSize.toString(),
79
+ });
80
+
81
+ if (lastUpdatedMillis !== undefined) {
82
+ queryParams.append('lastUpdatedMillis', lastUpdatedMillis.toString());
83
+ }
84
+
85
+ // Using the fleetmanager public API endpoint for real-time vehicle data
86
+ const response = await client.get<VehicleRealTime[]>(
87
+ `boapi/proxy/fleetmanager/public/fleets/${client.clientOptions.fleetId}/vehicles?${queryParams.toString()}`
88
+ );
89
+ return response.data;
90
+ };
91
+
92
+ /**
93
+ * Fetches all real-time vehicle data from the API using pagination
94
+ * @param client - The AIMA client instance
95
+ * @param pageSize - Number of vehicles per page (default: 500)
96
+ * @param lastUpdatedMillis - Optional timestamp in UTC milliseconds. If provided, only vehicles updated after this timestamp will be returned.
97
+ * @returns Promise that resolves to an array of all real-time vehicle data
98
+ * @throws Error if more than 50 pages are required to fetch all vehicles
99
+ * @throws Error if lastUpdatedMillis is in the future
100
+ */
101
+ export const getVehiclesRealTime = async (
102
+ client: Client,
103
+ pageSize = 500,
104
+ lastUpdatedMillis?: number
105
+ ): Promise<VehicleRealTime[]> => {
106
+ const schema = z.object({
107
+ pageSize: z.number().min(1).default(500),
108
+ lastUpdatedMillis: z.number().positive().optional(),
109
+ });
110
+ const result = schema.safeParse({ pageSize, lastUpdatedMillis });
111
+ if (!result.success) {
112
+ throw new TypeError('Invalid args', {
113
+ cause: result.error.issues,
114
+ });
115
+ }
116
+ const allVehicles: VehicleRealTime[] = [];
117
+ let currentPage = 0;
118
+ let hasMorePages = true;
119
+ const MAX_PAGES = 50;
120
+
121
+ // Validate lastUpdatedMillis if provided
122
+ if (lastUpdatedMillis !== undefined) {
123
+ const now = Date.now();
124
+ if (lastUpdatedMillis > now) {
125
+ throw new Error('lastUpdatedMillis must be in the past');
126
+ }
127
+ }
128
+
129
+ while (hasMorePages) {
130
+ if (currentPage >= MAX_PAGES) {
131
+ throw new Error(
132
+ `Maximum page limit (${MAX_PAGES}) reached. This might indicate an issue with the pagination or a very large dataset.`
133
+ );
134
+ }
135
+
136
+ // eslint-disable-next-line no-await-in-loop -- Pagination requires sequential API calls
137
+ const vehicles = await getVehiclesRealTimePage(
138
+ client,
139
+ currentPage,
140
+ result.data.pageSize,
141
+ result.data.lastUpdatedMillis
142
+ );
143
+ allVehicles.push(...vehicles);
144
+
145
+ // Stop if we received fewer vehicles than the page size (including 0)
146
+ hasMorePages = vehicles.length === result.data.pageSize;
147
+ currentPage += 1;
148
+ }
149
+
150
+ return allVehicles;
151
+ };
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from './getModel';
2
- export * from './getModels';
3
- export * from './getVehicle';
4
- export type { Model } from './types';
1
+ export { getModelsById } from './getModel';
2
+ export { getModels } from './getModels';
3
+ export { getVehicles, getVehiclesRealTime } from './getVehicles';
4
+ export { getVehicleById } from './getVehicle';
5
+ export type { Model, Vehicle } from './types';
package/src/types.ts CHANGED
@@ -1,21 +1,99 @@
1
+ /**
2
+ * Represents a vehicle model with its specifications and characteristics
3
+ */
1
4
  export type Model = {
5
+ /** Unique identifier of the model */
2
6
  id: number;
7
+ /** Name of the model (e.g., "C-Zero") */
3
8
  name: string;
4
- brand: string;
9
+ /** Type of energy used by the vehicle (e.g., "ELECTRIC") */
5
10
  energyType: string;
11
+ /** Current status of the model (e.g., "ACTIVE") */
6
12
  status: string;
13
+ /** Number of seats in the vehicle */
7
14
  nbOfSeats: number;
15
+ /** Maximum range/autonomy of the vehicle in kilometers */
8
16
  autonomy: number;
17
+ /** Date when the model was created */
9
18
  creationDate: string;
19
+ /** Date when the model was last updated */
10
20
  updateDate: string;
21
+ /** Description of the model (e.g., brand name) */
11
22
  description: string;
23
+ /** ID of the fleet this model belongs to */
12
24
  fleetId: string;
25
+ /** Type of vehicle (e.g., "CAR") */
13
26
  vehicleType: string;
27
+ /** Type of transmission (e.g., "UNDEFINED") */
14
28
  transmission: string;
29
+ /** Range threshold for out of service status */
15
30
  outOfServiceRange: string;
31
+ /** Range threshold for recovery */
16
32
  recoveryRange: string;
17
- incentiveThresholds: [];
33
+ /** Array of incentive thresholds */
34
+ incentiveThresholds: any[];
35
+ /** Range threshold for vehicle redistribution */
18
36
  redistributeVehicleChargedEnoughRange: string;
37
+ /** Indicates if the odometer readings are reliable */
38
+ odometerReliable?: boolean;
39
+ [key: string]: any;
40
+ };
41
+
42
+ /**
43
+ * Represents a vehicle in the system
44
+ */
45
+ export type Vehicle = {
46
+ /** Unique identifier of the vehicle */
47
+ id: string;
48
+ /** Name of the vehicle */
49
+ name: string;
50
+ /** License plate number */
51
+ plate: string;
52
+ /** Vehicle Identification Number */
53
+ vin: string;
54
+ /** Model information of the vehicle */
55
+ model: Model;
56
+ /** List of options/features installed on the vehicle */
57
+ options: Options[];
58
+ /** Date when the vehicle was created */
59
+ createDate: string;
60
+ /** Date when the vehicle was last updated */
61
+ updateDate: string;
62
+ /** ID of the fleet this vehicle belongs to */
63
+ fleetId: string;
64
+ /** External system identifier */
65
+ externalId: string;
66
+ /** Provider used for vehicle wakeup */
67
+ wakeupProvider?: string;
68
+ /** Mobile Subscriber Integrated Services Digital Network Number */
69
+ msisdn: string;
70
+ /** Integrated Circuit Card Identifier */
71
+ iccid: string;
72
+ /** International Mobile Subscriber Identity */
73
+ imsi?: string;
74
+ /** Whether the vehicle is published in the system */
75
+ published: boolean;
76
+ /** Whether the vehicle has no box installed */
77
+ noBox: boolean;
78
+ /** Whether the vehicle is archived */
79
+ archived: boolean;
80
+ [key: string]: any;
81
+ };
82
+
83
+ /**
84
+ * Represents a vehicle option or feature
85
+ */
86
+ export type Options = {
87
+ /** Unique identifier of the option */
88
+ id: number;
89
+ /** ID of the fleet this option belongs to */
90
+ fleetId: string;
91
+ /** Name of the option */
92
+ name: string;
93
+ /** Type of the option (e.g., "Color", "Gearbox") */
94
+ type: string;
95
+ /** Description of the option */
96
+ description: string;
19
97
  [key: string]: any;
20
98
  };
21
99