@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,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* ---------------------------------------------------------------------------------
|
|
4
|
+
* ----------------------- slug ----------------------------------------------------
|
|
5
|
+
* ---------------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
export declare const teslaClientSlugSchema: z.ZodObject<{
|
|
8
|
+
inCN: z.ZodBoolean;
|
|
9
|
+
inHkMoTw: z.ZodBoolean;
|
|
10
|
+
latitude: z.ZodNumber;
|
|
11
|
+
longitude: z.ZodNumber;
|
|
12
|
+
location_type: z.ZodArray<z.ZodString>;
|
|
13
|
+
location_url_slug: z.ZodString;
|
|
14
|
+
supercharger_function: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
access_type: z.ZodString;
|
|
16
|
+
actual_latitude: z.ZodString;
|
|
17
|
+
actual_longitude: z.ZodString;
|
|
18
|
+
charging_accessibility: z.ZodString;
|
|
19
|
+
coming_soon_latitude: z.ZodNullable<z.ZodString>;
|
|
20
|
+
coming_soon_longitude: z.ZodNullable<z.ZodString>;
|
|
21
|
+
coming_soon_name: z.ZodNullable<z.ZodString>;
|
|
22
|
+
open_to_non_tesla: z.ZodBoolean;
|
|
23
|
+
project_status: z.ZodString;
|
|
24
|
+
show_on_find_us: z.ZodString;
|
|
25
|
+
site_status: z.ZodString;
|
|
26
|
+
vote_winner_quarter: z.ZodNullable<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
title: z.ZodString;
|
|
29
|
+
uuid: z.ZodString;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export type TeslaClientSlug = z.infer<typeof teslaClientSlugSchema>;
|
|
32
|
+
export declare const teslaClientSlugsResponseSchema: z.ZodObject<{
|
|
33
|
+
data: z.ZodObject<{
|
|
34
|
+
data: z.ZodArray<z.ZodUnknown>;
|
|
35
|
+
success: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type TeslaClientSlugsResponse = z.infer<typeof teslaClientSlugsResponseSchema>;
|
|
39
|
+
/**
|
|
40
|
+
* Per-element validation of a slugs feed array: a malformed entry (schema
|
|
41
|
+
* drift on a single site) is skipped and counted instead of aborting the
|
|
42
|
+
* whole sync. Throws only when `entries` is not an array at all.
|
|
43
|
+
*/
|
|
44
|
+
export declare const parseTeslaClientSlugs: (entries: unknown) => {
|
|
45
|
+
slugs: TeslaClientSlug[];
|
|
46
|
+
invalid: number;
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=slugs.clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slugs.clients.d.ts","sourceRoot":"","sources":["../../src/client/slugs.clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAyBhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAGpE,eAAO,MAAM,8BAA8B;;;;;iBAKzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,OAAO,KACf;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAS7C,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* ---------------------------------------------------------------------------------
|
|
4
|
+
* ----------------------- slug ----------------------------------------------------
|
|
5
|
+
* ---------------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
export const teslaClientSlugSchema = z.object({
|
|
8
|
+
inCN: z.boolean(),
|
|
9
|
+
inHkMoTw: z.boolean(),
|
|
10
|
+
latitude: z.number(),
|
|
11
|
+
longitude: z.number(),
|
|
12
|
+
location_type: z.array(z.string()),
|
|
13
|
+
location_url_slug: z.string(),
|
|
14
|
+
supercharger_function: z
|
|
15
|
+
.object({
|
|
16
|
+
access_type: z.string(),
|
|
17
|
+
actual_latitude: z.string(),
|
|
18
|
+
actual_longitude: z.string(),
|
|
19
|
+
charging_accessibility: z.string(),
|
|
20
|
+
coming_soon_latitude: z.string().nullable(),
|
|
21
|
+
coming_soon_longitude: z.string().nullable(),
|
|
22
|
+
coming_soon_name: z.string().nullable(),
|
|
23
|
+
open_to_non_tesla: z.boolean(),
|
|
24
|
+
project_status: z.string(),
|
|
25
|
+
show_on_find_us: z.string(),
|
|
26
|
+
site_status: z.string(),
|
|
27
|
+
vote_winner_quarter: z.string().nullable(),
|
|
28
|
+
})
|
|
29
|
+
.optional(),
|
|
30
|
+
title: z.string(),
|
|
31
|
+
uuid: z.string(),
|
|
32
|
+
});
|
|
33
|
+
// elements stay unknown: they are validated one by one via parseTeslaClientSlugs
|
|
34
|
+
export const teslaClientSlugsResponseSchema = z.object({
|
|
35
|
+
data: z.object({
|
|
36
|
+
data: z.array(z.unknown()),
|
|
37
|
+
success: z.boolean().nullable().optional(),
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Per-element validation of a slugs feed array: a malformed entry (schema
|
|
42
|
+
* drift on a single site) is skipped and counted instead of aborting the
|
|
43
|
+
* whole sync. Throws only when `entries` is not an array at all.
|
|
44
|
+
*/
|
|
45
|
+
export const parseTeslaClientSlugs = (entries) => {
|
|
46
|
+
const slugs = [];
|
|
47
|
+
let invalid = 0;
|
|
48
|
+
for (const entry of z.array(z.unknown()).parse(entries)) {
|
|
49
|
+
const parsed = teslaClientSlugSchema.safeParse(entry);
|
|
50
|
+
if (parsed.success)
|
|
51
|
+
slugs.push(parsed.data);
|
|
52
|
+
else
|
|
53
|
+
invalid++;
|
|
54
|
+
}
|
|
55
|
+
return { slugs, invalid };
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=slugs.clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slugs.clients.js","sourceRoot":"","sources":["../../src/client/slugs.clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,qBAAqB,EAAE,CAAC;SACrB,MAAM,CAAC;QACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;QAC3B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;QAC5B,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE;QAClC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACvC,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE;QAC9B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;QAC1B,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;QAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;QACvB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC3C,CAAC;SACD,QAAQ,EAAE;IACb,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAIH,iFAAiF;AACjF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;KAC3C,CAAC;CACH,CAAC,CAAC;AAMH;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAgB,EAC+B,EAAE;IACjD,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YACvC,OAAO,EAAE,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface Coordinate {
|
|
2
|
+
latitude: number;
|
|
3
|
+
longitude: number;
|
|
4
|
+
}
|
|
5
|
+
export interface CoordinateStr {
|
|
6
|
+
latitude: string;
|
|
7
|
+
longitude: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CoordinateAny {
|
|
10
|
+
latitude: string | number;
|
|
11
|
+
longitude: string | number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Coordinate box (degrees) used as a cheap SQL prefilter before the exact
|
|
15
|
+
* haversine check below. Latitude degrees are ~constant (0.005° ≈ 555 m);
|
|
16
|
+
* longitude degrees shrink with latitude, so the longitude bound is twice as
|
|
17
|
+
* wide — 0.01° still spans the 250 m match radius up to ~77° latitude,
|
|
18
|
+
* comfortably past the northernmost Superchargers.
|
|
19
|
+
*/
|
|
20
|
+
export declare const COVERED_RADIUS_KM = 0.25;
|
|
21
|
+
export declare const COVERED_MARGIN = 1.05;
|
|
22
|
+
export declare const EARTH_RADIUS_KM = 6371;
|
|
23
|
+
export declare const KM_PER_DEG_LAT = 111.32;
|
|
24
|
+
export declare const distanceInKm: (a: CoordinateAny, b: CoordinateAny) => number;
|
|
25
|
+
export declare const toCoordinate: (item: CoordinateAny) => Coordinate;
|
|
26
|
+
export declare const toNumber: (value: string | number) => number;
|
|
27
|
+
export declare const boundingBoxDeg: (item: CoordinateAny, radiusKm: number) => {
|
|
28
|
+
latDeg: number;
|
|
29
|
+
lonDeg: number;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=coordinates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinates.d.ts","sourceRoot":"","sources":["../../src/common/coordinates.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,cAAc,OAAO,CAAC;AACnC,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,cAAc,SAAS,CAAC;AAIrC,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,GAAG,aAAa,KAAG,MAgBjE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,MAAM,aAAa,KAAG,UAGjD,CAAC;AAEH,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,GAAG,MAAM,KAAG,MAQjD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,aAAa,EAAE,UAAU,MAAM;;;CAOnE,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinate box (degrees) used as a cheap SQL prefilter before the exact
|
|
3
|
+
* haversine check below. Latitude degrees are ~constant (0.005° ≈ 555 m);
|
|
4
|
+
* longitude degrees shrink with latitude, so the longitude bound is twice as
|
|
5
|
+
* wide — 0.01° still spans the 250 m match radius up to ~77° latitude,
|
|
6
|
+
* comfortably past the northernmost Superchargers.
|
|
7
|
+
*/
|
|
8
|
+
export const COVERED_RADIUS_KM = 0.25;
|
|
9
|
+
export const COVERED_MARGIN = 1.05; // small safety factor for the box
|
|
10
|
+
export const EARTH_RADIUS_KM = 6371;
|
|
11
|
+
export const KM_PER_DEG_LAT = 111.32; // near-constant everywhere
|
|
12
|
+
const toRadians = (degrees) => degrees * (Math.PI / 180);
|
|
13
|
+
export const distanceInKm = (a, b) => {
|
|
14
|
+
const aCoord = toCoordinate(a);
|
|
15
|
+
const bCoord = toCoordinate(b);
|
|
16
|
+
const dLat = toRadians(bCoord.latitude - aCoord.latitude);
|
|
17
|
+
const dLon = toRadians(bCoord.longitude - aCoord.longitude);
|
|
18
|
+
const lat1 = toRadians(aCoord.latitude);
|
|
19
|
+
const lat2 = toRadians(bCoord.latitude);
|
|
20
|
+
const h = Math.sin(dLat / 2) ** 2 +
|
|
21
|
+
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) ** 2;
|
|
22
|
+
const c = 2 * Math.asin(Math.sqrt(h));
|
|
23
|
+
return EARTH_RADIUS_KM * c;
|
|
24
|
+
};
|
|
25
|
+
export const toCoordinate = (item) => ({
|
|
26
|
+
latitude: toNumber(item.latitude),
|
|
27
|
+
longitude: toNumber(item.longitude),
|
|
28
|
+
});
|
|
29
|
+
export const toNumber = (value) => {
|
|
30
|
+
const n = typeof value === "number" ? value : parseFloat(value);
|
|
31
|
+
if (Number.isNaN(n)) {
|
|
32
|
+
throw new Error(`Could not parse a numeric value from: ${JSON.stringify(value)}`);
|
|
33
|
+
}
|
|
34
|
+
return n;
|
|
35
|
+
};
|
|
36
|
+
export const boundingBoxDeg = (item, radiusKm) => {
|
|
37
|
+
const coord = toCoordinate(item);
|
|
38
|
+
const latDeg = radiusKm / KM_PER_DEG_LAT;
|
|
39
|
+
const cosLat = Math.cos((coord.latitude * Math.PI) / 180);
|
|
40
|
+
// guard: near the poles cos(lat) -> 0 and lonDeg explodes; clamp to full range
|
|
41
|
+
const lonDeg = cosLat > 1e-6 ? radiusKm / (KM_PER_DEG_LAT * cosLat) : 180;
|
|
42
|
+
return { latDeg, lonDeg };
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=coordinates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinates.js","sourceRoot":"","sources":["../../src/common/coordinates.ts"],"names":[],"mappings":"AAeA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,CAAC,kCAAkC;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,2BAA2B;AAEjE,MAAM,SAAS,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;AAEzE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAgB,EAAE,CAAgB,EAAU,EAAE;IACzE,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,CAAC,GACL,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5D,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtC,OAAO,eAAe,GAAG,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAmB,EAAc,EAAE,CAAC,CAAC;IAChE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;IACjC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;CACpC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAsB,EAAU,EAAE;IACzD,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,yCAAyC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CACjE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAmB,EAAE,QAAgB,EAAE,EAAE;IACtE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,GAAG,cAAc,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IAC1D,+EAA+E;IAC/E,MAAM,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ChargingProcesses, type ChargingProcessesId, type ChargingProcessesInitializer, type ChargingProcessesMutator, type PicChargingProcessStates, type PicChargingProcessStatesId } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import { IMateStore } from "./IMateStore.js";
|
|
3
|
+
import { type SqlTx } from "./db.js";
|
|
4
|
+
import type { FailedChargingProcessState, UnpricedChargingProcess } from "../types/chargingProcess.types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Access to TeslaMate's `charging_processes` table. The helpers here
|
|
7
|
+
* ({@link ChargingProcessesStore.getUnpricedCharges},
|
|
8
|
+
* {@link ChargingProcessesStore.updatePrice}) will back the planned charge-cost
|
|
9
|
+
* backfill; nothing calls them yet. The backfill's guardrails, once wired up:
|
|
10
|
+
* only charges matched to one of our priced Superchargers, and only rows where
|
|
11
|
+
* `cost IS NULL` — an existing cost (TeslaMate's or the user's) is never
|
|
12
|
+
* overwritten.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ChargingProcessesStore extends IMateStore<ChargingProcessesId, ChargingProcesses, ChargingProcessesInitializer, ChargingProcessesMutator> {
|
|
15
|
+
readonly statesTable: string;
|
|
16
|
+
constructor();
|
|
17
|
+
getUnpricedCharges(tx?: SqlTx): Promise<UnpricedChargingProcess[]>;
|
|
18
|
+
updatePrice(processId: ChargingProcessesId, cost: number | null, tx?: SqlTx): Promise<ChargingProcesses>;
|
|
19
|
+
getState(processId: ChargingProcessesId, tx?: SqlTx): Promise<PicChargingProcessStates | null>;
|
|
20
|
+
resetState(processId: ChargingProcessesId, tx?: SqlTx): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Failed state rows at or above `threshold`, most-failing first, each joined
|
|
23
|
+
* to its charge's `start_date`. With `onlyUnnotified` only rows not yet paged
|
|
24
|
+
* (`failure_notified_at IS NULL`) are returned.
|
|
25
|
+
*/
|
|
26
|
+
getFailedStates(threshold: number, onlyUnnotified?: boolean, tx?: SqlTx): Promise<FailedChargingProcessState[]>;
|
|
27
|
+
/** Stamp the notified flag on the given state rows (by id; empty is a no-op). */
|
|
28
|
+
markStatesNotified(stateIds: PicChargingProcessStatesId[], tx?: SqlTx): Promise<void>;
|
|
29
|
+
/** Bulk reset = delete every state row (matching single-row resetState); returns rows deleted. */
|
|
30
|
+
resetAllStates(tx?: SqlTx): Promise<number>;
|
|
31
|
+
incrementStateFailed(processId: ChargingProcessesId, tx?: SqlTx): Promise<number>;
|
|
32
|
+
}
|
|
33
|
+
export declare const chargingProcessesStore: () => ChargingProcessesStore;
|
|
34
|
+
//# sourceMappingURL=ChargingProcessesStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChargingProcessesStore.d.ts","sourceRoot":"","sources":["../../src/store/ChargingProcessesStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAO,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EACV,0BAA0B,EAC1B,uBAAuB,EACxB,MAAM,mCAAmC,CAAC;AAG3C;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,SAAQ,UAAU,CACpD,mBAAmB,EACnB,iBAAiB,EACjB,4BAA4B,EAC5B,wBAAwB,CACzB;IACC,SAAgB,WAAW,EAAE,MAAM,CAAiC;;IAUvD,kBAAkB,CAC7B,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAuBxB,WAAW,CACtB,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,iBAAiB,CAAC;IAQhB,QAAQ,CACnB,SAAS,EAAE,mBAAmB,EAC9B,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;IAO9B,UAAU,CACrB,SAAS,EAAE,mBAAmB,EAC9B,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,IAAI,CAAC;IAIhB;;;;OAIG;IACU,eAAe,CAC1B,SAAS,EAAE,MAAM,EACjB,cAAc,UAAQ,EACtB,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAWxC,iFAAiF;IACpE,kBAAkB,CAC7B,QAAQ,EAAE,0BAA0B,EAAE,EACtC,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,IAAI,CAAC;IAMhB,kGAAkG;IACrF,cAAc,CAAC,EAAE,GAAE,KAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAKlD,oBAAoB,CAC/B,SAAS,EAAE,mBAAmB,EAC9B,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,MAAM,CAAC;CAWnB;AAGD,eAAO,MAAM,sBAAsB,8BACQ,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { chargingProcessesInitializer, chargingProcessesMutator, } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import { IMateStore } from "./IMateStore.js";
|
|
3
|
+
import { sql } from "./db.js";
|
|
4
|
+
/**
|
|
5
|
+
* Access to TeslaMate's `charging_processes` table. The helpers here
|
|
6
|
+
* ({@link ChargingProcessesStore.getUnpricedCharges},
|
|
7
|
+
* {@link ChargingProcessesStore.updatePrice}) will back the planned charge-cost
|
|
8
|
+
* backfill; nothing calls them yet. The backfill's guardrails, once wired up:
|
|
9
|
+
* only charges matched to one of our priced Superchargers, and only rows where
|
|
10
|
+
* `cost IS NULL` — an existing cost (TeslaMate's or the user's) is never
|
|
11
|
+
* overwritten.
|
|
12
|
+
*/
|
|
13
|
+
export class ChargingProcessesStore extends IMateStore {
|
|
14
|
+
statesTable = "pic_charging_process_states";
|
|
15
|
+
constructor() {
|
|
16
|
+
super("charging_processes", chargingProcessesInitializer, chargingProcessesMutator);
|
|
17
|
+
}
|
|
18
|
+
async getUnpricedCharges(tx = sql()) {
|
|
19
|
+
return await tx `
|
|
20
|
+
SELECT
|
|
21
|
+
cp.id,
|
|
22
|
+
cp.start_date,
|
|
23
|
+
cp.end_date,
|
|
24
|
+
cp.car_id,
|
|
25
|
+
cp.position_id,
|
|
26
|
+
cp.address_id,
|
|
27
|
+
cp.charge_energy_added,
|
|
28
|
+
cp.charge_energy_used,
|
|
29
|
+
cp.duration_min,
|
|
30
|
+
p.latitude,
|
|
31
|
+
p.longitude,
|
|
32
|
+
s.id AS states_id,
|
|
33
|
+
s.failure_count
|
|
34
|
+
FROM charging_processes cp
|
|
35
|
+
INNER JOIN positions p ON p.id = cp.position_id
|
|
36
|
+
LEFT OUTER JOIN pic_charging_process_states as s ON s.charging_processes_id = cp.id
|
|
37
|
+
WHERE cp.cost IS NULL
|
|
38
|
+
AND cp.end_date IS NOT NULL;`;
|
|
39
|
+
}
|
|
40
|
+
async updatePrice(processId, cost, tx = sql()) {
|
|
41
|
+
return await this.update(processId, { cost: cost?.toString().replace(",", ".") ?? null }, tx);
|
|
42
|
+
}
|
|
43
|
+
async getState(processId, tx = sql()) {
|
|
44
|
+
const [row] = await tx `SELECT * FROM ${tx(this.statesTable)} WHERE charging_processes_id = ${processId}`;
|
|
45
|
+
return row ?? null;
|
|
46
|
+
}
|
|
47
|
+
async resetState(processId, tx = sql()) {
|
|
48
|
+
await tx `DELETE FROM ${tx(this.statesTable)} WHERE charging_processes_id = ${processId}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Failed state rows at or above `threshold`, most-failing first, each joined
|
|
52
|
+
* to its charge's `start_date`. With `onlyUnnotified` only rows not yet paged
|
|
53
|
+
* (`failure_notified_at IS NULL`) are returned.
|
|
54
|
+
*/
|
|
55
|
+
async getFailedStates(threshold, onlyUnnotified = false, tx = sql()) {
|
|
56
|
+
return await tx `
|
|
57
|
+
SELECT s.*, cp.start_date
|
|
58
|
+
FROM ${tx(this.statesTable)} s
|
|
59
|
+
LEFT JOIN charging_processes cp ON cp.id = s.charging_processes_id
|
|
60
|
+
WHERE s.failure_count >= ${threshold}
|
|
61
|
+
${onlyUnnotified ? tx `AND s.failure_notified_at IS NULL` : tx ``}
|
|
62
|
+
ORDER BY s.failure_count DESC
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
/** Stamp the notified flag on the given state rows (by id; empty is a no-op). */
|
|
66
|
+
async markStatesNotified(stateIds, tx = sql()) {
|
|
67
|
+
await tx `UPDATE ${tx(this.statesTable)}
|
|
68
|
+
SET failure_notified_at = CURRENT_TIMESTAMP
|
|
69
|
+
WHERE id = ANY(${stateIds}::bigint[])`;
|
|
70
|
+
}
|
|
71
|
+
/** Bulk reset = delete every state row (matching single-row resetState); returns rows deleted. */
|
|
72
|
+
async resetAllStates(tx = sql()) {
|
|
73
|
+
const result = await tx `DELETE FROM ${tx(this.statesTable)}`;
|
|
74
|
+
return result.count;
|
|
75
|
+
}
|
|
76
|
+
async incrementStateFailed(processId, tx = sql()) {
|
|
77
|
+
const [row] = await tx `
|
|
78
|
+
INSERT INTO ${tx(this.statesTable)} (created_at, updated_at, charging_processes_id, failure_count)
|
|
79
|
+
VALUES (CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, ${processId}, 1)
|
|
80
|
+
ON CONFLICT (charging_processes_id)
|
|
81
|
+
DO UPDATE SET failure_count = ${tx(this.statesTable)}.failure_count + 1,
|
|
82
|
+
updated_at = CURRENT_TIMESTAMP
|
|
83
|
+
RETURNING failure_count
|
|
84
|
+
`;
|
|
85
|
+
return row.failure_count;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
let _store = null;
|
|
89
|
+
export const chargingProcessesStore = () => (_store ??= new ChargingProcessesStore());
|
|
90
|
+
//# sourceMappingURL=ChargingProcessesStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChargingProcessesStore.js","sourceRoot":"","sources":["../../src/store/ChargingProcessesStore.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,GAOzB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAc,MAAM,SAAS,CAAC;AAO1C;;;;;;;;GAQG;AACH,MAAM,OAAO,sBAAuB,SAAQ,UAK3C;IACiB,WAAW,GAAW,6BAA6B,CAAC;IAEpE;QACE,KAAK,CACH,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,CACzB,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,KAAY,GAAG,EAAE;QAEjB,OAAO,MAAM,EAAE,CAA2B;;;;;;;;;;;;;;;;;;;uCAmBP,CAAC;IACtC,CAAC;IAEM,KAAK,CAAC,WAAW,CACtB,SAA8B,EAC9B,IAAmB,EACnB,KAAY,GAAG,EAAE;QAEjB,OAAO,MAAM,IAAI,CAAC,MAAM,CACtB,SAAS,EACT,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EACpD,EAAE,CACH,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,QAAQ,CACnB,SAA8B,EAC9B,KAAY,GAAG,EAAE;QAEjB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAErB,iBAAiB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,kCAAkC,SAAS,EAAE,CAAC;QACpF,OAAO,GAAG,IAAI,IAAI,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,SAA8B,EAC9B,KAAY,GAAG,EAAE;QAEjB,MAAM,EAAE,CAAA,eAAe,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,kCAAkC,SAAS,EAAE,CAAC;IAC3F,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe,CAC1B,SAAiB,EACjB,cAAc,GAAG,KAAK,EACtB,KAAY,GAAG,EAAE;QAEjB,OAAO,MAAM,EAAE,CAA8B;;eAElC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;;mCAEA,SAAS;UAClC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAA,mCAAmC,CAAC,CAAC,CAAC,EAAE,CAAA,EAAE;;KAElE,CAAC;IACJ,CAAC;IAED,iFAAiF;IAC1E,KAAK,CAAC,kBAAkB,CAC7B,QAAsC,EACtC,KAAY,GAAG,EAAE;QAEjB,MAAM,EAAE,CAAA,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;;uBAEnB,QAA+B,aAAa,CAAC;IAClE,CAAC;IAED,kGAAkG;IAC3F,KAAK,CAAC,cAAc,CAAC,KAAY,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAA,eAAe,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,SAA8B,EAC9B,KAAY,GAAG,EAAE;QAEjB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAAuB;oBAC7B,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;wDACgB,SAAS;;wCAEzB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;;;OAGrD,CAAC;QACJ,OAAO,GAAG,CAAC,aAAa,CAAC;IAC3B,CAAC;CACF;AAED,IAAI,MAAM,GAAkC,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CACzC,CAAC,MAAM,KAAK,IAAI,sBAAsB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Geofences, type GeofencesId, type GeofencesInitializer, type GeofencesMutator } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import { IMateStore } from "./IMateStore.js";
|
|
3
|
+
import type { Coordinate } from "../common/coordinates.js";
|
|
4
|
+
import { type SqlTx } from "./db.js";
|
|
5
|
+
/**
|
|
6
|
+
* Read access to TeslaMate's `geofences` table. Today this is only
|
|
7
|
+
* {@link GeofencesStore.getHome}; writing priced Supercharger geofences back
|
|
8
|
+
* into TeslaMate is planned but not implemented yet.
|
|
9
|
+
*/
|
|
10
|
+
export declare class GeofencesStore extends IMateStore<GeofencesId, Geofences, GeofencesInitializer, GeofencesMutator> {
|
|
11
|
+
constructor();
|
|
12
|
+
/**
|
|
13
|
+
* The coordinate of the TeslaMate geofence named `name` (case-insensitive,
|
|
14
|
+
* default "Home"), or null if there is none. Used to center a radius scope on
|
|
15
|
+
* your home without duplicating the coordinate in config.
|
|
16
|
+
*/
|
|
17
|
+
getHome(geofenceName?: string, tx?: SqlTx): Promise<Coordinate | null>;
|
|
18
|
+
}
|
|
19
|
+
export declare const geofencesStore: () => GeofencesStore;
|
|
20
|
+
//# sourceMappingURL=GeofencesStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeofencesStore.d.ts","sourceRoot":"","sources":["../../src/store/GeofencesStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACtB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAO,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,UAAU,CAC5C,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,gBAAgB,CACjB;;IAKC;;;;OAIG;IACU,OAAO,CAClB,YAAY,GAAE,MAAe,EAC7B,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAU9B;AAGD,eAAO,MAAM,cAAc,sBAA0C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { geofencesInitializer, geofencesMutator, } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import { IMateStore } from "./IMateStore.js";
|
|
3
|
+
import { sql } from "./db.js";
|
|
4
|
+
/**
|
|
5
|
+
* Read access to TeslaMate's `geofences` table. Today this is only
|
|
6
|
+
* {@link GeofencesStore.getHome}; writing priced Supercharger geofences back
|
|
7
|
+
* into TeslaMate is planned but not implemented yet.
|
|
8
|
+
*/
|
|
9
|
+
export class GeofencesStore extends IMateStore {
|
|
10
|
+
constructor() {
|
|
11
|
+
super("geofences", geofencesInitializer, geofencesMutator);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The coordinate of the TeslaMate geofence named `name` (case-insensitive,
|
|
15
|
+
* default "Home"), or null if there is none. Used to center a radius scope on
|
|
16
|
+
* your home without duplicating the coordinate in config.
|
|
17
|
+
*/
|
|
18
|
+
async getHome(geofenceName = "home", tx = sql()) {
|
|
19
|
+
const rows = await tx `SELECT latitude, longitude FROM geofences
|
|
20
|
+
WHERE name ILIKE ${geofenceName}
|
|
21
|
+
ORDER BY id
|
|
22
|
+
LIMIT 1`;
|
|
23
|
+
return rows[0] ?? null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
let _store = null;
|
|
27
|
+
export const geofencesStore = () => (_store ??= new GeofencesStore());
|
|
28
|
+
//# sourceMappingURL=GeofencesStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeofencesStore.js","sourceRoot":"","sources":["../../src/store/GeofencesStore.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,GAKjB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,GAAG,EAAc,MAAM,SAAS,CAAC;AAE1C;;;;GAIG;AACH,MAAM,OAAO,cAAe,SAAQ,UAKnC;IACC;QACE,KAAK,CAAC,WAAW,EAAE,oBAAoB,EAAE,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO,CAClB,eAAuB,MAAM,EAC7B,KAAY,GAAG,EAAE;QAEjB,MAAM,IAAI,GAAG,MAAM,EAAE,CAEpB;2BACsB,YAAY;;gBAEvB,CAAC;QAEb,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACzB,CAAC;CACF;AAED,IAAI,MAAM,GAA0B,IAAI,CAAC;AACzC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type SqlTx } from "./db.js";
|
|
2
|
+
import { IMateStore, type MateStoreId } from "./IMateStore.js";
|
|
3
|
+
export interface FailableMutator {
|
|
4
|
+
failure_count?: number;
|
|
5
|
+
failure_notified_at?: Date | null;
|
|
6
|
+
}
|
|
7
|
+
export interface FailableInitializer {
|
|
8
|
+
failure_count: number;
|
|
9
|
+
}
|
|
10
|
+
export interface Failable<T extends number | string> extends MateStoreId<T>, FailableInitializer {
|
|
11
|
+
}
|
|
12
|
+
export declare abstract class IFailableStore<ID extends number | string, BASE extends Failable<ID>, INITIALZER extends FailableInitializer, MUTATOR extends FailableMutator> extends IMateStore<ID, BASE, INITIALZER, MUTATOR> {
|
|
13
|
+
protected abstract parseFailure(failure_count: number): MUTATOR;
|
|
14
|
+
incrementFailed(id: string, tx?: SqlTx): Promise<number>;
|
|
15
|
+
setFailed(id: ID, failure_count: number, tx?: SqlTx): Promise<BASE>;
|
|
16
|
+
/** Clears both the failure count and the notified flag, re-arming paging. */
|
|
17
|
+
resetFailed(id: ID, tx?: SqlTx): Promise<BASE>;
|
|
18
|
+
/**
|
|
19
|
+
* Rows at or above `threshold` failures, most-failing first. With
|
|
20
|
+
* `onlyUnnotified` only rows that have not been paged yet
|
|
21
|
+
* (`failure_notified_at IS NULL`) are returned.
|
|
22
|
+
*/
|
|
23
|
+
getFailed(threshold: number, onlyUnnotified?: boolean, tx?: SqlTx): Promise<BASE[]>;
|
|
24
|
+
/** Stamp the notified flag on the given rows (empty list is a no-op). */
|
|
25
|
+
markNotified(ids: ID[], tx?: SqlTx): Promise<void>;
|
|
26
|
+
/** Reset every failing row (count + notified flag); returns rows affected. */
|
|
27
|
+
resetAllFailed(tx?: SqlTx): Promise<number>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=IFailableStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFailableStore.d.ts","sourceRoot":"","sources":["../../src/store/IFailableStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CACjD,SAAQ,WAAW,CAAC,CAAC,CAAC,EAAE,mBAAmB;CAAG;AAEhD,8BAAsB,cAAc,CAClC,EAAE,SAAS,MAAM,GAAG,MAAM,EAC1B,IAAI,SAAS,QAAQ,CAAC,EAAE,CAAC,EACzB,UAAU,SAAS,mBAAmB,EACtC,OAAO,SAAS,eAAe,CAC/B,SAAQ,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC;IACjD,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAElD,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,GAAE,KAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/D,SAAS,CACpB,EAAE,EAAE,EAAE,EACN,aAAa,EAAE,MAAM,EACrB,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,IAAI,CAAC;IAIhB,6EAA6E;IAChE,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAE,KAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlE;;;;OAIG;IACU,SAAS,CACpB,SAAS,EAAE,MAAM,EACjB,cAAc,UAAQ,EACtB,EAAE,GAAE,KAAa,GAChB,OAAO,CAAC,IAAI,EAAE,CAAC;IASlB,yEAAyE;IAC5D,YAAY,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAE,KAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtE,8EAA8E;IACjE,cAAc,CAAC,EAAE,GAAE,KAAa,GAAG,OAAO,CAAC,MAAM,CAAC;CAMhE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { sql } from "./db.js";
|
|
2
|
+
import { IMateStore } from "./IMateStore.js";
|
|
3
|
+
export class IFailableStore extends IMateStore {
|
|
4
|
+
async incrementFailed(id, tx = sql()) {
|
|
5
|
+
const [row] = await tx `
|
|
6
|
+
UPDATE ${tx(this.table)}
|
|
7
|
+
SET failure_count = failure_count + 1
|
|
8
|
+
WHERE id = ${id}
|
|
9
|
+
RETURNING failure_count
|
|
10
|
+
`;
|
|
11
|
+
return row.failure_count;
|
|
12
|
+
}
|
|
13
|
+
async setFailed(id, failure_count, tx = sql()) {
|
|
14
|
+
return await this.update(id, this.parseFailure(failure_count), tx);
|
|
15
|
+
}
|
|
16
|
+
/** Clears both the failure count and the notified flag, re-arming paging. */
|
|
17
|
+
async resetFailed(id, tx = sql()) {
|
|
18
|
+
return await this.update(id, { ...this.parseFailure(0), failure_notified_at: null }, tx);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Rows at or above `threshold` failures, most-failing first. With
|
|
22
|
+
* `onlyUnnotified` only rows that have not been paged yet
|
|
23
|
+
* (`failure_notified_at IS NULL`) are returned.
|
|
24
|
+
*/
|
|
25
|
+
async getFailed(threshold, onlyUnnotified = false, tx = sql()) {
|
|
26
|
+
return await tx `
|
|
27
|
+
SELECT * FROM ${tx(this.table)}
|
|
28
|
+
WHERE failure_count >= ${threshold}
|
|
29
|
+
${onlyUnnotified ? tx `AND failure_notified_at IS NULL` : tx ``}
|
|
30
|
+
ORDER BY failure_count DESC
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
/** Stamp the notified flag on the given rows (empty list is a no-op). */
|
|
34
|
+
async markNotified(ids, tx = sql()) {
|
|
35
|
+
await tx `UPDATE ${tx(this.table)}
|
|
36
|
+
SET failure_notified_at = CURRENT_TIMESTAMP
|
|
37
|
+
WHERE id = ANY(${ids}::bigint[])`;
|
|
38
|
+
}
|
|
39
|
+
/** Reset every failing row (count + notified flag); returns rows affected. */
|
|
40
|
+
async resetAllFailed(tx = sql()) {
|
|
41
|
+
const result = await tx `UPDATE ${tx(this.table)}
|
|
42
|
+
SET failure_count = 0, failure_notified_at = NULL
|
|
43
|
+
WHERE failure_count > 0`;
|
|
44
|
+
return result.count;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=IFailableStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFailableStore.js","sourceRoot":"","sources":["../../src/store/IFailableStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAc,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAc/D,MAAM,OAAgB,cAKpB,SAAQ,UAAyC;IAG1C,KAAK,CAAC,eAAe,CAAC,EAAU,EAAE,KAAY,GAAG,EAAE;QACxD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAAuB;eAClC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;;qBAER,EAAE;;KAElB,CAAC;QACF,OAAO,GAAG,CAAC,aAAa,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,SAAS,CACpB,EAAM,EACN,aAAqB,EACrB,KAAY,GAAG,EAAE;QAEjB,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,6EAA6E;IACtE,KAAK,CAAC,WAAW,CAAC,EAAM,EAAE,KAAY,GAAG,EAAE;QAChD,OAAO,MAAM,IAAI,CAAC,MAAM,CACtB,EAAE,EACF,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,IAAI,EAAE,EACtD,EAAE,CACH,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CACpB,SAAiB,EACjB,cAAc,GAAG,KAAK,EACtB,KAAY,GAAG,EAAE;QAEjB,OAAO,MAAM,EAAE,CAAQ;sBACL,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;iCACH,SAAS;UAChC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAA,iCAAiC,CAAC,CAAC,CAAC,EAAE,CAAA,EAAE;;KAEhE,CAAC;IACJ,CAAC;IAED,yEAAyE;IAClE,KAAK,CAAC,YAAY,CAAC,GAAS,EAAE,KAAY,GAAG,EAAE;QACpD,MAAM,EAAE,CAAA,UAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;;uBAEb,GAA0B,aAAa,CAAC;IAC7D,CAAC;IAED,8EAA8E;IACvE,KAAK,CAAC,cAAc,CAAC,KAAY,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAA,UAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;;8BAErB,CAAC;QAC3B,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import { type SqlTx } from "./db.js";
|
|
3
|
+
import type { Meta } from "../types/client.types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Run `fn` inside one transaction, serialized per `lockKey` via a Postgres
|
|
6
|
+
* advisory lock — concurrent runs on the same key wait instead of interleaving.
|
|
7
|
+
*/
|
|
8
|
+
export declare const transaction: <T>(lockKey: string, fn: (tx: SqlTx) => Promise<T>) => Promise<T>;
|
|
9
|
+
export interface MateStoreId<T extends number | string> {
|
|
10
|
+
id: T;
|
|
11
|
+
}
|
|
12
|
+
export interface FoundCoordinate<T> {
|
|
13
|
+
entity: T;
|
|
14
|
+
distanceInKm: number;
|
|
15
|
+
}
|
|
16
|
+
export declare abstract class IMateStore<ID extends number | string, BASE extends MateStoreId<ID>, INITIALZER extends object, MUTATOR extends object> {
|
|
17
|
+
readonly table: string;
|
|
18
|
+
protected readonly initializer: z.Schema<INITIALZER>;
|
|
19
|
+
protected readonly mutator: z.Schema<MUTATOR>;
|
|
20
|
+
readonly view: string | null;
|
|
21
|
+
constructor(table: string, initializer: z.Schema<INITIALZER>, mutator: z.Schema<MUTATOR>, view?: string | null);
|
|
22
|
+
createTable(tx?: SqlTx): Promise<void>;
|
|
23
|
+
get(id: ID, tx?: SqlTx): Promise<BASE | null>;
|
|
24
|
+
query(filters?: Partial<BASE>, tx?: SqlTx): Promise<BASE[]>;
|
|
25
|
+
delete(id: ID, tx?: SqlTx): Promise<void>;
|
|
26
|
+
deleteAll(tx?: SqlTx): Promise<void>;
|
|
27
|
+
insert(data: INITIALZER, tx?: SqlTx): Promise<BASE>;
|
|
28
|
+
insertMany(data: INITIALZER[], tx?: SqlTx): Promise<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Single-row `INSERT … ON CONFLICT (conflictColumn) DO UPDATE … RETURNING *`.
|
|
31
|
+
* Unlike `upsertMany` the update is unconditional, so the meta columns
|
|
32
|
+
* (`fetched_at`, `last_fetch_uuid`) advance even when the content is
|
|
33
|
+
* unchanged — callers rely on that for staleness tracking.
|
|
34
|
+
*/
|
|
35
|
+
upsertOne(data: INITIALZER, opts: {
|
|
36
|
+
conflictColumn: string;
|
|
37
|
+
/** columns SET from EXCLUDED on conflict */
|
|
38
|
+
updateColumns: string[];
|
|
39
|
+
}, tx?: SqlTx): Promise<BASE>;
|
|
40
|
+
/**
|
|
41
|
+
* Chunked `INSERT … ON CONFLICT (conflictColumn) DO UPDATE`. A conflicting
|
|
42
|
+
* row is only written when its `compareColumns` differ by value
|
|
43
|
+
* (`IS DISTINCT FROM`) from the incoming row; untouched rows are not part
|
|
44
|
+
* of the returned count.
|
|
45
|
+
*/
|
|
46
|
+
upsertMany(data: INITIALZER[], opts: {
|
|
47
|
+
conflictColumn: string;
|
|
48
|
+
/** columns SET from EXCLUDED when the row changed */
|
|
49
|
+
updateColumns: string[];
|
|
50
|
+
/** columns compared to decide whether the row changed */
|
|
51
|
+
compareColumns: string[];
|
|
52
|
+
}, tx?: SqlTx): Promise<number>;
|
|
53
|
+
/**
|
|
54
|
+
* Soft-delete every not-yet-deleted row whose id is NOT in `ids` — i.e. the
|
|
55
|
+
* rows absent from the current snapshot. Assumes the table's meta columns
|
|
56
|
+
* (`deleted_at`, `fetched_at`, `last_fetch_uuid`) and a bigint/int identity id.
|
|
57
|
+
*/
|
|
58
|
+
softDeleteWhereIdNotIn(ids: ID[], meta: Meta, tx?: SqlTx): Promise<number>;
|
|
59
|
+
/**
|
|
60
|
+
* Hard-delete every row whose id is NOT in `ids` — for tables that mirror
|
|
61
|
+
* their feed instead of soft-deleting absent rows.
|
|
62
|
+
*/
|
|
63
|
+
deleteWhereIdNotIn(ids: ID[], tx?: SqlTx): Promise<number>;
|
|
64
|
+
update(id: ID, data: MUTATOR, tx?: SqlTx): Promise<BASE>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=IMateStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IMateStore.d.ts","sourceRoot":"","sources":["../../src/store/IMateStore.ts"],"names":[],"mappings":"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"}
|