@mxpicture/tesla-superchargers-api 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/api/ChargersApi.d.ts +53 -0
- package/dist/api/ChargersApi.d.ts.map +1 -0
- package/dist/api/ChargersApi.js +173 -0
- package/dist/api/ChargersApi.js.map +1 -0
- package/dist/api/ChargingProcessesApi.d.ts +11 -0
- package/dist/api/ChargingProcessesApi.d.ts.map +1 -0
- package/dist/api/ChargingProcessesApi.js +56 -0
- package/dist/api/ChargingProcessesApi.js.map +1 -0
- package/dist/api/FailuresApi.d.ts +38 -0
- package/dist/api/FailuresApi.d.ts.map +1 -0
- package/dist/api/FailuresApi.js +88 -0
- package/dist/api/FailuresApi.js.map +1 -0
- package/dist/api/IApi.d.ts +6 -0
- package/dist/api/IApi.d.ts.map +1 -0
- package/dist/api/IApi.js +11 -0
- package/dist/api/IApi.js.map +1 -0
- package/dist/api/SlugsApi.d.ts +15 -0
- package/dist/api/SlugsApi.d.ts.map +1 -0
- package/dist/api/SlugsApi.js +68 -0
- package/dist/api/SlugsApi.js.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +7 -0
- package/dist/api/index.js.map +1 -0
- package/dist/common/chargers.common.d.ts +11 -0
- package/dist/common/chargers.common.d.ts.map +1 -0
- package/dist/common/chargers.common.js +11 -0
- package/dist/common/chargers.common.js.map +1 -0
- package/dist/common/failures.common.d.ts +8 -0
- package/dist/common/failures.common.d.ts.map +1 -0
- package/dist/common/failures.common.js +33 -0
- package/dist/common/failures.common.js.map +1 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +7 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/pricebooks.common.d.ts +47 -0
- package/dist/common/pricebooks.common.d.ts.map +1 -0
- package/dist/common/pricebooks.common.js +95 -0
- package/dist/common/pricebooks.common.js.map +1 -0
- package/dist/common/pushover.common.d.ts +23 -0
- package/dist/common/pushover.common.d.ts.map +1 -0
- package/dist/common/pushover.common.js +52 -0
- package/dist/common/pushover.common.js.map +1 -0
- package/dist/common/sync.common.d.ts +51 -0
- package/dist/common/sync.common.d.ts.map +1 -0
- package/dist/common/sync.common.js +106 -0
- package/dist/common/sync.common.js.map +1 -0
- package/dist/types/chargers.types.d.ts +8 -0
- package/dist/types/chargers.types.d.ts.map +1 -0
- package/dist/types/chargers.types.js +2 -0
- package/dist/types/chargers.types.js.map +1 -0
- package/dist/types/charging.types.d.ts +15 -0
- package/dist/types/charging.types.d.ts.map +1 -0
- package/dist/types/charging.types.js +2 -0
- package/dist/types/charging.types.js.map +1 -0
- package/dist/types/failures.types.d.ts +19 -0
- package/dist/types/failures.types.d.ts.map +1 -0
- package/dist/types/failures.types.js +2 -0
- package/dist/types/failures.types.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pricebooks.types.d.ts +28 -0
- package/dist/types/pricebooks.types.d.ts.map +1 -0
- package/dist/types/pricebooks.types.js +2 -0
- package/dist/types/pricebooks.types.js.map +1 -0
- package/dist/types/pushover.types.d.ts +12 -0
- package/dist/types/pushover.types.d.ts.map +1 -0
- package/dist/types/pushover.types.js +2 -0
- package/dist/types/pushover.types.js.map +1 -0
- package/dist/types/sync.types.d.ts +22 -0
- package/dist/types/sync.types.d.ts.map +1 -0
- package/dist/types/sync.types.js +2 -0
- package/dist/types/sync.types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Refetch a cached charger whose last fetch is older than this. */
|
|
2
|
+
export const CHARGER_STALE_AFTER_DAYS = 5;
|
|
3
|
+
/** Detail fetches per findByCoordinate call — the endpoint is slow and guarded. */
|
|
4
|
+
export const MAX_CHARGER_FETCHES = 3;
|
|
5
|
+
/** Candidates that failed this often are tried after the rest, so dead slugs stop burning the fetch budget first. */
|
|
6
|
+
export const FAILURE_DEPRIORITIZE_THRESHOLD = 3;
|
|
7
|
+
export const isFresh = (row) => row.fetched_at.getTime() >
|
|
8
|
+
Date.now() - CHARGER_STALE_AFTER_DAYS * 24 * 60 * 60 * 1000;
|
|
9
|
+
/** FK links are not part of the feed; a snapshot re-sync must not wipe them. */
|
|
10
|
+
export const withoutFkColumns = (columns) => columns.filter((column) => column !== "pic_slugs_id");
|
|
11
|
+
//# sourceMappingURL=chargers.common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chargers.common.js","sourceRoot":"","sources":["../../src/common/chargers.common.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAE1C,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,qHAAqH;AACrH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEhD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAgB,EAAW,EAAE,CACnD,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE;IACxB,IAAI,CAAC,GAAG,EAAE,GAAG,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9D,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAiB,EAAY,EAAE,CAC9D,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PushoverMessage } from "../types/pushover.types.js";
|
|
2
|
+
import type { FailedSources } from "../types/failures.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Build the Pushover message for a set of failing rows, or null when every
|
|
5
|
+
* source is empty (nothing to page). Pure — unit-tested without a request.
|
|
6
|
+
*/
|
|
7
|
+
export declare const buildFailureMessage: (failed: FailedSources) => PushoverMessage | null;
|
|
8
|
+
//# sourceMappingURL=failures.common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failures.common.d.ts","sourceRoot":"","sources":["../../src/common/failures.common.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAehE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,aAAa,KACpB,eAAe,GAAG,IA2CpB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Max rows listed per source section before truncating with a summary line. */
|
|
2
|
+
const MAX_LISTED = 10;
|
|
3
|
+
/** One titled section: up to MAX_LISTED lines, then `…and N more.` if truncated. */
|
|
4
|
+
const section = (title, lines) => {
|
|
5
|
+
const shown = lines.slice(0, MAX_LISTED).join("\n");
|
|
6
|
+
const more = lines.length > MAX_LISTED
|
|
7
|
+
? `\n…and ${lines.length - MAX_LISTED} more.`
|
|
8
|
+
: "";
|
|
9
|
+
return `${title}\n${shown}${more}`;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Build the Pushover message for a set of failing rows, or null when every
|
|
13
|
+
* source is empty (nothing to page). Pure — unit-tested without a request.
|
|
14
|
+
*/
|
|
15
|
+
export const buildFailureMessage = (failed) => {
|
|
16
|
+
const sections = [];
|
|
17
|
+
if (failed.charges.length > 0)
|
|
18
|
+
sections.push(section("Charges:", failed.charges.map((c) => `• charge #${c.charging_processes_id} ` +
|
|
19
|
+
`(${c.start_date ? c.start_date.toISOString() : "?"}): ` +
|
|
20
|
+
`${c.failure_count} failures`)));
|
|
21
|
+
if (failed.chargers.length > 0)
|
|
22
|
+
sections.push(section("Chargers:", failed.chargers.map((c) => `• ${c.name}, ${c.city}: ${c.failure_count} failures`)));
|
|
23
|
+
if (failed.slugs.length > 0)
|
|
24
|
+
sections.push(section("Slugs:", failed.slugs.map((s) => `• ${s.location_url_slug}: ${s.failure_count} failures`)));
|
|
25
|
+
if (sections.length === 0)
|
|
26
|
+
return null;
|
|
27
|
+
return {
|
|
28
|
+
title: "🚫 Supercharger failures",
|
|
29
|
+
message: sections.join("\n\n"),
|
|
30
|
+
priority: 1,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=failures.common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failures.common.js","sourceRoot":"","sources":["../../src/common/failures.common.ts"],"names":[],"mappings":"AAGA,gFAAgF;AAChF,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,oFAAoF;AACpF,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,KAAe,EAAU,EAAE;IACzD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GACR,KAAK,CAAC,MAAM,GAAG,UAAU;QACvB,CAAC,CAAC,UAAU,KAAK,CAAC,MAAM,GAAG,UAAU,QAAQ;QAC7C,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,GAAG,KAAK,KAAK,KAAK,GAAG,IAAI,EAAE,CAAC;AACrC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,MAAqB,EACG,EAAE;IAC1B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAC3B,QAAQ,CAAC,IAAI,CACX,OAAO,CACL,UAAU,EACV,MAAM,CAAC,OAAO,CAAC,GAAG,CAChB,CAAC,CAAC,EAAE,EAAE,CACJ,aAAa,CAAC,CAAC,qBAAqB,GAAG;YACvC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK;YACxD,GAAG,CAAC,CAAC,aAAa,WAAW,CAChC,CACF,CACF,CAAC;IAEJ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC5B,QAAQ,CAAC,IAAI,CACX,OAAO,CACL,WAAW,EACX,MAAM,CAAC,QAAQ,CAAC,GAAG,CACjB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,aAAa,WAAW,CAC7D,CACF,CACF,CAAC;IAEJ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACzB,QAAQ,CAAC,IAAI,CACX,OAAO,CACL,QAAQ,EACR,MAAM,CAAC,KAAK,CAAC,GAAG,CACd,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,iBAAiB,KAAK,CAAC,CAAC,aAAa,WAAW,CAC/D,CACF,CACF,CAAC;IAEJ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,OAAO;QACL,KAAK,EAAE,0BAA0B;QACjC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9B,QAAQ,EAAE,CAAC;KACZ,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file is auto-generated by build-cli. Do not edit manually.
|
|
2
|
+
export * from "./chargers.common.js";
|
|
3
|
+
export * from "./failures.common.js";
|
|
4
|
+
export * from "./pricebooks.common.js";
|
|
5
|
+
export * from "./pushover.common.js";
|
|
6
|
+
export * from "./sync.common.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure pricebook helpers: snapshot-group comparison for the history sync and
|
|
3
|
+
* the time-of-use window filter for prices-at-a-time lookups. No DB access —
|
|
4
|
+
* unit-testable in isolation.
|
|
5
|
+
*/
|
|
6
|
+
import type { ChargingRate, PricebookContent } from "../types/pricebooks.types.js";
|
|
7
|
+
/** Feed values identifying the row that prices a Tesla vehicle's charging. */
|
|
8
|
+
export declare const TESLA_VEHICLE_MAKE = "tesla";
|
|
9
|
+
export declare const CHARGING_FEE_TYPE = "charging";
|
|
10
|
+
export declare const KWH_UOM = "kwh";
|
|
11
|
+
/** Canonical `HH:MM:SS` for a TIME value (Date → its UTC wall time). */
|
|
12
|
+
export declare const normalizeTime: (time: Date | string) => string;
|
|
13
|
+
export declare const normalizeRate: (rate: string | number) => string;
|
|
14
|
+
/** One row's content columns as a canonical string, order-independent in `days`. */
|
|
15
|
+
export declare const canonicalRow: (row: PricebookContent) => string;
|
|
16
|
+
/** Local weekday (0=Sunday … 6=Saturday, matching the feed's `days`) and `HH:MM:SS` of `at` in an IANA time zone. */
|
|
17
|
+
export declare const localDayTime: (at: Date, timeZone: string) => {
|
|
18
|
+
weekday: number;
|
|
19
|
+
time: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Does this row's time-of-use window cover the instant `at` (in the charger's
|
|
23
|
+
* time zone)? Empty `days` means no day restriction (non-TOU rows). The feed
|
|
24
|
+
* partitions a day into windows that never span into the next day, with
|
|
25
|
+
* `00:00` as `end` meaning end-of-day (e.g. `00:00–16:00`, `16:00–20:00`,
|
|
26
|
+
* `20:00–00:00`); `start == end == 00:00` is a whole-day window. `end` is
|
|
27
|
+
* exclusive — each instant falls into exactly one window of a partition.
|
|
28
|
+
*/
|
|
29
|
+
export declare const pricebookCoversInstant: (row: Pick<PricebookContent, "days" | "start_time" | "end_time">, at: Date, timeZone: string) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Order-independent multiset equality over the content columns — the "did any
|
|
32
|
+
* price change?" check of the history sync. Meta columns (`fetched_at`,
|
|
33
|
+
* `last_fetch_uuid`, ids) are ignored. Normalization matters: a false
|
|
34
|
+
* "different" here creates a bogus new group on every fetch.
|
|
35
|
+
*/
|
|
36
|
+
export declare const samePricebookGroup: (a: PricebookContent[], b: PricebookContent[]) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The per-kWh rate a Tesla vehicle pays for charging, picked from the
|
|
39
|
+
* variant rows valid at one instant (member/non-member × vehicle make ×
|
|
40
|
+
* fee type, as `findPrices` returns them): fee type "charging", vehicle
|
|
41
|
+
* make "tesla", the non-member row when both memberships are present
|
|
42
|
+
* (Tesla drivers need no membership). Returns null when no such row
|
|
43
|
+
* exists or the row doesn't bill per kWh — per-minute billing depends on
|
|
44
|
+
* charging power, which stored energy totals don't carry.
|
|
45
|
+
*/
|
|
46
|
+
export declare const teslaChargingRate: (rows: PricebookContent[]) => ChargingRate | null;
|
|
47
|
+
//# sourceMappingURL=pricebooks.common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricebooks.common.d.ts","sourceRoot":"","sources":["../../src/common/pricebooks.common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAEtC,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAC1C,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAC5C,eAAO,MAAM,OAAO,QAAQ,CAAC;AAE7B,wEAAwE;AACxE,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,GAAG,MAAM,KAAG,MAInD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,GAAG,MAAM,KAAG,MAC7B,CAAC;AAE1B,oFAAoF;AACpF,eAAO,MAAM,YAAY,GAAI,KAAK,gBAAgB,KAAG,MAcxC,CAAC;AAEd,qHAAqH;AACrH,eAAO,MAAM,YAAY,GACvB,IAAI,IAAI,EACR,UAAU,MAAM,KACf;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAkBjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,KAAK,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC,EAC/D,IAAI,IAAI,EACR,UAAU,MAAM,KACf,OASF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,GAAG,gBAAgB,EAAE,EACrB,GAAG,gBAAgB,EAAE,KACpB,OAKF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,gBAAgB,EAAE,KACvB,YAAY,GAAG,IAWjB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** Feed values identifying the row that prices a Tesla vehicle's charging. */
|
|
2
|
+
export const TESLA_VEHICLE_MAKE = "tesla";
|
|
3
|
+
export const CHARGING_FEE_TYPE = "charging";
|
|
4
|
+
export const KWH_UOM = "kwh";
|
|
5
|
+
/** Canonical `HH:MM:SS` for a TIME value (Date → its UTC wall time). */
|
|
6
|
+
export const normalizeTime = (time) => {
|
|
7
|
+
if (time instanceof Date)
|
|
8
|
+
return time.toISOString().slice(11, 19); // transforms build Date(0) + UTC hours
|
|
9
|
+
const [h = "0", m = "0", s = "0"] = time.split(".")[0].split(":");
|
|
10
|
+
return [h, m, s].map((part) => part.padStart(2, "0")).join(":");
|
|
11
|
+
};
|
|
12
|
+
export const normalizeRate = (rate) => Number(rate).toFixed(2);
|
|
13
|
+
/** One row's content columns as a canonical string, order-independent in `days`. */
|
|
14
|
+
export const canonicalRow = (row) => [
|
|
15
|
+
row.currency_code,
|
|
16
|
+
row.uom,
|
|
17
|
+
[...row.days].sort((a, b) => a - b).join(","),
|
|
18
|
+
normalizeTime(row.start_time),
|
|
19
|
+
normalizeTime(row.end_time),
|
|
20
|
+
row.vehicle_make_type,
|
|
21
|
+
row.fee_type,
|
|
22
|
+
row.is_member_pricebook,
|
|
23
|
+
row.is_tou,
|
|
24
|
+
normalizeRate(row.rate_base),
|
|
25
|
+
normalizeRate(row.rate_tier_1),
|
|
26
|
+
normalizeRate(row.rate_tier_2),
|
|
27
|
+
].join("|");
|
|
28
|
+
/** Local weekday (0=Sunday … 6=Saturday, matching the feed's `days`) and `HH:MM:SS` of `at` in an IANA time zone. */
|
|
29
|
+
export const localDayTime = (at, timeZone) => {
|
|
30
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
31
|
+
timeZone,
|
|
32
|
+
weekday: "short",
|
|
33
|
+
hourCycle: "h23",
|
|
34
|
+
hour: "2-digit",
|
|
35
|
+
minute: "2-digit",
|
|
36
|
+
second: "2-digit",
|
|
37
|
+
}).formatToParts(at);
|
|
38
|
+
const part = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
39
|
+
const weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(part("weekday"));
|
|
40
|
+
return {
|
|
41
|
+
weekday,
|
|
42
|
+
time: `${part("hour")}:${part("minute")}:${part("second")}`,
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Does this row's time-of-use window cover the instant `at` (in the charger's
|
|
47
|
+
* time zone)? Empty `days` means no day restriction (non-TOU rows). The feed
|
|
48
|
+
* partitions a day into windows that never span into the next day, with
|
|
49
|
+
* `00:00` as `end` meaning end-of-day (e.g. `00:00–16:00`, `16:00–20:00`,
|
|
50
|
+
* `20:00–00:00`); `start == end == 00:00` is a whole-day window. `end` is
|
|
51
|
+
* exclusive — each instant falls into exactly one window of a partition.
|
|
52
|
+
*/
|
|
53
|
+
export const pricebookCoversInstant = (row, at, timeZone) => {
|
|
54
|
+
const { weekday, time } = localDayTime(at, timeZone);
|
|
55
|
+
if (row.days.length > 0 && !row.days.includes(weekday))
|
|
56
|
+
return false;
|
|
57
|
+
const start = normalizeTime(row.start_time);
|
|
58
|
+
const end = normalizeTime(row.end_time);
|
|
59
|
+
if (start === "00:00:00" && end === "00:00:00")
|
|
60
|
+
return true; // whole day
|
|
61
|
+
if (start > end)
|
|
62
|
+
return time >= start || time < end; // end 00:00 = end of day
|
|
63
|
+
return time >= start && time < end;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Order-independent multiset equality over the content columns — the "did any
|
|
67
|
+
* price change?" check of the history sync. Meta columns (`fetched_at`,
|
|
68
|
+
* `last_fetch_uuid`, ids) are ignored. Normalization matters: a false
|
|
69
|
+
* "different" here creates a bogus new group on every fetch.
|
|
70
|
+
*/
|
|
71
|
+
export const samePricebookGroup = (a, b) => {
|
|
72
|
+
if (a.length !== b.length)
|
|
73
|
+
return false;
|
|
74
|
+
const canonical = (rows) => rows.map(canonicalRow).sort().join("\n");
|
|
75
|
+
return canonical(a) === canonical(b);
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* The per-kWh rate a Tesla vehicle pays for charging, picked from the
|
|
79
|
+
* variant rows valid at one instant (member/non-member × vehicle make ×
|
|
80
|
+
* fee type, as `findPrices` returns them): fee type "charging", vehicle
|
|
81
|
+
* make "tesla", the non-member row when both memberships are present
|
|
82
|
+
* (Tesla drivers need no membership). Returns null when no such row
|
|
83
|
+
* exists or the row doesn't bill per kWh — per-minute billing depends on
|
|
84
|
+
* charging power, which stored energy totals don't carry.
|
|
85
|
+
*/
|
|
86
|
+
export const teslaChargingRate = (rows) => {
|
|
87
|
+
const candidates = rows.filter((row) => row.fee_type.toLowerCase() === CHARGING_FEE_TYPE &&
|
|
88
|
+
row.vehicle_make_type.toLowerCase() === TESLA_VEHICLE_MAKE);
|
|
89
|
+
const row = candidates.find((candidate) => !candidate.is_member_pricebook) ??
|
|
90
|
+
candidates[0];
|
|
91
|
+
if (!row || row.uom.toLowerCase() !== KWH_UOM)
|
|
92
|
+
return null;
|
|
93
|
+
return { rate: Number(row.rate_base), currencyCode: row.currency_code };
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=pricebooks.common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricebooks.common.js","sourceRoot":"","sources":["../../src/common/pricebooks.common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Pushover (https://pushover.net) sender. Mirrors the shape used by the
|
|
3
|
+
* sibling deployment scripts (a token/user app message with an optional
|
|
4
|
+
* priority), so it reuses the same PUSHOVER_* credentials the deployment already
|
|
5
|
+
* injects. Sending NEVER throws — a notify failure is logged and reported via
|
|
6
|
+
* the return value so it can't abort the run that is trying to alert. When
|
|
7
|
+
* either credential is missing the whole feature is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
import type { PushoverConfig, PushoverMessage } from "../types/pushover.types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Pushover credentials from `PUSHOVER_API_TOKEN` / `PUSHOVER_USER_KEY`, or null
|
|
12
|
+
* when either is unset (so the caller treats alerting as disabled).
|
|
13
|
+
*/
|
|
14
|
+
export declare const pushoverConfigFromEnv: () => PushoverConfig | null;
|
|
15
|
+
/** The form body Pushover expects. Pure, so it is unit-tested without a request. */
|
|
16
|
+
export declare const buildPushoverForm: (cfg: PushoverConfig, msg: PushoverMessage) => Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* POST one message to Pushover. Returns true on success; on any failure it logs
|
|
19
|
+
* via `logger` and returns false (never throws), so a notify error can't kill
|
|
20
|
+
* the caller.
|
|
21
|
+
*/
|
|
22
|
+
export declare const sendPushover: (cfg: PushoverConfig, msg: PushoverMessage, logger?: (m: string) => void) => Promise<boolean>;
|
|
23
|
+
//# sourceMappingURL=pushover.common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushover.common.d.ts","sourceRoot":"","sources":["../../src/common/pushover.common.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAIpC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,cAAc,GAAG,IAKzD,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,GAC5B,KAAK,cAAc,EACnB,KAAK,eAAe,KACnB,MAAM,CAAC,MAAM,EAAE,MAAM,CAMtB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAQ,CAAC,CAAC,EAAE,MAAM,KAAK,IAAe,KACrC,OAAO,CAAC,OAAO,CAkBjB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Pushover (https://pushover.net) sender. Mirrors the shape used by the
|
|
3
|
+
* sibling deployment scripts (a token/user app message with an optional
|
|
4
|
+
* priority), so it reuses the same PUSHOVER_* credentials the deployment already
|
|
5
|
+
* injects. Sending NEVER throws — a notify failure is logged and reported via
|
|
6
|
+
* the return value so it can't abort the run that is trying to alert. When
|
|
7
|
+
* either credential is missing the whole feature is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
const PUSHOVER_URL = "https://api.pushover.net/1/messages.json";
|
|
10
|
+
/**
|
|
11
|
+
* Pushover credentials from `PUSHOVER_API_TOKEN` / `PUSHOVER_USER_KEY`, or null
|
|
12
|
+
* when either is unset (so the caller treats alerting as disabled).
|
|
13
|
+
*/
|
|
14
|
+
export const pushoverConfigFromEnv = () => {
|
|
15
|
+
const token = process.env.PUSHOVER_API_TOKEN;
|
|
16
|
+
const user = process.env.PUSHOVER_USER_KEY;
|
|
17
|
+
if (!token || !user)
|
|
18
|
+
return null;
|
|
19
|
+
return { token, user };
|
|
20
|
+
};
|
|
21
|
+
/** The form body Pushover expects. Pure, so it is unit-tested without a request. */
|
|
22
|
+
export const buildPushoverForm = (cfg, msg) => ({
|
|
23
|
+
token: cfg.token,
|
|
24
|
+
user: cfg.user,
|
|
25
|
+
title: msg.title,
|
|
26
|
+
message: msg.message,
|
|
27
|
+
priority: String(msg.priority ?? 0),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* POST one message to Pushover. Returns true on success; on any failure it logs
|
|
31
|
+
* via `logger` and returns false (never throws), so a notify error can't kill
|
|
32
|
+
* the caller.
|
|
33
|
+
*/
|
|
34
|
+
export const sendPushover = async (cfg, msg, logger = () => { }) => {
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(PUSHOVER_URL, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
body: new URLSearchParams(buildPushoverForm(cfg, msg)),
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
logger(`pushover send failed: HTTP ${res.status}`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
logger(`pushover sent: ${msg.title}`);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
logger(`pushover send failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=pushover.common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushover.common.js","sourceRoot":"","sources":["../../src/common/pushover.common.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,YAAY,GAAG,0CAA0C,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAA0B,EAAE;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC3C,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC,CAAC;AAEF,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAAmB,EACnB,GAAoB,EACI,EAAE,CAAC,CAAC;IAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;IAChB,IAAI,EAAE,GAAG,CAAC,IAAI;IACd,KAAK,EAAE,GAAG,CAAC,KAAK;IAChB,OAAO,EAAE,GAAG,CAAC,OAAO;IACpB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC;CACpC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,GAAmB,EACnB,GAAoB,EACpB,SAA8B,GAAG,EAAE,GAAE,CAAC,EACpB,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,eAAe,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SACvD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,kBAAkB,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CACJ,yBAAyB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACtE,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { KeyParams } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import type { Meta } from "@mxpicture/tesla-superchargers-mate/types";
|
|
3
|
+
import type { SyncDbRow, SyncPlan, SyncSummary } from "../types/sync.types.js";
|
|
4
|
+
import { type IMateStore } from "@mxpicture/tesla-superchargers-mate/store";
|
|
5
|
+
/** Abort the sync when the feed shrinks below this share of the active rows. */
|
|
6
|
+
export declare const CIRCUIT_BREAKER_MIN_RATIO = 0.5;
|
|
7
|
+
/**
|
|
8
|
+
* Pure planning step of a snapshot sync: match feed docs to db rows by the
|
|
9
|
+
* semantic key (deduplicating the feed, first wins) and track which db ids
|
|
10
|
+
* were seen so the caller can delete the absent rest.
|
|
11
|
+
* Throws (before anything is written) when the feed looks truncated.
|
|
12
|
+
*/
|
|
13
|
+
export declare const planSync: <CLIENT, DB extends SyncDbRow, INITIALZER>(p: {
|
|
14
|
+
clientDocs: CLIENT[];
|
|
15
|
+
dbDocs: DB[];
|
|
16
|
+
toInitializer: (clientDoc: CLIENT) => INITIALZER;
|
|
17
|
+
keyOfInit: (doc: INITIALZER) => string | null;
|
|
18
|
+
keyOfDb: (doc: DB) => string | null;
|
|
19
|
+
}) => SyncPlan<INITIALZER>;
|
|
20
|
+
/**
|
|
21
|
+
* Upsert column lists from the generated initializer keys: compared columns
|
|
22
|
+
* are the feed content plus — on soft-delete tables — `deleted_at` (so
|
|
23
|
+
* returning sites resurrect even when unchanged); updated columns add the
|
|
24
|
+
* fetch meta. `failure_count`/`failure_notified_at` stay out of both — the
|
|
25
|
+
* chargers pipeline owns them after the initial insert.
|
|
26
|
+
*/
|
|
27
|
+
export declare const syncColumns: <T extends object>(initializerKeys: KeyParams<T>[]) => {
|
|
28
|
+
updateColumns: string[];
|
|
29
|
+
compareColumns: string[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Snapshot sync: plan in memory, then — in one advisory-locked transaction —
|
|
33
|
+
* delete the rows absent from the feed (`deleteAbsent`: "soft" keeps them
|
|
34
|
+
* with `deleted_at` set, "hard" removes them — the table mirrors the feed)
|
|
35
|
+
* and upsert the rest (value-compared via IS DISTINCT FROM). The delete runs
|
|
36
|
+
* first so rows the upsert is about to insert cannot be caught by the
|
|
37
|
+
* absence check.
|
|
38
|
+
*/
|
|
39
|
+
export declare const syncSnapshot: <CLIENT, DB extends SyncDbRow, INITIALZER extends object>(p: {
|
|
40
|
+
store: IMateStore<string, DB, INITIALZER, any>;
|
|
41
|
+
clientDocs: CLIENT[];
|
|
42
|
+
meta: Meta;
|
|
43
|
+
toInitializer: (clientDoc: CLIENT) => INITIALZER;
|
|
44
|
+
keyOfInit: (doc: INITIALZER) => string | null;
|
|
45
|
+
keyOfDb: (doc: DB) => string | null;
|
|
46
|
+
deleteAbsent: "hard" | "soft";
|
|
47
|
+
conflictColumn: string;
|
|
48
|
+
updateColumns: string[];
|
|
49
|
+
compareColumns: string[];
|
|
50
|
+
}) => Promise<SyncSummary>;
|
|
51
|
+
//# sourceMappingURL=sync.common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.common.d.ts","sourceRoot":"","sources":["../../src/common/sync.common.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,2CAA2C,CAAC;AAEnD,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,MAAM,EAAE,EAAE,SAAS,SAAS,EAAE,UAAU,EAAE,GAAG;IACpE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,EAAE,EAAE,CAAC;IACb,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,CAAC;IACjD,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;CACrC,KAAG,QAAQ,CAAC,UAAU,CA6CtB,CAAC;AAUF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,EAC1C,iBAAiB,SAAS,CAAC,CAAC,CAAC,EAAE,KAC9B;IAAE,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAUrD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,EACN,EAAE,SAAS,SAAS,EACpB,UAAU,SAAS,MAAM,EACzB,GAAG;IAEH,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,CAAC;IACjD,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,KAAG,OAAO,CAAC,WAAW,CAiCnB,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { transaction, } from "@mxpicture/tesla-superchargers-mate/store";
|
|
2
|
+
/** Abort the sync when the feed shrinks below this share of the active rows. */
|
|
3
|
+
export const CIRCUIT_BREAKER_MIN_RATIO = 0.5;
|
|
4
|
+
/**
|
|
5
|
+
* Pure planning step of a snapshot sync: match feed docs to db rows by the
|
|
6
|
+
* semantic key (deduplicating the feed, first wins) and track which db ids
|
|
7
|
+
* were seen so the caller can delete the absent rest.
|
|
8
|
+
* Throws (before anything is written) when the feed looks truncated.
|
|
9
|
+
*/
|
|
10
|
+
export const planSync = (p) => {
|
|
11
|
+
const activeCount = p.dbDocs.filter((doc) => doc.deleted_at == null).length;
|
|
12
|
+
if (activeCount > 0 &&
|
|
13
|
+
p.clientDocs.length < activeCount * CIRCUIT_BREAKER_MIN_RATIO)
|
|
14
|
+
throw new Error(`sync aborted: feed has ${p.clientDocs.length} docs for ${activeCount} active rows` +
|
|
15
|
+
` (circuit breaker ratio ${CIRCUIT_BREAKER_MIN_RATIO}) — refusing to mass soft-delete`);
|
|
16
|
+
const dbByKey = new Map();
|
|
17
|
+
for (const dbDoc of p.dbDocs) {
|
|
18
|
+
const key = p.keyOfDb(dbDoc);
|
|
19
|
+
if (key !== null)
|
|
20
|
+
dbByKey.set(key, dbDoc);
|
|
21
|
+
}
|
|
22
|
+
const plan = {
|
|
23
|
+
upserts: [],
|
|
24
|
+
seenIds: [],
|
|
25
|
+
feedDuplicates: 0,
|
|
26
|
+
feedNullKeys: 0,
|
|
27
|
+
};
|
|
28
|
+
const seenKeys = new Set();
|
|
29
|
+
for (const clientDoc of p.clientDocs) {
|
|
30
|
+
const newDoc = p.toInitializer(clientDoc);
|
|
31
|
+
const key = p.keyOfInit(newDoc);
|
|
32
|
+
if (key === null) {
|
|
33
|
+
plan.feedNullKeys++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (seenKeys.has(key)) {
|
|
37
|
+
plan.feedDuplicates++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
seenKeys.add(key);
|
|
41
|
+
const dbDoc = dbByKey.get(key);
|
|
42
|
+
if (dbDoc !== undefined)
|
|
43
|
+
plan.seenIds.push(dbDoc.id);
|
|
44
|
+
plan.upserts.push(newDoc);
|
|
45
|
+
}
|
|
46
|
+
return plan;
|
|
47
|
+
};
|
|
48
|
+
const SYNC_META_COLUMNS = [
|
|
49
|
+
"fetched_at",
|
|
50
|
+
"last_fetch_uuid",
|
|
51
|
+
"failure_count",
|
|
52
|
+
"failure_notified_at",
|
|
53
|
+
"deleted_at",
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Upsert column lists from the generated initializer keys: compared columns
|
|
57
|
+
* are the feed content plus — on soft-delete tables — `deleted_at` (so
|
|
58
|
+
* returning sites resurrect even when unchanged); updated columns add the
|
|
59
|
+
* fetch meta. `failure_count`/`failure_notified_at` stay out of both — the
|
|
60
|
+
* chargers pipeline owns them after the initial insert.
|
|
61
|
+
*/
|
|
62
|
+
export const syncColumns = (initializerKeys) => {
|
|
63
|
+
const names = initializerKeys.map((key) => key.name);
|
|
64
|
+
const content = names.filter((name) => !SYNC_META_COLUMNS.includes(name));
|
|
65
|
+
const compareColumns = names.includes("deleted_at")
|
|
66
|
+
? [...content, "deleted_at"]
|
|
67
|
+
: content;
|
|
68
|
+
return {
|
|
69
|
+
compareColumns,
|
|
70
|
+
updateColumns: [...compareColumns, "fetched_at", "last_fetch_uuid"],
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Snapshot sync: plan in memory, then — in one advisory-locked transaction —
|
|
75
|
+
* delete the rows absent from the feed (`deleteAbsent`: "soft" keeps them
|
|
76
|
+
* with `deleted_at` set, "hard" removes them — the table mirrors the feed)
|
|
77
|
+
* and upsert the rest (value-compared via IS DISTINCT FROM). The delete runs
|
|
78
|
+
* first so rows the upsert is about to insert cannot be caught by the
|
|
79
|
+
* absence check.
|
|
80
|
+
*/
|
|
81
|
+
export const syncSnapshot = async (p) => await transaction(p.store.table, async (tx) => {
|
|
82
|
+
const dbDocs = await p.store.query(undefined, tx);
|
|
83
|
+
const plan = planSync({
|
|
84
|
+
clientDocs: p.clientDocs,
|
|
85
|
+
dbDocs,
|
|
86
|
+
toInitializer: p.toInitializer,
|
|
87
|
+
keyOfInit: p.keyOfInit,
|
|
88
|
+
keyOfDb: p.keyOfDb,
|
|
89
|
+
});
|
|
90
|
+
const deleted = p.deleteAbsent === "hard"
|
|
91
|
+
? await p.store.deleteWhereIdNotIn(plan.seenIds, tx)
|
|
92
|
+
: await p.store.softDeleteWhereIdNotIn(plan.seenIds, p.meta, tx);
|
|
93
|
+
const upserted = await p.store.upsertMany(plan.upserts, {
|
|
94
|
+
conflictColumn: p.conflictColumn,
|
|
95
|
+
updateColumns: p.updateColumns,
|
|
96
|
+
compareColumns: p.compareColumns,
|
|
97
|
+
}, tx);
|
|
98
|
+
return {
|
|
99
|
+
feedCount: p.clientDocs.length,
|
|
100
|
+
feedDuplicates: plan.feedDuplicates,
|
|
101
|
+
feedNullKeys: plan.feedNullKeys,
|
|
102
|
+
upserted,
|
|
103
|
+
deleted,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=sync.common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.common.js","sourceRoot":"","sources":["../../src/common/sync.common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PicSlugsId } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
export interface ChargerCandidate {
|
|
3
|
+
/** slug for the details endpoint (location_url_slug) */
|
|
4
|
+
slug: string;
|
|
5
|
+
slugsId: PicSlugsId;
|
|
6
|
+
failureCount: number;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=chargers.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chargers.types.d.ts","sourceRoot":"","sources":["../../src/types/chargers.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iDAAiD,CAAC;AAElF,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chargers.types.js","sourceRoot":"","sources":["../../src/types/chargers.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { UnpricedChargingProcess } from "@mxpicture/tesla-superchargers-mate/types";
|
|
2
|
+
import type { ChargingRate } from "./pricebooks.types.js";
|
|
3
|
+
export interface PricingSummaryItem {
|
|
4
|
+
charge: UnpricedChargingProcess;
|
|
5
|
+
topic: "chargeUpdated" | "noRate" | "noEnergyValue" | "failureLimitReached" | "unknown";
|
|
6
|
+
energy?: string | null;
|
|
7
|
+
rate?: ChargingRate | null;
|
|
8
|
+
cost?: number | null;
|
|
9
|
+
failure_count?: number | null;
|
|
10
|
+
}
|
|
11
|
+
export interface PricingSummary {
|
|
12
|
+
unpricedCharges: number;
|
|
13
|
+
items: PricingSummaryItem[];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=charging.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charging.types.d.ts","sourceRoot":"","sources":["../../src/types/charging.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,uBAAuB,CAAC;IAChC,KAAK,EACD,eAAe,GACf,QAAQ,GACR,eAAe,GACf,qBAAqB,GACrB,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charging.types.js","sourceRoot":"","sources":["../../src/types/charging.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PicChargers, PicSlugs } from "@mxpicture/tesla-superchargers-generated/public";
|
|
2
|
+
import type { FailedChargingProcessState } from "@mxpicture/tesla-superchargers-mate/types";
|
|
3
|
+
/** The three failure-tracked sources. */
|
|
4
|
+
export type FailureSource = "charges" | "chargers" | "slugs";
|
|
5
|
+
/** Failing rows grouped by source; a non-requested source stays empty. */
|
|
6
|
+
export interface FailedSources {
|
|
7
|
+
charges: FailedChargingProcessState[];
|
|
8
|
+
chargers: PicChargers[];
|
|
9
|
+
slugs: PicSlugs[];
|
|
10
|
+
}
|
|
11
|
+
/** Outcome of a notify run: whether Pushover was configured/sent and per-source counts. */
|
|
12
|
+
export interface FailureNotifySummary {
|
|
13
|
+
configured: boolean;
|
|
14
|
+
sent: boolean;
|
|
15
|
+
charges: number;
|
|
16
|
+
chargers: number;
|
|
17
|
+
slugs: number;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=failures.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failures.types.d.ts","sourceRoot":"","sources":["../../src/types/failures.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACT,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAE5F,yCAAyC;AACzC,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7D,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,2FAA2F;AAC3F,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failures.types.js","sourceRoot":"","sources":["../../src/types/failures.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This file is auto-generated by build-cli. Do not edit manually.
|
|
2
|
+
export * from "./chargers.types.js";
|
|
3
|
+
export * from "./charging.types.js";
|
|
4
|
+
export * from "./failures.types.js";
|
|
5
|
+
export * from "./pricebooks.types.js";
|
|
6
|
+
export * from "./pushover.types.js";
|
|
7
|
+
export * from "./sync.types.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
|