@teslemetry/api 0.3.0 → 0.5.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.
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import { EventEmitter } from "events";
2
+
1
3
  //#region src/client/core/bodySerializer.gen.ts
2
4
  const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
3
5
 
@@ -790,23 +792,6 @@ const getApiRefreshByVin = (options) => (options.client ?? client).get({
790
792
  ...options
791
793
  });
792
794
  /**
793
- * Vehicle Image
794
- *
795
- * Redirect to the Tesla Design Studio image of a vehicle
796
- */
797
- const getApiImageByVin = (options) => (options.client ?? client).get({
798
- security: [{
799
- scheme: "bearer",
800
- type: "http"
801
- }, {
802
- in: "query",
803
- name: "token",
804
- type: "apiKey"
805
- }],
806
- url: "/api/image/{vin}",
807
- ...options
808
- });
809
- /**
810
795
  * Vehicle Data
811
796
  *
812
797
  * Returns the cached vehicle data for this vehicle. location_data will only be present if you have provided the location_data scope.
@@ -3004,23 +2989,27 @@ const getSseByVin_ = (options) => (options.client ?? client).sse.get({
3004
2989
 
3005
2990
  //#endregion
3006
2991
  //#region src/TeslemetryVehicleStream.ts
3007
- var TeslemetryVehicleStream = class {
2992
+ var TeslemetryVehicleStream = class extends EventEmitter {
3008
2993
  root;
3009
- stream;
3010
2994
  vin;
3011
2995
  fields = {};
3012
2996
  _pendingFields = {};
3013
2997
  _debounceTimeout = null;
3014
2998
  logger;
3015
- constructor(root, stream, vin) {
2999
+ data;
3000
+ constructor(root, vin) {
3001
+ if (root.sse.vehicles.has(vin)) throw new Error("Vehicle already exists");
3002
+ super();
3016
3003
  this.root = root;
3017
- this.stream = stream;
3018
3004
  this.vin = vin;
3019
- this.logger = stream.logger;
3020
- stream.onConfig((event) => {
3005
+ this.logger = root.sse.logger;
3006
+ this.data = new EventEmitter();
3007
+ root.sse.vehicles.set(vin, this);
3008
+ this.on("config", (event) => {
3021
3009
  this.fields = event.config.fields;
3022
- }, { vin: this.vin });
3010
+ });
3023
3011
  }
3012
+ /** Get the current configuration for the vehicle */
3024
3013
  async getConfig() {
3025
3014
  const { data, response } = await getApiConfigByVin({ path: { vin: this.vin } });
3026
3015
  if (response.status === 200 && data) this.fields = data.fields || {};
@@ -3029,7 +3018,8 @@ var TeslemetryVehicleStream = class {
3029
3018
  return;
3030
3019
  } else throw new Error(`Failed to get config: ${response.statusText}`);
3031
3020
  }
3032
- updateFields(fields) {
3021
+ /** Safely add field configuration to the vehicle */
3022
+ async updateFields(fields) {
3033
3023
  this._pendingFields = {
3034
3024
  ...this._pendingFields,
3035
3025
  ...fields
@@ -3048,6 +3038,7 @@ var TeslemetryVehicleStream = class {
3048
3038
  this._debounceTimeout = null;
3049
3039
  }, 100);
3050
3040
  }
3041
+ /** Modify the field configuration of the vehicle */
3051
3042
  async patchConfig(fields) {
3052
3043
  const { data } = await patchApiConfigByVin({
3053
3044
  client: this.root.client,
@@ -3056,6 +3047,7 @@ var TeslemetryVehicleStream = class {
3056
3047
  });
3057
3048
  return data;
3058
3049
  }
3050
+ /** Replace the field configuration of the vehicle */
3059
3051
  async postConfig(fields) {
3060
3052
  const { data } = await postApiConfigByVin({
3061
3053
  client: this.root.client,
@@ -3064,6 +3056,12 @@ var TeslemetryVehicleStream = class {
3064
3056
  });
3065
3057
  return data;
3066
3058
  }
3059
+ /**
3060
+ * Add a field to the vehicles streaming configuration
3061
+ * @param field Vehicle Signal
3062
+ * @param interval
3063
+ * @returns
3064
+ */
3067
3065
  async addField(field, interval) {
3068
3066
  if (this.fields && this.fields[field] && (interval === void 0 || this.fields[field].interval_seconds === interval)) {
3069
3067
  this.logger.debug(`Streaming field ${field} already enabled @ ${this.fields[field]?.interval_seconds || "default"}s`);
@@ -3072,59 +3070,37 @@ var TeslemetryVehicleStream = class {
3072
3070
  const value = interval !== void 0 ? { interval_seconds: interval } : null;
3073
3071
  this.updateFields({ [field]: value });
3074
3072
  }
3075
- onState(callback) {
3076
- return this.stream.onState(callback, { vin: this.vin });
3077
- }
3078
- onData(callback) {
3079
- return this.stream.onData(callback, { vin: this.vin });
3080
- }
3081
- onErrors(callback) {
3082
- return this.stream.onErrors(callback, { vin: this.vin });
3083
- }
3084
- onAlerts(callback) {
3085
- return this.stream.onAlerts(callback, { vin: this.vin });
3086
- }
3087
- onConnectivity(callback) {
3088
- return this.stream.onConnectivity(callback, { vin: this.vin });
3089
- }
3090
- onVehicleData(callback) {
3091
- return this.stream.onVehicleData(callback, { vin: this.vin });
3092
- }
3093
- onConfig(callback) {
3094
- return this.stream.onConfig(callback, { vin: this.vin });
3095
- }
3096
- on(callback) {
3097
- return this.stream.on((event) => {
3098
- callback(event);
3099
- }, { vin: this.vin });
3100
- }
3073
+ /**
3074
+ * Helper to enable and listen for specific field signals
3075
+ * @param field Vehicle field to listen for
3076
+ * @param callback Callback function to handle signals
3077
+ * @returns Off function to stop the listener
3078
+ */
3101
3079
  onSignal(field, callback) {
3102
3080
  this.addField(field).catch((error) => {
3103
3081
  this.logger.error(`Failed to add field ${field}:`, error);
3104
3082
  });
3105
- return this.stream.onData((event) => {
3106
- const value = event.data[field];
3107
- if (value !== void 0) callback(value);
3108
- }, {
3109
- vin: this.vin,
3110
- data: { [field]: null }
3111
- });
3083
+ this.data.on(field, callback);
3084
+ return () => this.data.off(field, callback);
3085
+ }
3086
+ stop() {
3087
+ this.removeAllListeners();
3088
+ this.data.removeAllListeners();
3112
3089
  }
3113
3090
  };
3114
3091
 
3115
3092
  //#endregion
3116
3093
  //#region src/TeslemetryStream.ts
3117
- var TeslemetryStream = class {
3094
+ var TeslemetryStream = class extends EventEmitter {
3118
3095
  root;
3119
3096
  active = false;
3120
3097
  connected = false;
3121
3098
  vin;
3122
3099
  cache;
3123
3100
  logger;
3124
- listeners = /* @__PURE__ */ new Map();
3125
- _connectionListeners = /* @__PURE__ */ new Map();
3126
3101
  vehicles = /* @__PURE__ */ new Map();
3127
3102
  constructor(root, options) {
3103
+ super();
3128
3104
  this.root = root;
3129
3105
  this.vin = options?.vin;
3130
3106
  this.cache = options?.cache;
@@ -3132,7 +3108,7 @@ var TeslemetryStream = class {
3132
3108
  if (this.vin) this.getVehicle(this.vin);
3133
3109
  }
3134
3110
  getVehicle(vin) {
3135
- if (!this.vehicles.has(vin)) this.vehicles.set(vin, new TeslemetryVehicleStream(this.root, this, vin));
3111
+ if (!this.vehicles.has(vin)) new TeslemetryVehicleStream(this.root, vin);
3136
3112
  return this.vehicles.get(vin);
3137
3113
  }
3138
3114
  async connect() {
@@ -3151,7 +3127,7 @@ var TeslemetryStream = class {
3151
3127
  this.logger.info(`Connected to stream`);
3152
3128
  retries = 0;
3153
3129
  this.connected = true;
3154
- this._updateConnectionListeners(true);
3130
+ this.emit("connect");
3155
3131
  if (sse.stream) for await (const event of sse.stream) {
3156
3132
  if (!this.active) break;
3157
3133
  this._dispatch(event);
@@ -3160,13 +3136,13 @@ var TeslemetryStream = class {
3160
3136
  if (!this.active) break;
3161
3137
  this.logger.error("SSE error:", error);
3162
3138
  this.connected = false;
3163
- this._updateConnectionListeners(false);
3139
+ this.emit("disconnect");
3164
3140
  retries++;
3165
3141
  const delay = Math.min(2 ** retries, 600) * 1e3;
3166
3142
  this.logger.info(`Reconnecting in ${delay / 1e3} seconds...`);
3167
3143
  await new Promise((resolve) => setTimeout(resolve, delay));
3168
3144
  }
3169
- this._updateConnectionListeners(false);
3145
+ this.emit("disconnect");
3170
3146
  }
3171
3147
  disconnect() {
3172
3148
  this.active = false;
@@ -3175,99 +3151,37 @@ var TeslemetryStream = class {
3175
3151
  close() {
3176
3152
  this.active = false;
3177
3153
  this.logger.info(`Disconnecting from stream`);
3178
- this._updateConnectionListeners(false);
3179
- }
3180
- onConnection(callback) {
3181
- const removeListener = () => {
3182
- this._connectionListeners.delete(removeListener);
3183
- };
3184
- this._connectionListeners.set(removeListener, callback);
3185
- return removeListener;
3186
- }
3187
- onState(callback, filters) {
3188
- return this._createListener("state", callback, filters);
3189
- }
3190
- onData(callback, filters) {
3191
- return this._createListener("data", callback, filters);
3192
- }
3193
- onErrors(callback, filters) {
3194
- return this._createListener("errors", callback, filters);
3195
- }
3196
- onAlerts(callback, filters) {
3197
- return this._createListener("alerts", callback, filters);
3198
- }
3199
- onConnectivity(callback, filters) {
3200
- return this._createListener("connectivity", callback, filters);
3201
- }
3202
- onCredits(callback, filters) {
3203
- return this._createListener("credits", callback, filters);
3204
3154
  }
3205
- onVehicleData(callback, filters) {
3206
- return this._createListener("vehicle_data", callback, filters);
3207
- }
3208
- onConfig(callback, filters) {
3209
- return this._createListener("config", callback, filters);
3210
- }
3211
- on(callback, filters) {
3212
- return this._createListener("all", callback, filters);
3213
- }
3214
- _updateConnectionListeners(value) {
3215
- for (const listener of this._connectionListeners.values()) listener(value);
3216
- }
3217
- _createListener(eventType, callback, filters) {
3218
- const entry = {
3219
- callback,
3220
- filters
3221
- };
3222
- if (!this.listeners.has(eventType)) this.listeners.set(eventType, /* @__PURE__ */ new Set());
3223
- this.listeners.get(eventType).add(entry);
3224
- return () => {
3225
- const set = this.listeners.get(eventType);
3226
- if (set) {
3227
- set.delete(entry);
3228
- if (set.size === 0) this.listeners.delete(eventType);
3229
- }
3230
- };
3155
+ parseCreatedAt(event) {
3156
+ const [main, ns] = event.createdAt.split(".");
3157
+ const date = /* @__PURE__ */ new Date(main + "Z");
3158
+ return new Date(date.getTime() + parseInt((ns || "000").substring(0, 3)));
3231
3159
  }
3232
3160
  _dispatch(event) {
3233
- if (event.createdAt && !event.timestamp) {
3234
- const [main, ns] = event.createdAt.split(".");
3235
- event.timestamp = (/* @__PURE__ */ new Date(main + "Z")).getTime() + parseInt((ns || "000").substring(0, 3));
3236
- }
3237
- const allListeners = this.listeners.get("all");
3238
- if (allListeners) {
3239
- for (const entry of allListeners) if (recursiveMatch(entry.filters, event)) entry.callback(event);
3240
- }
3241
- let eventType;
3242
- if ("state" in event) eventType = "state";
3243
- else if ("data" in event) eventType = "data";
3244
- else if ("errors" in event) eventType = "errors";
3245
- else if ("alerts" in event) eventType = "alerts";
3246
- else if ("networkInterface" in event) eventType = "connectivity";
3247
- else if ("credits" in event) eventType = "credits";
3248
- else if ("vehicle_data" in event) eventType = "vehicle_data";
3249
- else if ("config" in event) eventType = "config";
3250
- if (eventType) {
3251
- const set = this.listeners.get(eventType);
3252
- if (set) {
3253
- for (const entry of set) if (recursiveMatch(entry.filters, event)) entry.callback(event);
3254
- }
3161
+ if ("state" in event) this.emit("state", event);
3162
+ else if ("data" in event) this.emit("data", event);
3163
+ else if ("errors" in event) this.emit("errors", event);
3164
+ else if ("alerts" in event) this.emit("alerts", event);
3165
+ else if ("networkInterface" in event) this.emit("connectivity", event);
3166
+ else if ("credits" in event) this.emit("credits", event);
3167
+ else if ("vehicle_data" in event) this.emit("vehicle_data", event);
3168
+ else if ("config" in event) this.emit("config", event);
3169
+ const vehicle = this.vehicles.get(event.vin);
3170
+ if (vehicle) {
3171
+ if ("state" in event) vehicle.emit("state", event);
3172
+ else if ("data" in event) {
3173
+ vehicle.emit("data", event);
3174
+ Object.keys(event.data).forEach((key) => {
3175
+ if (event.data[key] !== void 0) vehicle.data.emit(key, event.data[key]);
3176
+ });
3177
+ } else if ("errors" in event) vehicle.emit("errors", event);
3178
+ else if ("alerts" in event) vehicle.emit("alerts", event);
3179
+ else if ("networkInterface" in event) vehicle.emit("connectivity", event);
3180
+ else if ("vehicle_data" in event) vehicle.emit("vehicle_data", event);
3181
+ else if ("config" in event) vehicle.emit("config", event);
3255
3182
  }
3256
3183
  }
3257
3184
  };
3258
- function recursiveMatch(filter, event) {
3259
- if (filter === null || filter === void 0) return true;
3260
- if (typeof filter !== "object" || filter === null || typeof event !== "object" || event === null) return filter === event;
3261
- if (Array.isArray(filter)) {
3262
- if (!Array.isArray(event)) return false;
3263
- return filter.some((fItem) => event.some((eItem) => recursiveMatch(fItem, eItem)));
3264
- }
3265
- for (const key in filter) {
3266
- if (!(key in event)) return false;
3267
- if (!recursiveMatch(filter[key], event[key])) return false;
3268
- }
3269
- return true;
3270
- }
3271
3185
 
3272
3186
  //#endregion
3273
3187
  //#region src/TeslemetryChargingApi.ts
@@ -3328,12 +3242,24 @@ var TeslemetryChargingApi = class {
3328
3242
 
3329
3243
  //#endregion
3330
3244
  //#region src/TeslemetryEnergyApi.ts
3331
- var TeslemetryEnergyApi = class {
3245
+ var TeslemetryEnergyApi = class extends EventEmitter {
3332
3246
  root;
3333
3247
  siteId;
3248
+ refreshDelay = 3e4;
3249
+ refreshInterval = {
3250
+ siteInfo: null,
3251
+ liveStatus: null
3252
+ };
3253
+ refreshClients = {
3254
+ siteInfo: /* @__PURE__ */ new Set(),
3255
+ liveStatus: /* @__PURE__ */ new Set()
3256
+ };
3334
3257
  constructor(root, siteId) {
3258
+ if (root.api.energySites.has(siteId)) throw new Error("Energy site already exists");
3259
+ super();
3335
3260
  this.root = root;
3336
3261
  this.siteId = siteId;
3262
+ root.api.energySites.set(siteId, this);
3337
3263
  }
3338
3264
  /**
3339
3265
  * Adjust the site's backup reserve.
@@ -3395,6 +3321,7 @@ var TeslemetryEnergyApi = class {
3395
3321
  path: { id: this.siteId },
3396
3322
  client: this.root.client
3397
3323
  });
3324
+ this.emit("liveStatus", data);
3398
3325
  return data;
3399
3326
  }
3400
3327
  /**
@@ -3406,6 +3333,7 @@ var TeslemetryEnergyApi = class {
3406
3333
  path: { id: this.siteId },
3407
3334
  client: this.root.client
3408
3335
  });
3336
+ this.emit("siteInfo", data);
3409
3337
  return data;
3410
3338
  }
3411
3339
  /**
@@ -3467,6 +3395,34 @@ var TeslemetryEnergyApi = class {
3467
3395
  });
3468
3396
  return data;
3469
3397
  }
3398
+ requestPolling(endpoint) {
3399
+ if (!this.refreshInterval[endpoint]) switch (endpoint) {
3400
+ case "siteInfo":
3401
+ this.refreshInterval[endpoint] = setInterval(() => {
3402
+ this.getSiteInfo();
3403
+ }, this.refreshDelay);
3404
+ this.getSiteInfo();
3405
+ break;
3406
+ case "liveStatus":
3407
+ this.refreshInterval[endpoint] = setInterval(() => {
3408
+ this.getLiveStatus();
3409
+ }, this.refreshDelay);
3410
+ this.getLiveStatus();
3411
+ break;
3412
+ default: throw new Error(`Invalid endpoint: ${endpoint}`);
3413
+ }
3414
+ const symbol = Symbol("refreshClient");
3415
+ this.refreshClients[endpoint].add(symbol);
3416
+ return () => {
3417
+ this.refreshClients[endpoint].delete(symbol);
3418
+ if (this.refreshClients[endpoint].size === 0) {
3419
+ if (this.refreshInterval[endpoint]) {
3420
+ clearInterval(this.refreshInterval[endpoint]);
3421
+ this.refreshInterval[endpoint] = null;
3422
+ }
3423
+ }
3424
+ };
3425
+ }
3470
3426
  };
3471
3427
 
3472
3428
  //#endregion
@@ -3538,12 +3494,15 @@ const ALL_SEATS = {
3538
3494
  7: 7,
3539
3495
  8: 8
3540
3496
  };
3541
- var TeslemetryVehicleApi = class {
3497
+ var TeslemetryVehicleApi = class extends EventEmitter {
3542
3498
  root;
3543
3499
  vin;
3544
3500
  constructor(root, vin) {
3501
+ if (root.api.vehicles.has(vin)) throw new Error("Vehicle already exists");
3502
+ super();
3545
3503
  this.root = root;
3546
3504
  this.vin = vin;
3505
+ root.api.vehicles.set(vin, this);
3547
3506
  }
3548
3507
  /**
3549
3508
  * Data about the vehicle.
@@ -3554,6 +3513,7 @@ var TeslemetryVehicleApi = class {
3554
3513
  path: { vin: this.vin },
3555
3514
  client: this.root.client
3556
3515
  });
3516
+ this.emit("state", data);
3557
3517
  return data;
3558
3518
  }
3559
3519
  /**
@@ -3571,6 +3531,7 @@ var TeslemetryVehicleApi = class {
3571
3531
  path: { vin: this.vin },
3572
3532
  client: this.root.client
3573
3533
  });
3534
+ this.emit("vehicleData", data);
3574
3535
  return data;
3575
3536
  }
3576
3537
  /**
@@ -3585,17 +3546,6 @@ var TeslemetryVehicleApi = class {
3585
3546
  return data;
3586
3547
  }
3587
3548
  /**
3588
- * Redirect to the Tesla Design Studio image of a vehicle
3589
- * @return Promise to an object with response containing redirect information
3590
- */
3591
- async getImage() {
3592
- const { data } = await getApiImageByVin({
3593
- path: { vin: this.vin },
3594
- client: this.root.client
3595
- });
3596
- return data;
3597
- }
3598
- /**
3599
3549
  * Get the saved vehicle config.
3600
3550
  * @return Promise to an object with response containing the vehicle configuration
3601
3551
  */
@@ -3604,6 +3554,7 @@ var TeslemetryVehicleApi = class {
3604
3554
  path: { vin: this.vin },
3605
3555
  client: this.root.client
3606
3556
  });
3557
+ this.emit("vehicleConfig", data);
3607
3558
  return data;
3608
3559
  }
3609
3560
  /**
@@ -3615,6 +3566,7 @@ var TeslemetryVehicleApi = class {
3615
3566
  path: { vin: this.vin },
3616
3567
  client: this.root.client
3617
3568
  });
3569
+ this.emit("config", data);
3618
3570
  return data;
3619
3571
  }
3620
3572
  /**
@@ -3663,6 +3615,7 @@ var TeslemetryVehicleApi = class {
3663
3615
  path: { vin: this.vin },
3664
3616
  client: this.root.client
3665
3617
  });
3618
+ this.emit("mobileEnabled", data);
3666
3619
  return data;
3667
3620
  }
3668
3621
  /**
@@ -3674,6 +3627,7 @@ var TeslemetryVehicleApi = class {
3674
3627
  path: { vin: this.vin },
3675
3628
  client: this.root.client
3676
3629
  });
3630
+ this.emit("nearbyChargingSites", data);
3677
3631
  return data;
3678
3632
  }
3679
3633
  /**
@@ -3685,6 +3639,7 @@ var TeslemetryVehicleApi = class {
3685
3639
  path: { vin: this.vin },
3686
3640
  client: this.root.client
3687
3641
  });
3642
+ this.emit("recentAlerts", data);
3688
3643
  return data;
3689
3644
  }
3690
3645
  /**
@@ -3696,6 +3651,7 @@ var TeslemetryVehicleApi = class {
3696
3651
  path: { vin: this.vin },
3697
3652
  client: this.root.client
3698
3653
  });
3654
+ this.emit("releaseNotes", data);
3699
3655
  return data;
3700
3656
  }
3701
3657
  /**
@@ -3707,6 +3663,7 @@ var TeslemetryVehicleApi = class {
3707
3663
  path: { vin: this.vin },
3708
3664
  client: this.root.client
3709
3665
  });
3666
+ this.emit("serviceData", data);
3710
3667
  return data;
3711
3668
  }
3712
3669
  /**
@@ -3740,6 +3697,7 @@ var TeslemetryVehicleApi = class {
3740
3697
  path: { vin: this.vin },
3741
3698
  client: this.root.client
3742
3699
  });
3700
+ this.emit("fleetTelemetryConfig", data);
3743
3701
  return data;
3744
3702
  }
3745
3703
  /**
@@ -3762,6 +3720,7 @@ var TeslemetryVehicleApi = class {
3762
3720
  path: { vin: this.vin },
3763
3721
  client: this.root.client
3764
3722
  });
3723
+ this.emit("fleetTelemetryErrors", data);
3765
3724
  return data;
3766
3725
  }
3767
3726
  /**
@@ -4626,6 +4585,7 @@ var TeslemetryVehicleApi = class {
4626
4585
  path: { vin: this.vin },
4627
4586
  client: this.root.client
4628
4587
  });
4588
+ this.emit("drivers", data);
4629
4589
  return data;
4630
4590
  }
4631
4591
  /**
@@ -4650,6 +4610,7 @@ var TeslemetryVehicleApi = class {
4650
4610
  path: { vin: this.vin },
4651
4611
  client: this.root.client
4652
4612
  });
4613
+ this.emit("invitations", data);
4653
4614
  return data;
4654
4615
  }
4655
4616
  /**
@@ -4864,8 +4825,8 @@ var TeslemetryVehicleApi = class {
4864
4825
  //#region src/TeslemetryApi.ts
4865
4826
  var TeslemetryApi = class {
4866
4827
  root;
4867
- _vehicles = {};
4868
- _energySites = {};
4828
+ vehicles = /* @__PURE__ */ new Map();
4829
+ energySites = /* @__PURE__ */ new Map();
4869
4830
  user;
4870
4831
  charging;
4871
4832
  constructor(root) {
@@ -4879,8 +4840,8 @@ var TeslemetryApi = class {
4879
4840
  * @returns The vehicle API instance for the specified VIN.
4880
4841
  */
4881
4842
  getVehicle(vin) {
4882
- if (!this._vehicles[vin]) this._vehicles[vin] = new TeslemetryVehicleApi(this.root, vin);
4883
- return this._vehicles[vin];
4843
+ if (!this.vehicles.has(vin)) new TeslemetryVehicleApi(this.root, vin);
4844
+ return this.vehicles.get(vin);
4884
4845
  }
4885
4846
  /**
4886
4847
  * Gets or creates an energy site API instance for the specified ID.
@@ -4888,8 +4849,8 @@ var TeslemetryApi = class {
4888
4849
  * @returns The energy site API instance for the specified ID.
4889
4850
  */
4890
4851
  getEnergySite(id) {
4891
- if (!this._energySites[id]) this._energySites[id] = new TeslemetryEnergyApi(this.root, id);
4892
- return this._energySites[id];
4852
+ if (!this.energySites.has(id)) new TeslemetryEnergyApi(this.root, id);
4853
+ return this.energySites.get(id);
4893
4854
  }
4894
4855
  /**
4895
4856
  * Creates API instances for all products (vehicles and energy sites) associated with the account.
@@ -4902,11 +4863,11 @@ var TeslemetryApi = class {
4902
4863
  if (product.device_type === "energy") this.getEnergySite(product.energy_site_id);
4903
4864
  });
4904
4865
  return {
4905
- vehicles: this._vehicles,
4906
- energySites: this._energySites
4866
+ vehicles: this.vehicles,
4867
+ energySites: this.energySites
4907
4868
  };
4908
4869
  }
4909
- async fields() {
4870
+ async getFields() {
4910
4871
  const { data } = await getFieldsJson({ client: this.root.client });
4911
4872
  return data;
4912
4873
  }
@@ -4915,7 +4876,7 @@ var TeslemetryApi = class {
4915
4876
  * @returns A promise that resolves to an object containing a `response` array and count.
4916
4877
  * Each item in the array is a product, which can be a vehicle or an energy site, and a `count` of the products.
4917
4878
  */
4918
- async products() {
4879
+ async getProducts() {
4919
4880
  const { data } = await getApi1Products({ client: this.root.client });
4920
4881
  return data;
4921
4882
  }
@@ -4932,7 +4893,7 @@ var TeslemetryApi = class {
4932
4893
  * @returns Promise to an object containing metadata about the account,
4933
4894
  * including user UID, region, scopes, and lists of vehicles and energy sites.
4934
4895
  */
4935
- async metadata() {
4896
+ async getMetadata() {
4936
4897
  const { data } = await getApiMetadata({ client: this.root.client });
4937
4898
  return data;
4938
4899
  }
@@ -4942,7 +4903,7 @@ var TeslemetryApi = class {
4942
4903
  * @returns Promise to an object containing lists of paired and unpaired VINs,
4943
4904
  * and detailed info for each vehicle.
4944
4905
  */
4945
- async fleetStatus(vins) {
4906
+ async getFleetStatus(vins) {
4946
4907
  const { data } = await postApi1VehiclesFleetStatus({
4947
4908
  body: { vins },
4948
4909
  client: this.root.client
@@ -4954,7 +4915,7 @@ var TeslemetryApi = class {
4954
4915
  * @returns Promise to an object containing a list of vehicles,
4955
4916
  * pagination details, and a total count.
4956
4917
  */
4957
- async vehicles() {
4918
+ async getVehicles() {
4958
4919
  const { data } = await getApi1Vehicles({ client: this.root.client });
4959
4920
  return data;
4960
4921
  }
@@ -4983,7 +4944,7 @@ const consoleLogger = {
4983
4944
 
4984
4945
  //#endregion
4985
4946
  //#region package.json
4986
- var version = "0.3.0";
4947
+ var version = "0.5.0";
4987
4948
 
4988
4949
  //#endregion
4989
4950
  //#region src/Teslemetry.ts
@@ -5044,27 +5005,25 @@ var Teslemetry = class {
5044
5005
  * @returns A promise that resolves to an object containing vehicle and energy site names, API, and SSE instances.
5045
5006
  */
5046
5007
  async createProducts() {
5047
- const { data } = await getApi1Products({ client: this.client });
5048
- const result = {
5049
- vehicles: {},
5050
- energySites: {}
5008
+ const { data } = await getApiMetadata({ client: this.client });
5009
+ return {
5010
+ vehicles: Object.fromEntries(Object.entries(data.vehicles).map(([vin, metadata]) => [vin, {
5011
+ name: metadata.name ?? useTeslaModel(vin),
5012
+ vin,
5013
+ api: this.api.getVehicle(vin),
5014
+ sse: this.sse.getVehicle(vin),
5015
+ metadata
5016
+ }])),
5017
+ energySites: Object.fromEntries(Object.entries(data.energy_sites ?? {}).map(([id, metadata]) => {
5018
+ const siteId = Number(id);
5019
+ return [id, {
5020
+ name: metadata.name ?? "Unnamed",
5021
+ id: siteId,
5022
+ api: this.api.getEnergySite(siteId),
5023
+ metadata
5024
+ }];
5025
+ }))
5051
5026
  };
5052
- data.response?.forEach((product) => {
5053
- if (product.device_type === "vehicle") result.vehicles[product.vin] = {
5054
- name: product.display_name ?? useTeslaModel(product.vin),
5055
- vin: product.vin,
5056
- api: this.api.getVehicle(product.vin),
5057
- sse: this.sse.getVehicle(product.vin),
5058
- product
5059
- };
5060
- if (product.device_type === "energy") result.energySites[product.energy_site_id] = {
5061
- name: product.site_name ?? "Unnamed",
5062
- site: product.energy_site_id,
5063
- api: this.api.getEnergySite(product.energy_site_id),
5064
- product
5065
- };
5066
- });
5067
- return result;
5068
5027
  }
5069
5028
  /**
5070
5029
  * Get a vehicle API instance for the specified VIN.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teslemetry/api",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "API client for Teslemetry",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",