@mxpicture/tesla-superchargers-mate 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/TeslaClient.d.ts +49 -0
- package/dist/client/TeslaClient.d.ts.map +1 -0
- package/dist/client/TeslaClient.js +81 -0
- package/dist/client/TeslaClient.js.map +1 -0
- package/dist/client/chargers.clients.d.ts +188 -0
- package/dist/client/chargers.clients.d.ts.map +1 -0
- package/dist/client/chargers.clients.js +114 -0
- package/dist/client/chargers.clients.js.map +1 -0
- package/dist/client/common.clients.d.ts +34 -0
- package/dist/client/common.clients.d.ts.map +1 -0
- package/dist/client/common.clients.js +129 -0
- package/dist/client/common.clients.js.map +1 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/slugs.clients.d.ts +48 -0
- package/dist/client/slugs.clients.d.ts.map +1 -0
- package/dist/client/slugs.clients.js +57 -0
- package/dist/client/slugs.clients.js.map +1 -0
- package/dist/common/coordinates.d.ts +31 -0
- package/dist/common/coordinates.d.ts.map +1 -0
- package/dist/common/coordinates.js +44 -0
- package/dist/common/coordinates.js.map +1 -0
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +3 -0
- package/dist/common/index.js.map +1 -0
- package/dist/store/ChargingProcessesStore.d.ts +34 -0
- package/dist/store/ChargingProcessesStore.d.ts.map +1 -0
- package/dist/store/ChargingProcessesStore.js +90 -0
- package/dist/store/ChargingProcessesStore.js.map +1 -0
- package/dist/store/GeofencesStore.d.ts +20 -0
- package/dist/store/GeofencesStore.d.ts.map +1 -0
- package/dist/store/GeofencesStore.js +28 -0
- package/dist/store/GeofencesStore.js.map +1 -0
- package/dist/store/IFailableStore.d.ts +29 -0
- package/dist/store/IFailableStore.d.ts.map +1 -0
- package/dist/store/IFailableStore.js +47 -0
- package/dist/store/IFailableStore.js.map +1 -0
- package/dist/store/IMateStore.d.ts +66 -0
- package/dist/store/IMateStore.d.ts.map +1 -0
- package/dist/store/IMateStore.js +132 -0
- package/dist/store/IMateStore.js.map +1 -0
- package/dist/store/PicChargersStore.d.ts +17 -0
- package/dist/store/PicChargersStore.d.ts.map +1 -0
- package/dist/store/PicChargersStore.js +34 -0
- package/dist/store/PicChargersStore.js.map +1 -0
- package/dist/store/PicPricebooksStore.d.ts +27 -0
- package/dist/store/PicPricebooksStore.d.ts.map +1 -0
- package/dist/store/PicPricebooksStore.js +57 -0
- package/dist/store/PicPricebooksStore.js.map +1 -0
- package/dist/store/PicSlugsStore.d.ts +18 -0
- package/dist/store/PicSlugsStore.d.ts.map +1 -0
- package/dist/store/PicSlugsStore.js +34 -0
- package/dist/store/PicSlugsStore.js.map +1 -0
- package/dist/store/db.d.ts +15 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +26 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/index.d.ts +10 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +11 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/statements.d.ts +14 -0
- package/dist/store/statements.d.ts.map +1 -0
- package/dist/store/statements.js +30 -0
- package/dist/store/statements.js.map +1 -0
- package/dist/transform/chargers.transform.d.ts +9 -0
- package/dist/transform/chargers.transform.d.ts.map +1 -0
- package/dist/transform/chargers.transform.js +42 -0
- package/dist/transform/chargers.transform.js.map +1 -0
- package/dist/transform/common.transform.d.ts +19 -0
- package/dist/transform/common.transform.d.ts.map +1 -0
- package/dist/transform/common.transform.js +72 -0
- package/dist/transform/common.transform.js.map +1 -0
- package/dist/transform/index.d.ts +5 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +6 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/transform/pricebooks.transform.d.ts +9 -0
- package/dist/transform/pricebooks.transform.d.ts.map +1 -0
- package/dist/transform/pricebooks.transform.js +24 -0
- package/dist/transform/pricebooks.transform.js.map +1 -0
- package/dist/transform/slugs.transform.d.ts +9 -0
- package/dist/transform/slugs.transform.d.ts.map +1 -0
- package/dist/transform/slugs.transform.js +29 -0
- package/dist/transform/slugs.transform.js.map +1 -0
- package/dist/types/charger.types.d.ts +5 -0
- package/dist/types/charger.types.d.ts.map +1 -0
- package/dist/types/charger.types.js +2 -0
- package/dist/types/charger.types.js.map +1 -0
- package/dist/types/chargingProcess.types.d.ts +21 -0
- package/dist/types/chargingProcess.types.d.ts.map +1 -0
- package/dist/types/chargingProcess.types.js +2 -0
- package/dist/types/chargingProcess.types.js.map +1 -0
- package/dist/types/client.types.d.ts +14 -0
- package/dist/types/client.types.d.ts.map +1 -0
- package/dist/types/client.types.js +2 -0
- package/dist/types/client.types.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/slug.types.d.ts +5 -0
- package/dist/types/slug.types.d.ts.map +1 -0
- package/dist/types/slug.types.js +2 -0
- package/dist/types/slug.types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull ALL Tesla Supercharger locations + pricing using two PUBLIC,
|
|
3
|
+
* UNAUTHENTICATED tesla.com endpoints. No Fleet API, no OAuth token, no account.
|
|
4
|
+
*
|
|
5
|
+
* 1) ENUMERATE -> https://www.tesla.com/all-locations
|
|
6
|
+
* Every Tesla location worldwide as one JSON array (no pricing).
|
|
7
|
+
* 2) CHARGERS -> https://www.tesla.com/api/findus/get-charger-details
|
|
8
|
+
* Per-site details INCLUDING pricing ("effectivePricebooks").
|
|
9
|
+
*
|
|
10
|
+
* Both endpoints are public but sit behind Akamai bot protection, and Akamai
|
|
11
|
+
* now treats them differently, so the transport is split:
|
|
12
|
+
* 1. `/all-locations` is a FINGERPRINT-only gate. It clears from any IP as
|
|
13
|
+
* long as the request presents a real browser TLS/HTTP-2 fingerprint, so
|
|
14
|
+
* in prod we issue it via curl-impersonate (`SUPERCHARGERS_CURL_BIN`, e.g.
|
|
15
|
+
* `curl_chrome110`). No proxy is used. The impersonate binary also brings
|
|
16
|
+
* its own complete browser header set, so when it is NOT plain `curl` we do
|
|
17
|
+
* NOT add our hand-rolled headers (doing so breaks the impersonation).
|
|
18
|
+
* 2. `get-charger-details` additionally enforces a JS-sensor challenge that a
|
|
19
|
+
* raw fingerprint cannot satisfy. It needs a rendering unblocker: set
|
|
20
|
+
* `SUPERCHARGERS_CHARGERS_PROXY` to a BrightData Web Unlocker URL and ONLY
|
|
21
|
+
* this route is sent through it, via plain system `curl` (the unblocker
|
|
22
|
+
* owns the fingerprint and MITMs TLS, so we use `--proxy` + `-k`).
|
|
23
|
+
* The configured curl binary must be present on PATH at runtime.
|
|
24
|
+
* The `get-charger-details` slug also fuzzy/prefix-matches, so we try a couple
|
|
25
|
+
* of slug candidates and validate the returned city.
|
|
26
|
+
*
|
|
27
|
+
* The functions return data (and throw on hard failures) instead of writing
|
|
28
|
+
* files / calling `process.exit`, so the CLI and stores can own I/O.
|
|
29
|
+
*/
|
|
30
|
+
import { type TeslaClientCharger } from "./chargers.clients.js";
|
|
31
|
+
import { type TeslaClientSlug } from "./slugs.clients.js";
|
|
32
|
+
export declare class TeslaClient {
|
|
33
|
+
constructor();
|
|
34
|
+
/**
|
|
35
|
+
* Fetch the map UI's location feed (`get-locations?view=map`), the source of the
|
|
36
|
+
* canonical `location_url_slug` per site. Like `get-charger-details` (and unlike `/all-locations`) this
|
|
37
|
+
* `/api/findus/` route sits behind Akamai's JS-sensor challenge, so it needs the
|
|
38
|
+
* rendering unblocker: routed through `SUPERCHARGERS_CHARGERS_PROXY` via plain
|
|
39
|
+
* `curl` when set.
|
|
40
|
+
*/
|
|
41
|
+
fetchSlugs(): Promise<TeslaClientSlug[]>;
|
|
42
|
+
fetchCharger(slug: string, locale: string): Promise<{
|
|
43
|
+
charger: TeslaClientCharger | null;
|
|
44
|
+
reason?: string;
|
|
45
|
+
attempts: number;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
export declare const teslaClient: () => TeslaClient;
|
|
49
|
+
//# sourceMappingURL=TeslaClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TeslaClient.d.ts","sourceRoot":"","sources":["../../src/client/TeslaClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AASH,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,oBAAoB,CAAC;AAE5B,qBAAa,WAAW;;IAGtB;;;;;;OAMG;IACU,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAyBxC,YAAY,CACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QACT,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;QACnC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CAkCH;AAGD,eAAO,MAAM,WAAW,mBAAwC,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull ALL Tesla Supercharger locations + pricing using two PUBLIC,
|
|
3
|
+
* UNAUTHENTICATED tesla.com endpoints. No Fleet API, no OAuth token, no account.
|
|
4
|
+
*
|
|
5
|
+
* 1) ENUMERATE -> https://www.tesla.com/all-locations
|
|
6
|
+
* Every Tesla location worldwide as one JSON array (no pricing).
|
|
7
|
+
* 2) CHARGERS -> https://www.tesla.com/api/findus/get-charger-details
|
|
8
|
+
* Per-site details INCLUDING pricing ("effectivePricebooks").
|
|
9
|
+
*
|
|
10
|
+
* Both endpoints are public but sit behind Akamai bot protection, and Akamai
|
|
11
|
+
* now treats them differently, so the transport is split:
|
|
12
|
+
* 1. `/all-locations` is a FINGERPRINT-only gate. It clears from any IP as
|
|
13
|
+
* long as the request presents a real browser TLS/HTTP-2 fingerprint, so
|
|
14
|
+
* in prod we issue it via curl-impersonate (`SUPERCHARGERS_CURL_BIN`, e.g.
|
|
15
|
+
* `curl_chrome110`). No proxy is used. The impersonate binary also brings
|
|
16
|
+
* its own complete browser header set, so when it is NOT plain `curl` we do
|
|
17
|
+
* NOT add our hand-rolled headers (doing so breaks the impersonation).
|
|
18
|
+
* 2. `get-charger-details` additionally enforces a JS-sensor challenge that a
|
|
19
|
+
* raw fingerprint cannot satisfy. It needs a rendering unblocker: set
|
|
20
|
+
* `SUPERCHARGERS_CHARGERS_PROXY` to a BrightData Web Unlocker URL and ONLY
|
|
21
|
+
* this route is sent through it, via plain system `curl` (the unblocker
|
|
22
|
+
* owns the fingerprint and MITMs TLS, so we use `--proxy` + `-k`).
|
|
23
|
+
* The configured curl binary must be present on PATH at runtime.
|
|
24
|
+
* The `get-charger-details` slug also fuzzy/prefix-matches, so we try a couple
|
|
25
|
+
* of slug candidates and validate the returned city.
|
|
26
|
+
*
|
|
27
|
+
* The functions return data (and throw on hard failures) instead of writing
|
|
28
|
+
* files / calling `process.exit`, so the CLI and stores can own I/O.
|
|
29
|
+
*/
|
|
30
|
+
import { CHARGERS_HEADERS, CHARGERS_URL, getJson, SLUGS_URL, } from "./common.clients.js";
|
|
31
|
+
import { teslaClientChargerResponseSchema, } from "./chargers.clients.js";
|
|
32
|
+
import { parseTeslaClientSlugs, teslaClientSlugsResponseSchema, } from "./slugs.clients.js";
|
|
33
|
+
export class TeslaClient {
|
|
34
|
+
constructor() { }
|
|
35
|
+
/**
|
|
36
|
+
* Fetch the map UI's location feed (`get-locations?view=map`), the source of the
|
|
37
|
+
* canonical `location_url_slug` per site. Like `get-charger-details` (and unlike `/all-locations`) this
|
|
38
|
+
* `/api/findus/` route sits behind Akamai's JS-sensor challenge, so it needs the
|
|
39
|
+
* rendering unblocker: routed through `SUPERCHARGERS_CHARGERS_PROXY` via plain
|
|
40
|
+
* `curl` when set.
|
|
41
|
+
*/
|
|
42
|
+
async fetchSlugs() {
|
|
43
|
+
const detailsProxy = process.env.SUPERCHARGERS_CHARGERS_PROXY;
|
|
44
|
+
const opts = detailsProxy
|
|
45
|
+
? { bin: "curl", proxy: detailsProxy, insecure: true }
|
|
46
|
+
: {};
|
|
47
|
+
const { data, error } = await getJson(SLUGS_URL, CHARGERS_HEADERS, { view: "map" }, undefined, undefined, undefined, opts);
|
|
48
|
+
if (error)
|
|
49
|
+
throw new Error(error);
|
|
50
|
+
const { slugs, invalid } = parseTeslaClientSlugs(teslaClientSlugsResponseSchema.parse(data).data.data);
|
|
51
|
+
if (invalid > 0)
|
|
52
|
+
console.warn(`slugs feed: skipped ${invalid} invalid entries`);
|
|
53
|
+
return slugs;
|
|
54
|
+
}
|
|
55
|
+
async fetchCharger(slug, locale) {
|
|
56
|
+
// get-charger-details needs a rendering unblocker. When configured, route ONLY
|
|
57
|
+
// this call through it using PLAIN `curl` (the unblocker owns the fingerprint
|
|
58
|
+
// and MITMs TLS, so -k). Otherwise go direct via SUPERCHARGERS_CURL_BIN.
|
|
59
|
+
const detailsProxy = process.env.SUPERCHARGERS_CHARGERS_PROXY;
|
|
60
|
+
const opts = detailsProxy
|
|
61
|
+
? { bin: "curl", proxy: detailsProxy, insecure: true }
|
|
62
|
+
: {};
|
|
63
|
+
const { data, attempts, error } = await getJson(CHARGERS_URL, CHARGERS_HEADERS, {
|
|
64
|
+
locationSlug: slug,
|
|
65
|
+
programType: "supercharger",
|
|
66
|
+
locale,
|
|
67
|
+
isInHkMoTw: "false",
|
|
68
|
+
}, undefined, undefined, undefined, opts);
|
|
69
|
+
// A hard fetch failure (HTTP status / timeout / missing curl) — surface it as
|
|
70
|
+
// the reason so the caller logs why this slug failed and tries the next one.
|
|
71
|
+
if (error)
|
|
72
|
+
return { charger: null, reason: error, attempts };
|
|
73
|
+
const parsed = teslaClientChargerResponseSchema.safeParse(data);
|
|
74
|
+
if (!parsed.success)
|
|
75
|
+
return { charger: null, reason: `${parsed.error}`, attempts };
|
|
76
|
+
return { charger: parsed.data.data.data, attempts };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let _client = null;
|
|
80
|
+
export const teslaClient = () => (_client ??= new TeslaClient());
|
|
81
|
+
//# sourceMappingURL=TeslaClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TeslaClient.js","sourceRoot":"","sources":["../../src/client/TeslaClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,SAAS,GACV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAGL,gCAAgC,GACjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,qBAAqB,EACrB,8BAA8B,GAG/B,MAAM,oBAAoB,CAAC;AAE5B,MAAM,OAAO,WAAW;IACtB,gBAAsB,CAAC;IAEvB;;;;;;OAMG;IACI,KAAK,CAAC,UAAU;QACrB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;QAC9D,MAAM,IAAI,GAAgB,YAAY;YACpC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CACnC,SAAS,EACT,gBAAgB,EAChB,EAAE,IAAI,EAAE,KAAK,EAAE,EACf,SAAS,EACT,SAAS,EACT,SAAS,EACT,IAAI,CACL,CAAC;QAEF,IAAI,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAC9C,8BAA8B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CACrD,CAAC;QACF,IAAI,OAAO,GAAG,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,uBAAuB,OAAO,kBAAkB,CAAC,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,YAAY,CACvB,IAAY,EACZ,MAAc;QAMd,+EAA+E;QAC/E,8EAA8E;QAC9E,yEAAyE;QACzE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;QAC9D,MAAM,IAAI,GAAgB,YAAY;YACpC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAC7C,YAAY,EACZ,gBAAgB,EAChB;YACE,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,cAAc;YAC3B,MAAM;YACN,UAAU,EAAE,OAAO;SACpB,EACD,SAAS,EACT,SAAS,EACT,SAAS,EACT,IAAI,CACL,CAAC;QAEF,8EAA8E;QAC9E,6EAA6E;QAC7E,IAAI,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QAE7D,MAAM,MAAM,GAAG,gCAAgC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,CAAC,OAAO;YACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;QAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACtD,CAAC;CACF;AAED,IAAI,OAAO,GAAuB,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CAAC,OAAO,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* ---------------------------------------------------------------------------------
|
|
4
|
+
* ----------------------- charger -------------------------------------------------
|
|
5
|
+
* ---------------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
export declare const teslaClientChargerSchema: z.ZodObject<{
|
|
8
|
+
accessType: z.ZodString;
|
|
9
|
+
address: z.ZodObject<{
|
|
10
|
+
city: z.ZodString;
|
|
11
|
+
country: z.ZodString;
|
|
12
|
+
countryCode: z.ZodString;
|
|
13
|
+
district: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
14
|
+
navRegion: z.ZodString;
|
|
15
|
+
nearestEntrance: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
16
|
+
postalCode: z.ZodString;
|
|
17
|
+
postalExt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
18
|
+
state: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
19
|
+
street: z.ZodString;
|
|
20
|
+
streetNumber: z.ZodString;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
availabilityProfile: z.ZodObject<{
|
|
23
|
+
siteId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
24
|
+
id: z.ZodNumber;
|
|
25
|
+
siteType: z.ZodString;
|
|
26
|
+
}, z.core.$strip>>>;
|
|
27
|
+
trtId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
28
|
+
id: z.ZodNumber;
|
|
29
|
+
siteType: z.ZodString;
|
|
30
|
+
}, z.core.$strip>>>;
|
|
31
|
+
utcOffset: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
brandName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
|
+
centroid: z.ZodObject<{
|
|
35
|
+
latitude: z.ZodNumber;
|
|
36
|
+
longitude: z.ZodNumber;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
commonSiteName: z.ZodString;
|
|
39
|
+
effectivePricebooks: z.ZodArray<z.ZodObject<{
|
|
40
|
+
currencyCode: z.ZodString;
|
|
41
|
+
days: z.ZodString;
|
|
42
|
+
endTime: z.ZodString;
|
|
43
|
+
feeType: z.ZodString;
|
|
44
|
+
isMemberPricebook: z.ZodBoolean;
|
|
45
|
+
isTou: z.ZodBoolean;
|
|
46
|
+
rateBase: z.ZodNumber;
|
|
47
|
+
rateTier1: z.ZodNumber;
|
|
48
|
+
rateTier2: z.ZodNumber;
|
|
49
|
+
startTime: z.ZodString;
|
|
50
|
+
uom: z.ZodString;
|
|
51
|
+
vehicleMakeType: z.ZodString;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
entryPoint: z.ZodObject<{
|
|
54
|
+
latitude: z.ZodNumber;
|
|
55
|
+
longitude: z.ZodNumber;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
locationGUID: z.ZodString;
|
|
58
|
+
maxPowerKw: z.ZodNumber;
|
|
59
|
+
name: z.ZodString;
|
|
60
|
+
openToNonTeslas: z.ZodBoolean;
|
|
61
|
+
openToPublic: z.ZodBoolean;
|
|
62
|
+
publicStallCount: z.ZodNumber;
|
|
63
|
+
timeZone: z.ZodString;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
export declare const teslaClientChargersSchema: z.ZodArray<z.ZodObject<{
|
|
66
|
+
accessType: z.ZodString;
|
|
67
|
+
address: z.ZodObject<{
|
|
68
|
+
city: z.ZodString;
|
|
69
|
+
country: z.ZodString;
|
|
70
|
+
countryCode: z.ZodString;
|
|
71
|
+
district: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
72
|
+
navRegion: z.ZodString;
|
|
73
|
+
nearestEntrance: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
74
|
+
postalCode: z.ZodString;
|
|
75
|
+
postalExt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
76
|
+
state: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
77
|
+
street: z.ZodString;
|
|
78
|
+
streetNumber: z.ZodString;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
availabilityProfile: z.ZodObject<{
|
|
81
|
+
siteId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
82
|
+
id: z.ZodNumber;
|
|
83
|
+
siteType: z.ZodString;
|
|
84
|
+
}, z.core.$strip>>>;
|
|
85
|
+
trtId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
86
|
+
id: z.ZodNumber;
|
|
87
|
+
siteType: z.ZodString;
|
|
88
|
+
}, z.core.$strip>>>;
|
|
89
|
+
utcOffset: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
90
|
+
}, z.core.$strip>;
|
|
91
|
+
brandName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
92
|
+
centroid: z.ZodObject<{
|
|
93
|
+
latitude: z.ZodNumber;
|
|
94
|
+
longitude: z.ZodNumber;
|
|
95
|
+
}, z.core.$strip>;
|
|
96
|
+
commonSiteName: z.ZodString;
|
|
97
|
+
effectivePricebooks: z.ZodArray<z.ZodObject<{
|
|
98
|
+
currencyCode: z.ZodString;
|
|
99
|
+
days: z.ZodString;
|
|
100
|
+
endTime: z.ZodString;
|
|
101
|
+
feeType: z.ZodString;
|
|
102
|
+
isMemberPricebook: z.ZodBoolean;
|
|
103
|
+
isTou: z.ZodBoolean;
|
|
104
|
+
rateBase: z.ZodNumber;
|
|
105
|
+
rateTier1: z.ZodNumber;
|
|
106
|
+
rateTier2: z.ZodNumber;
|
|
107
|
+
startTime: z.ZodString;
|
|
108
|
+
uom: z.ZodString;
|
|
109
|
+
vehicleMakeType: z.ZodString;
|
|
110
|
+
}, z.core.$strip>>;
|
|
111
|
+
entryPoint: z.ZodObject<{
|
|
112
|
+
latitude: z.ZodNumber;
|
|
113
|
+
longitude: z.ZodNumber;
|
|
114
|
+
}, z.core.$strip>;
|
|
115
|
+
locationGUID: z.ZodString;
|
|
116
|
+
maxPowerKw: z.ZodNumber;
|
|
117
|
+
name: z.ZodString;
|
|
118
|
+
openToNonTeslas: z.ZodBoolean;
|
|
119
|
+
openToPublic: z.ZodBoolean;
|
|
120
|
+
publicStallCount: z.ZodNumber;
|
|
121
|
+
timeZone: z.ZodString;
|
|
122
|
+
}, z.core.$strip>>;
|
|
123
|
+
export type TeslaClientCharger = z.infer<typeof teslaClientChargerSchema>;
|
|
124
|
+
export declare const teslaClientChargerResponseSchema: z.ZodObject<{
|
|
125
|
+
data: z.ZodObject<{
|
|
126
|
+
data: z.ZodObject<{
|
|
127
|
+
accessType: z.ZodString;
|
|
128
|
+
address: z.ZodObject<{
|
|
129
|
+
city: z.ZodString;
|
|
130
|
+
country: z.ZodString;
|
|
131
|
+
countryCode: z.ZodString;
|
|
132
|
+
district: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
133
|
+
navRegion: z.ZodString;
|
|
134
|
+
nearestEntrance: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
|
+
postalCode: z.ZodString;
|
|
136
|
+
postalExt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
137
|
+
state: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
138
|
+
street: z.ZodString;
|
|
139
|
+
streetNumber: z.ZodString;
|
|
140
|
+
}, z.core.$strip>;
|
|
141
|
+
availabilityProfile: z.ZodObject<{
|
|
142
|
+
siteId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
143
|
+
id: z.ZodNumber;
|
|
144
|
+
siteType: z.ZodString;
|
|
145
|
+
}, z.core.$strip>>>;
|
|
146
|
+
trtId: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
147
|
+
id: z.ZodNumber;
|
|
148
|
+
siteType: z.ZodString;
|
|
149
|
+
}, z.core.$strip>>>;
|
|
150
|
+
utcOffset: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
151
|
+
}, z.core.$strip>;
|
|
152
|
+
brandName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
153
|
+
centroid: z.ZodObject<{
|
|
154
|
+
latitude: z.ZodNumber;
|
|
155
|
+
longitude: z.ZodNumber;
|
|
156
|
+
}, z.core.$strip>;
|
|
157
|
+
commonSiteName: z.ZodString;
|
|
158
|
+
effectivePricebooks: z.ZodArray<z.ZodObject<{
|
|
159
|
+
currencyCode: z.ZodString;
|
|
160
|
+
days: z.ZodString;
|
|
161
|
+
endTime: z.ZodString;
|
|
162
|
+
feeType: z.ZodString;
|
|
163
|
+
isMemberPricebook: z.ZodBoolean;
|
|
164
|
+
isTou: z.ZodBoolean;
|
|
165
|
+
rateBase: z.ZodNumber;
|
|
166
|
+
rateTier1: z.ZodNumber;
|
|
167
|
+
rateTier2: z.ZodNumber;
|
|
168
|
+
startTime: z.ZodString;
|
|
169
|
+
uom: z.ZodString;
|
|
170
|
+
vehicleMakeType: z.ZodString;
|
|
171
|
+
}, z.core.$strip>>;
|
|
172
|
+
entryPoint: z.ZodObject<{
|
|
173
|
+
latitude: z.ZodNumber;
|
|
174
|
+
longitude: z.ZodNumber;
|
|
175
|
+
}, z.core.$strip>;
|
|
176
|
+
locationGUID: z.ZodString;
|
|
177
|
+
maxPowerKw: z.ZodNumber;
|
|
178
|
+
name: z.ZodString;
|
|
179
|
+
openToNonTeslas: z.ZodBoolean;
|
|
180
|
+
openToPublic: z.ZodBoolean;
|
|
181
|
+
publicStallCount: z.ZodNumber;
|
|
182
|
+
timeZone: z.ZodString;
|
|
183
|
+
}, z.core.$strip>;
|
|
184
|
+
success: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
185
|
+
}, z.core.$strip>;
|
|
186
|
+
}, z.core.$strip>;
|
|
187
|
+
export type TeslaClientChargerResponse = z.infer<typeof teslaClientChargerResponseSchema>;
|
|
188
|
+
//# sourceMappingURL=chargers.clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chargers.clients.d.ts","sourceRoot":"","sources":["../../src/client/chargers.clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqGnC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAoC,CAAC;AAE3E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAK3C,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* ---------------------------------------------------------------------------------
|
|
4
|
+
* ----------------------- charger -------------------------------------------------
|
|
5
|
+
* ---------------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
export const teslaClientChargerSchema = z.object({
|
|
8
|
+
// accessHours: z.object({ // not needed
|
|
9
|
+
// twentyFourSeven: z.boolean(),
|
|
10
|
+
// }),
|
|
11
|
+
accessType: z.string(),
|
|
12
|
+
address: z.object({
|
|
13
|
+
city: z.string(),
|
|
14
|
+
country: z.string(),
|
|
15
|
+
countryCode: z.string(),
|
|
16
|
+
district: z.string().nullable().optional(),
|
|
17
|
+
navRegion: z.string(),
|
|
18
|
+
nearestEntrance: z.string().nullable().optional(),
|
|
19
|
+
postalCode: z.string(),
|
|
20
|
+
postalExt: z.string().nullable().optional(),
|
|
21
|
+
state: z.string().nullable().optional(),
|
|
22
|
+
street: z.string(),
|
|
23
|
+
streetNumber: z.string(),
|
|
24
|
+
}),
|
|
25
|
+
// amenities: z.array(z.string()), // not needed
|
|
26
|
+
availabilityProfile: z.object({
|
|
27
|
+
// availabilityProfile: z.object({ // not needed
|
|
28
|
+
// friday: z.object({
|
|
29
|
+
// congestionValue: z.array(z.number()),
|
|
30
|
+
// }),
|
|
31
|
+
// monday: z.object({
|
|
32
|
+
// congestionValue: z.array(z.number()),
|
|
33
|
+
// }),
|
|
34
|
+
// saturday: z.object({
|
|
35
|
+
// congestionValue: z.array(z.number()),
|
|
36
|
+
// }),
|
|
37
|
+
// sunday: z.object({
|
|
38
|
+
// congestionValue: z.array(z.number()),
|
|
39
|
+
// }),
|
|
40
|
+
// thursday: z.object({
|
|
41
|
+
// congestionValue: z.array(z.number()),
|
|
42
|
+
// }),
|
|
43
|
+
// tuesday: z.object({
|
|
44
|
+
// congestionValue: z.array(z.number()),
|
|
45
|
+
// }),
|
|
46
|
+
// wednesday: z.object({
|
|
47
|
+
// congestionValue: z.array(z.number()),
|
|
48
|
+
// }),
|
|
49
|
+
// }),
|
|
50
|
+
// createdTimestamp: z.string(), // not needed
|
|
51
|
+
siteId: z
|
|
52
|
+
.object({
|
|
53
|
+
id: z.number(),
|
|
54
|
+
siteType: z.string(),
|
|
55
|
+
})
|
|
56
|
+
.nullable()
|
|
57
|
+
.optional(),
|
|
58
|
+
trtId: z
|
|
59
|
+
.object({
|
|
60
|
+
id: z.number(),
|
|
61
|
+
siteType: z.string(),
|
|
62
|
+
})
|
|
63
|
+
.nullable()
|
|
64
|
+
.optional(),
|
|
65
|
+
utcOffset: z.string().nullable().optional(),
|
|
66
|
+
}),
|
|
67
|
+
brandName: z.string().nullable().optional(),
|
|
68
|
+
centroid: z.object({
|
|
69
|
+
latitude: z.number(),
|
|
70
|
+
longitude: z.number(),
|
|
71
|
+
}),
|
|
72
|
+
commonSiteName: z.string(),
|
|
73
|
+
effectivePricebooks: z.array(z.object({
|
|
74
|
+
currencyCode: z.string(),
|
|
75
|
+
days: z.string(),
|
|
76
|
+
endTime: z.string(),
|
|
77
|
+
feeType: z.string(),
|
|
78
|
+
isMemberPricebook: z.boolean(),
|
|
79
|
+
isTou: z.boolean(),
|
|
80
|
+
// maxSiteOccupancy: z.null(), // not needed
|
|
81
|
+
// minSiteOccupancy: z.null(), // not needed
|
|
82
|
+
rateBase: z.number(),
|
|
83
|
+
// rateMinTier1: z.null(), // not needed
|
|
84
|
+
// rateMinTier2: z.null(), // not needed
|
|
85
|
+
// rateMinTier3: z.null(), // not needed
|
|
86
|
+
// rateMinTier4: z.null(), // not needed
|
|
87
|
+
rateTier1: z.number(),
|
|
88
|
+
rateTier2: z.number(),
|
|
89
|
+
startTime: z.string(),
|
|
90
|
+
uom: z.string(),
|
|
91
|
+
vehicleMakeType: z.string(),
|
|
92
|
+
})),
|
|
93
|
+
entryPoint: z.object({
|
|
94
|
+
latitude: z.number(),
|
|
95
|
+
longitude: z.number(),
|
|
96
|
+
}),
|
|
97
|
+
// isTrailerFriendly: z.boolean(), // not needed
|
|
98
|
+
locationGUID: z.string(),
|
|
99
|
+
maxPowerKw: z.number(),
|
|
100
|
+
name: z.string(),
|
|
101
|
+
openToNonTeslas: z.boolean(),
|
|
102
|
+
openToPublic: z.boolean(),
|
|
103
|
+
// ownershipType: z.null(), // not needed
|
|
104
|
+
publicStallCount: z.number(),
|
|
105
|
+
timeZone: z.string(),
|
|
106
|
+
});
|
|
107
|
+
export const teslaClientChargersSchema = z.array(teslaClientChargerSchema);
|
|
108
|
+
export const teslaClientChargerResponseSchema = z.object({
|
|
109
|
+
data: z.object({
|
|
110
|
+
data: teslaClientChargerSchema,
|
|
111
|
+
success: z.boolean().nullable().optional(),
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=chargers.clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chargers.clients.js","sourceRoot":"","sources":["../../src/client/chargers.clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CurlOptions } from "../types/client.types.js";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
export declare const CHARGERS_URL = "https://www.tesla.com/api/findus/get-charger-details";
|
|
4
|
+
export declare const SLUGS_URL = "https://www.tesla.com/api/findus/get-locations";
|
|
5
|
+
/**
|
|
6
|
+
* Map-feed `location_type`s that represent a (super)charger we can fetch.
|
|
7
|
+
* German Superchargers, for example, are typed `party` in the feed — matching
|
|
8
|
+
* only `supercharger` would miss them.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CHARGER_MAP_TYPES: Set<string>;
|
|
11
|
+
export declare const CHARGERS_HEADERS: Record<string, string>;
|
|
12
|
+
export declare const execFileAsync: typeof execFile.__promisify__;
|
|
13
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
14
|
+
export declare const getJson: <T>(url: string, headers: Record<string, string>, params?: Record<string, string>, retries?: number, backoff?: number, timeoutMs?: number, opts?: CurlOptions) => Promise<{
|
|
15
|
+
data: T | null;
|
|
16
|
+
attempts: number;
|
|
17
|
+
error: string | null;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Build the `{ bin, args }` for one curl GET. Exposed for unit testing the
|
|
21
|
+
* arg-building rules without spawning a process.
|
|
22
|
+
*
|
|
23
|
+
* Header rule: our hand-rolled `-H` headers are sent ONLY when the effective
|
|
24
|
+
* binary is plain `curl` (whether direct or via the unblocker proxy). An
|
|
25
|
+
* impersonate wrapper (bin !== "curl") supplies its own complete browser header
|
|
26
|
+
* set + TLS fingerprint, so re-sending UA/sec-ch-ua/etc. would break it.
|
|
27
|
+
* `--compressed` lets curl advertise + decode its own content-encoding, so we
|
|
28
|
+
* drop any caller-supplied `Accept-Encoding` to avoid an encoding it can't read.
|
|
29
|
+
*/
|
|
30
|
+
export declare const buildCurlArgs: (url: string, headers: Record<string, string>, timeoutMs: number, opts?: CurlOptions) => {
|
|
31
|
+
bin: string;
|
|
32
|
+
args: string[];
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=common.clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.clients.d.ts","sourceRoot":"","sources":["../../src/client/common.clients.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,eAAO,MAAM,YAAY,yDAC+B,CAAC;AACzD,eAAO,MAAM,SAAS,mDAAmD,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,aAK5B,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAYnD,CAAC;AAEF,eAAO,MAAM,aAAa,+BAAsB,CAAC;AAEjD,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CACF,CAAC;AAE9C,eAAO,MAAM,OAAO,GAAU,CAAC,EAC7B,KAAK,MAAM,EACX,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,gBAAW,EACX,gBAAa,EACb,kBAAiB,EACjB,OAAM,WAAgB,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAmCpE,CAAC;AAqCF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,MAAM,EACX,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,WAAW,MAAM,EACjB,OAAM,WAAgB,KACrB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAqB/B,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { promisify } from "node:util";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
export const CHARGERS_URL = "https://www.tesla.com/api/findus/get-charger-details";
|
|
4
|
+
export const SLUGS_URL = "https://www.tesla.com/api/findus/get-locations";
|
|
5
|
+
/**
|
|
6
|
+
* Map-feed `location_type`s that represent a (super)charger we can fetch.
|
|
7
|
+
* German Superchargers, for example, are typed `party` in the feed — matching
|
|
8
|
+
* only `supercharger` would miss them.
|
|
9
|
+
*/
|
|
10
|
+
export const CHARGER_MAP_TYPES = new Set([
|
|
11
|
+
"supercharger",
|
|
12
|
+
"party",
|
|
13
|
+
"coming_soon_supercharger",
|
|
14
|
+
"winner_supercharger",
|
|
15
|
+
]);
|
|
16
|
+
export const CHARGERS_HEADERS = {
|
|
17
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36",
|
|
18
|
+
Accept: "application/json, text/plain, */*",
|
|
19
|
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
20
|
+
"Accept-Language": "en,de-DE;q=0.9,de;q=0.8,en-US;q=0.7",
|
|
21
|
+
Priority: "u=1, i",
|
|
22
|
+
"sec-ch-ua": `"Google Chrome";v="149", "Chromium";v="149", "Not)A;Brand";v="24"`,
|
|
23
|
+
Referer: "https://www.tesla.com/findus",
|
|
24
|
+
"sec-fetch-dest": "empty",
|
|
25
|
+
"sec-ch-ua-platform": `"macOS"`,
|
|
26
|
+
"sec-ch-ua-mobile": "?0",
|
|
27
|
+
};
|
|
28
|
+
export const execFileAsync = promisify(execFile);
|
|
29
|
+
export const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
30
|
+
export const getJson = async (url, headers, params, retries = 4, backoff = 1.5, timeoutMs = 30000, opts = {}) => {
|
|
31
|
+
const full = params ? `${url}?${new URLSearchParams(params)}` : url;
|
|
32
|
+
let last = "";
|
|
33
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
34
|
+
try {
|
|
35
|
+
const res = await curlGet(full, headers, timeoutMs, opts);
|
|
36
|
+
if (res.status === 200)
|
|
37
|
+
return {
|
|
38
|
+
data: JSON.parse(res.body),
|
|
39
|
+
attempts: attempt + 1,
|
|
40
|
+
error: null,
|
|
41
|
+
};
|
|
42
|
+
last = `HTTP ${res.status}`;
|
|
43
|
+
// 403/429 -> almost always rate limiting or a bot challenge; back off.
|
|
44
|
+
if ([403, 429, 500, 502, 503].includes(res.status)) {
|
|
45
|
+
await sleep(backoff * 1000 * (attempt + 1));
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// Other non-200 (e.g. 404): a hard failure. Report the status so the
|
|
49
|
+
// caller can log *why* instead of silently dropping the site.
|
|
50
|
+
return {
|
|
51
|
+
data: null,
|
|
52
|
+
attempts: attempt + 1,
|
|
53
|
+
error: `Request failed (${last}) for ${full}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
last = e instanceof Error ? e.message : String(e);
|
|
58
|
+
await sleep(backoff * 1000 * (attempt + 1));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
data: null,
|
|
63
|
+
attempts: retries,
|
|
64
|
+
error: `Request failed (${last}) for ${full}`,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* One HTTP GET via curl (HTTP/2). We append the status code to stdout via `-w`
|
|
69
|
+
* and split it back off the body. The binary + header/proxy rules are decided
|
|
70
|
+
* by {@link buildCurlArgs}.
|
|
71
|
+
*/
|
|
72
|
+
const curlGet = async (url, headers, timeoutMs, opts = {}) => {
|
|
73
|
+
const { bin, args } = buildCurlArgs(url, headers, timeoutMs, opts);
|
|
74
|
+
let stdout;
|
|
75
|
+
try {
|
|
76
|
+
({ stdout } = await execFileAsync(bin, args, {
|
|
77
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
78
|
+
timeout: timeoutMs + 5000,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
const err = e;
|
|
83
|
+
if (err.code === "ENOENT") {
|
|
84
|
+
throw new Error(`\`${bin}\` is required to reach tesla.com but was not found on PATH.`);
|
|
85
|
+
}
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
const idx = stdout.lastIndexOf("\n");
|
|
89
|
+
const body = idx >= 0 ? stdout.slice(0, idx) : "";
|
|
90
|
+
const status = Number(stdout.slice(idx + 1).trim());
|
|
91
|
+
return { status, body };
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Build the `{ bin, args }` for one curl GET. Exposed for unit testing the
|
|
95
|
+
* arg-building rules without spawning a process.
|
|
96
|
+
*
|
|
97
|
+
* Header rule: our hand-rolled `-H` headers are sent ONLY when the effective
|
|
98
|
+
* binary is plain `curl` (whether direct or via the unblocker proxy). An
|
|
99
|
+
* impersonate wrapper (bin !== "curl") supplies its own complete browser header
|
|
100
|
+
* set + TLS fingerprint, so re-sending UA/sec-ch-ua/etc. would break it.
|
|
101
|
+
* `--compressed` lets curl advertise + decode its own content-encoding, so we
|
|
102
|
+
* drop any caller-supplied `Accept-Encoding` to avoid an encoding it can't read.
|
|
103
|
+
*/
|
|
104
|
+
export const buildCurlArgs = (url, headers, timeoutMs, opts = {}) => {
|
|
105
|
+
const bin = opts.bin ?? (process.env.SUPERCHARGERS_CURL_BIN || "curl");
|
|
106
|
+
const args = [
|
|
107
|
+
"-sS",
|
|
108
|
+
"--compressed",
|
|
109
|
+
"--http2",
|
|
110
|
+
"--max-time",
|
|
111
|
+
String(Math.ceil(timeoutMs / 1000)),
|
|
112
|
+
"-w",
|
|
113
|
+
"\n%{http_code}",
|
|
114
|
+
];
|
|
115
|
+
if (opts.proxy)
|
|
116
|
+
args.push("--proxy", opts.proxy);
|
|
117
|
+
if (opts.insecure)
|
|
118
|
+
args.push("-k");
|
|
119
|
+
if (bin === "curl") {
|
|
120
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
121
|
+
if (k.toLowerCase() === "accept-encoding")
|
|
122
|
+
continue;
|
|
123
|
+
args.push("-H", `${k}: ${v}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
args.push(url);
|
|
127
|
+
return { bin, args };
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=common.clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.clients.js","sourceRoot":"","sources":["../../src/client/common.clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|