@mxpicture/tesla-superchargers-http 0.1.26 → 0.1.27

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.
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,YAAY,CAAC;AAwB1D;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAO,eAmE/B,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,YAAY,CAAC;AAwB1D;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAO,eAoF/B,CAAC"}
package/dist/commands.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { chargersApi, chargingProcessesApi, failuresApi, invoicesApi, slugsApi, } from "@mxpicture/tesla-superchargers-api/api";
2
2
  import { HttpError } from "./errors.js";
3
- import { coordinate, flag, locale, maxFetches, optString, optTimestamp, radiusKm, source, threshold, } from "./params.js";
3
+ import { coordinate, favourite, flag, id, locale, maxFetches, optString, optTimestamp, radiusKm, source, threshold, } from "./params.js";
4
4
  /** reset-failures: exactly one of `id` (a single row) or `all` (the source). */
5
5
  const resetFailures = async (params) => {
6
6
  const src = source(params);
@@ -22,43 +22,59 @@ const resetFailures = async (params) => {
22
22
  * side-effecting actions answer POST with a JSON body.
23
23
  */
24
24
  export const buildCommands = () => ({
25
- "find-slug": {
25
+ "get-slug": {
26
26
  method: "GET",
27
27
  run: (p) => slugsApi().get(coordinate(p), radiusKm(p)),
28
28
  },
29
- "find-slugs": {
29
+ "query-slugs": {
30
30
  method: "GET",
31
31
  run: (p) => slugsApi().query(coordinate(p), radiusKm(p)),
32
32
  },
33
- "find-charger": {
33
+ "get-charger": {
34
34
  method: "GET",
35
- run: (p) => chargersApi().get(coordinate(p), locale(p), radiusKm(p)),
35
+ run: (p) => chargersApi().get(id(p)),
36
36
  },
37
- "find-chargers": {
37
+ "query-chargers": {
38
38
  method: "GET",
39
- run: (p) => chargersApi().query(coordinate(p), locale(p), radiusKm(p), undefined, maxFetches(p)),
39
+ run: (p) => chargersApi().query({ coord: coordinate(p), radiusKm: radiusKm(p) }),
40
40
  },
41
- "find-prices": {
41
+ "query-fav-chargers": {
42
42
  method: "GET",
43
- run: (p) => chargersApi().getPrices(coordinate(p), optTimestamp(p, "at") ?? new Date(), radiusKm(p)),
43
+ run: () => chargersApi().queryFavourites(),
44
44
  },
45
- "find-unpriced-charges": {
45
+ "update-fav-charger": {
46
+ method: "GET",
47
+ run: (p) => chargersApi().updateFavourite(id(p), favourite(p)),
48
+ },
49
+ "fetch-charger": {
50
+ method: "GET",
51
+ run: (p) => chargersApi().fetchSingle(coordinate(p), locale(p), radiusKm(p)),
52
+ },
53
+ "fetch-chargers": {
54
+ method: "GET",
55
+ run: (p) => chargersApi().fetch(coordinate(p), locale(p), radiusKm(p), undefined, maxFetches(p)),
56
+ },
57
+ "fetch-prices": {
58
+ method: "GET",
59
+ run: (p) => chargersApi().fetchPrices(coordinate(p), optTimestamp(p, "at") ?? new Date(), radiusKm(p)),
60
+ },
61
+ "query-unpriced-charges": {
46
62
  method: "GET",
47
63
  run: () => chargingProcessesApi().getUnpricedCharges(),
48
64
  },
49
- "find-failures": {
65
+ "query-failures": {
50
66
  method: "GET",
51
67
  run: (p) => failuresApi().getFailed(source(p), threshold(p)),
52
68
  },
53
- "find-unmatched-invoices": {
69
+ "query-unmatched-invoices": {
54
70
  method: "GET",
55
- run: () => invoicesApi().getUnmatched(),
71
+ run: () => invoicesApi().queryUnmatched(),
56
72
  },
57
73
  "sync-invoices-dropbox": {
58
74
  method: "POST",
59
75
  run: () => invoicesApi().syncDropbox(),
60
76
  },
61
- "process-unpriced-charges": {
77
+ "run-unpriced-charges": {
62
78
  method: "POST",
63
79
  run: () => chargingProcessesApi().runPricing(),
64
80
  },
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,QAAQ,GACT,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,gFAAgF;AAChF,MAAM,aAAa,GAAG,KAAK,EAAE,MAAc,EAAoB,EAAE;IAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,KAAK,GAAG;QAC5B,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,sCAAsC,CAAC,CAAC;IAEnE,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACrB,IAAI,GAAG,KAAK,KAAK;YACf,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,gEAAgE,CACjE,CAAC;QACJ,MAAM,WAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACzC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,MAAM,WAAW,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAoB,EAAE,CAAC,CAAC;IACnD,WAAW,EAAE;QACX,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;KACvD;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;KACzD;IACD,cAAc,EAAE;QACd,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;KACrE;IACD,eAAe,EAAE;QACf,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CACT,WAAW,EAAE,CAAC,KAAK,CACjB,UAAU,CAAC,CAAC,CAAC,EACb,MAAM,CAAC,CAAC,CAAC,EACT,QAAQ,CAAC,CAAC,CAAC,EACX,SAAS,EACT,UAAU,CAAC,CAAC,CAAC,CACd;KACJ;IACD,aAAa,EAAE;QACb,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CACT,WAAW,EAAE,CAAC,SAAS,CACrB,UAAU,CAAC,CAAC,CAAC,EACb,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,EACnC,QAAQ,CAAC,CAAC,CAAC,CACZ;KACJ;IACD,uBAAuB,EAAE;QACvB,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC,kBAAkB,EAAE;KACvD;IACD,eAAe,EAAE;QACf,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;KAC7D;IACD,yBAAyB,EAAE;QACzB,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,YAAY,EAAE;KACxC;IAED,uBAAuB,EAAE;QACvB,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE;KACvC;IACD,0BAA0B,EAAE;QAC1B,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC,UAAU,EAAE;KAC/C;IACD,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;KAC7B;IACD,gBAAgB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE;IACxD,iBAAiB,EAAE;QACjB,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC;KACpE;IACD,2BAA2B,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC;KACtD;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,13 +6,13 @@
6
6
  * `@mxpicture/tesla-superchargers-api`) as bearer-token-authenticated
7
7
  * endpoints — one per command:
8
8
  *
9
- * GET /find-charger?lat&lon
10
- * GET /find-prices?lat&lon[&at]
11
- * GET /find-unpriced-charges
12
- * GET /find-failures[?source&threshold]
13
- * GET /find-unmatched-invoices
9
+ * GET /fetch-charger?lat&lon
10
+ * GET /fetch-prices?lat&lon[&at]
11
+ * GET /query-unpriced-charges
12
+ * GET /query-failures[?source&threshold]
13
+ * GET /query-unmatched-invoices
14
14
  * POST /sync-invoices-dropbox
15
- * POST /process-unpriced-charges
15
+ * POST /run-unpriced-charges
16
16
  * POST /reset-failures body: { source, id } | { source, all: true }
17
17
  * POST /notify-failures body: { threshold? }
18
18
  * POST /notify-unmatched-invoices
package/dist/params.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { FailureSource } from "@mxpicture/tesla-superchargers-api/types";
2
2
  import type { Params } from "./types.js";
3
+ export declare const boolValue: (params: Params, key: string) => boolean;
4
+ export declare const stringValue: (params: Params, key: string) => string;
3
5
  /** A present, non-empty scalar as a string; absent/empty → undefined. */
4
6
  export declare const optString: (params: Params, key: string) => string | undefined;
5
7
  /** The `lat`/`lon` pair as a coordinate; missing or non-numeric → 400. */
@@ -7,6 +9,8 @@ export declare const coordinate: (params: Params) => {
7
9
  latitude: number;
8
10
  longitude: number;
9
11
  };
12
+ export declare const id: (params: Params) => string;
13
+ export declare const favourite: (params: Params) => boolean;
10
14
  export declare const radiusKm: (params: Params) => number;
11
15
  export declare const locale: (params: Params) => string;
12
16
  /** An optional ISO-8601 timestamp; present but unparseable → 400. */
@@ -1 +1 @@
1
- {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC,yEAAyE;AACzE,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAOhE,CAAC;AAcF,0EAA0E;AAC1E,eAAO,MAAM,UAAU,GACrB,QAAQ,MAAM,KACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAGtC,CAAC;AAEH,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,KAAG,MACT,CAAC;AAElC,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,KAAG,MACF,CAAC;AAEvC,qEAAqE;AACrE,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,IAAI,GAAG,SASjE,CAAC;AAIF,uEAAuE;AACvE,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,KAAG,aAAa,GAAG,KAMvD,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,KAAG,MAQ1C,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,KAAG,MAQ3C,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OAGlD,CAAC"}
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OASvD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAOzD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAOhE,CAAC;AAcF,0EAA0E;AAC1E,eAAO,MAAM,UAAU,GACrB,QAAQ,MAAM,KACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAGtC,CAAC;AAEH,eAAO,MAAM,EAAE,GAAI,QAAQ,MAAM,WAA8B,CAAC;AAEhE,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,YAAmC,CAAC;AAE5E,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,KAAG,MACT,CAAC;AAElC,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,KAAG,MACF,CAAC;AAEvC,qEAAqE;AACrE,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,IAAI,GAAG,SASjE,CAAC;AAIF,uEAAuE;AACvE,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,KAAG,aAAa,GAAG,KAMvD,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,KAAG,MAQ1C,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,KAAG,MAQ3C,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,OAGlD,CAAC"}
package/dist/params.js CHANGED
@@ -3,6 +3,22 @@ import { HttpError } from "./errors.js";
3
3
  const bad = (message) => {
4
4
  throw new HttpError(400, message);
5
5
  };
6
+ export const boolValue = (params, key) => {
7
+ const value = params[key];
8
+ if (value === null || value === undefined)
9
+ return bad(`'${key}' not provided`);
10
+ if (typeof value !== "boolean")
11
+ return bad(`'${key}' wrong type. expected "boolean", got ${typeof value}`);
12
+ return value;
13
+ };
14
+ export const stringValue = (params, key) => {
15
+ const value = params[key];
16
+ if (value === null || value === undefined)
17
+ return bad(`'${key}' not provided`);
18
+ if (typeof value !== "string")
19
+ return bad(`'${key}' wrong type. expected "string", got ${typeof value}`);
20
+ return value;
21
+ };
6
22
  /** A present, non-empty scalar as a string; absent/empty → undefined. */
7
23
  export const optString = (params, key) => {
8
24
  const value = params[key];
@@ -30,6 +46,8 @@ export const coordinate = (params) => ({
30
46
  latitude: numberValue(params, "lat"),
31
47
  longitude: numberValue(params, "lon"),
32
48
  });
49
+ export const id = (params) => stringValue(params, "id");
50
+ export const favourite = (params) => boolValue(params, "favourite");
33
51
  export const radiusKm = (params) => numberValue(params, "radiusKm");
34
52
  export const locale = (params) => params.locale ?? "de-DE";
35
53
  /** An optional ISO-8601 timestamp; present but unparseable → 400. */
@@ -1 +1 @@
1
- {"version":3,"file":"params.js","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"params.js","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts CHANGED
@@ -13,5 +13,5 @@
13
13
  * The inner <script> deliberately avoids template literals so it can live inside
14
14
  * this outer template string without escaping.
15
15
  */
16
- export declare const UI_HTML = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Tesla Superchargers</title>\n<style>\n :root {\n --bg: #f6f7f9; --card: #ffffff; --ink: #1a1d21; --muted: #6b7280;\n --line: #e4e7eb; --accent: #2563eb; --action: #b45309; --ok: #047857;\n --err: #b91c1c; --code-bg: #0f172a; --code-ink: #e2e8f0;\n }\n @media (prefers-color-scheme: dark) {\n :root {\n --bg: #0f1216; --card: #171b21; --ink: #e6e8eb; --muted: #9aa4b2;\n --line: #262b33; --accent: #60a5fa; --action: #f59e0b; --ok: #34d399;\n --err: #f87171; --code-bg: #0b0f16; --code-ink: #dbe2ea;\n }\n }\n * { box-sizing: border-box; }\n body {\n margin: 0; background: var(--bg); color: var(--ink);\n font: 15px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;\n }\n header {\n padding: 20px 24px; border-bottom: 1px solid var(--line);\n display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;\n }\n header h1 { margin: 0; font-size: 18px; font-weight: 650; }\n header p { margin: 0; color: var(--muted); font-size: 13px; }\n main {\n max-width: 1100px; margin: 0 auto; padding: 24px;\n display: grid; gap: 16px;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n .card {\n background: var(--card); border: 1px solid var(--line); border-radius: 10px;\n padding: 16px; display: flex; flex-direction: column; gap: 10px;\n }\n .card .title { display: flex; align-items: center; gap: 8px; }\n .card h2 { margin: 0; font-size: 15px; font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }\n .badge {\n font-size: 11px; font-weight: 700; letter-spacing: .03em; padding: 2px 6px;\n border-radius: 5px; color: #fff;\n }\n .badge.get { background: var(--accent); }\n .badge.post { background: var(--action); }\n .desc { margin: 0; color: var(--muted); font-size: 13px; }\n .fields { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\n .field { display: flex; flex-direction: column; gap: 3px; }\n .field.wide { grid-column: 1 / -1; }\n .field label { font-size: 12px; color: var(--muted); }\n .field input, .field select {\n padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px;\n background: var(--bg); color: var(--ink); font-size: 14px; width: 100%;\n }\n .row { display: flex; align-items: center; gap: 8px; margin-top: 2px; }\n button {\n align-self: flex-start; padding: 7px 14px; border: 0; border-radius: 7px;\n background: var(--accent); color: #fff; font-size: 14px; font-weight: 600;\n cursor: pointer;\n }\n .card.action button { background: var(--action); }\n button:disabled { opacity: .55; cursor: default; }\n pre.result {\n margin: 0; padding: 10px 12px; border-radius: 8px; background: var(--code-bg);\n color: var(--code-ink); font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;\n max-height: 340px; overflow: auto; white-space: pre-wrap; word-break: break-word;\n border-left: 3px solid var(--line);\n }\n pre.result.ok { border-left-color: var(--ok); }\n pre.result.err { border-left-color: var(--err); }\n pre.result.running { border-left-color: var(--accent); color: var(--muted); }\n</style>\n</head>\n<body>\n<header>\n <h1>Tesla Superchargers</h1>\n <p>Run a command against the price-history database. Actions are highlighted and ask to confirm.</p>\n</header>\n<main id=\"commands\"></main>\n<script>\n(function () {\n var F = {\n lat: { name: \"lat\", label: \"Latitude\", type: \"text\", placeholder: \"49.3135644\", required: true },\n lon: { name: \"lon\", label: \"Longitude\", type: \"text\", placeholder: \"12.1445587\", required: true },\n radiusKm: { name: \"radiusKm\", label: \"Radius (km)\", type: \"number\", placeholder: \"default\" },\n locale: { name: \"locale\", label: \"Locale\", type: \"text\", placeholder: \"de-DE\" },\n maxFetches: { name: \"maxFetches\", label: \"Max fetches\", type: \"number\", placeholder: \"default\" },\n at: { name: \"at\", label: \"At (local)\", type: \"datetime-local\", wide: true },\n source: { name: \"source\", label: \"Source\", type: \"select\", options: [\"all\", \"charges\", \"chargers\", \"slugs\"] },\n sourceCon: { name: \"source\", label: \"Source\", type: \"select\", options: [\"charges\", \"chargers\", \"slugs\", \"all\"] },\n threshold: { name: \"threshold\", label: \"Threshold\", type: \"number\", placeholder: \"default\" },\n id: { name: \"id\", label: \"Id\", type: \"text\", placeholder: \"reset all if empty\", wide: true }\n };\n\n var COMMANDS = [\n { name: \"find-slugs\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.radiusKm],\n desc: \"Nearest location slugs (tesla_uuid) to a coordinate.\" },\n { name: \"find-chargers\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.locale, F.radiusKm, F.maxFetches],\n desc: \"Nearest chargers to a coordinate. May fetch tesla.com on demand \u2014 can be slow.\" },\n { name: \"find-prices\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.at, F.radiusKm],\n desc: \"Supercharger prices valid at a time (default now) for a coordinate.\" },\n { name: \"find-unpriced-charges\", method: \"GET\", kind: \"read\", fields: [],\n desc: \"TeslaMate Supercharger charges with no cost yet.\" },\n { name: \"find-failures\", method: \"GET\", kind: \"read\", fields: [F.source, F.threshold],\n desc: \"Rows with repeated failures at or above the threshold.\" },\n { name: \"find-unmatched-invoices\", method: \"GET\", kind: \"read\", fields: [],\n desc: \"Supercharger charges without a matched invoice.\" },\n { name: \"sync-invoices-dropbox\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Import Tesla charging-history CSV exports from Dropbox.\" },\n { name: \"process-unpriced-charges\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Backfill cost on unpriced charges from stored Supercharger prices.\" },\n { name: \"sync-slugs\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Snapshot-sync pic_slugs against the live Tesla map feed.\" },\n { name: \"reset-failures\", method: \"POST\", kind: \"action\", fields: [F.sourceCon, F.id],\n desc: \"Clear failure state. Leave id empty to reset ALL rows of the source.\",\n buildBody: function (v) { return v.id ? { source: v.source, id: v.id } : { source: v.source, all: true }; } }\n ];\n\n function el(tag, attrs, text) {\n var e = document.createElement(tag);\n if (attrs) for (var k in attrs) e.setAttribute(k, attrs[k]);\n if (text != null) e.textContent = text;\n return e;\n }\n\n function fieldNode(f) {\n var wrap = el(\"div\", { class: \"field\" + (f.wide ? \" wide\" : \"\") });\n wrap.appendChild(el(\"label\", null, f.label));\n var input;\n if (f.type === \"select\") {\n input = el(\"select\", { name: f.name });\n f.options.forEach(function (o) { input.appendChild(el(\"option\", { value: o }, o)); });\n } else {\n input = el(\"input\", { name: f.name, type: f.type });\n if (f.placeholder) input.setAttribute(\"placeholder\", f.placeholder);\n }\n wrap.appendChild(input);\n return wrap;\n }\n\n function collect(cmd, form) {\n var values = {};\n cmd.fields.forEach(function (f) {\n var input = form.elements[f.name];\n var val = input ? String(input.value).trim() : \"\";\n if (f.type === \"datetime-local\" && val) val = new Date(val).toISOString();\n if (val !== \"\") values[f.name] = val;\n });\n return values;\n }\n\n function show(out, cls, text) {\n out.hidden = false;\n out.className = \"result \" + cls;\n out.textContent = text;\n }\n\n function pretty(text) {\n try { return JSON.stringify(JSON.parse(text), null, 2); } catch (e) { return text; }\n }\n\n function run(cmd, form, out, btn) {\n var values = collect(cmd, form);\n for (var i = 0; i < cmd.fields.length; i++) {\n var f = cmd.fields[i];\n if (f.required && !values[f.name]) { show(out, \"err\", \"Please fill in \" + f.label + \".\"); return; }\n }\n\n var url = \"/\" + cmd.name;\n var opts = { method: cmd.method, headers: {} };\n if (cmd.method === \"GET\") {\n var qs = new URLSearchParams(values).toString();\n if (qs) url += \"?\" + qs;\n } else {\n if (!window.confirm(\"Run \" + cmd.name + \"? This performs a real action.\")) return;\n var body = cmd.buildBody ? cmd.buildBody(values) : values;\n opts.headers[\"content-type\"] = \"application/json\";\n opts.body = JSON.stringify(body);\n }\n\n btn.disabled = true;\n show(out, \"running\", \"Running\u2026\");\n fetch(url, opts).then(function (res) {\n return res.text().then(function (text) {\n if (res.ok) show(out, \"ok\", pretty(text));\n else if (res.status === 401) show(out, \"err\", \"401 Unauthorized \u2014 sign in via the SSO portal (running locally, the command endpoints need the bearer token).\");\n else show(out, \"err\", res.status + \" \u2014 \" + pretty(text));\n });\n }).catch(function (e) {\n show(out, \"err\", \"Request failed: \" + (e && e.message ? e.message : e));\n }).then(function () { btn.disabled = false; });\n }\n\n function card(cmd) {\n var form = el(\"form\", { class: \"card \" + cmd.kind });\n var title = el(\"div\", { class: \"title\" });\n title.appendChild(el(\"span\", { class: \"badge \" + (cmd.method === \"GET\" ? \"get\" : \"post\") }, cmd.method));\n title.appendChild(el(\"h2\", null, cmd.name));\n form.appendChild(title);\n form.appendChild(el(\"p\", { class: \"desc\" }, cmd.desc));\n\n if (cmd.fields.length) {\n var fields = el(\"div\", { class: \"fields\" });\n cmd.fields.forEach(function (f) { fields.appendChild(fieldNode(f)); });\n form.appendChild(fields);\n }\n\n var btn = el(\"button\", { type: \"submit\" }, cmd.kind === \"action\" ? \"Run action\" : \"Run\");\n form.appendChild(btn);\n var out = el(\"pre\", { class: \"result\", hidden: \"hidden\" });\n form.appendChild(out);\n\n form.addEventListener(\"submit\", function (e) { e.preventDefault(); run(cmd, form, out, btn); });\n return form;\n }\n\n var root = document.getElementById(\"commands\");\n COMMANDS.forEach(function (cmd) { root.appendChild(card(cmd)); });\n})();\n</script>\n</body>\n</html>\n";
16
+ export declare const UI_HTML = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Tesla Superchargers</title>\n<style>\n :root {\n --bg: #f6f7f9; --card: #ffffff; --ink: #1a1d21; --muted: #6b7280;\n --line: #e4e7eb; --accent: #2563eb; --action: #b45309; --ok: #047857;\n --err: #b91c1c; --code-bg: #0f172a; --code-ink: #e2e8f0;\n }\n @media (prefers-color-scheme: dark) {\n :root {\n --bg: #0f1216; --card: #171b21; --ink: #e6e8eb; --muted: #9aa4b2;\n --line: #262b33; --accent: #60a5fa; --action: #f59e0b; --ok: #34d399;\n --err: #f87171; --code-bg: #0b0f16; --code-ink: #dbe2ea;\n }\n }\n * { box-sizing: border-box; }\n body {\n margin: 0; background: var(--bg); color: var(--ink);\n font: 15px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;\n }\n header {\n padding: 20px 24px; border-bottom: 1px solid var(--line);\n display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;\n }\n header h1 { margin: 0; font-size: 18px; font-weight: 650; }\n header p { margin: 0; color: var(--muted); font-size: 13px; }\n main {\n max-width: 1100px; margin: 0 auto; padding: 24px;\n display: grid; gap: 16px;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n }\n .card {\n background: var(--card); border: 1px solid var(--line); border-radius: 10px;\n padding: 16px; display: flex; flex-direction: column; gap: 10px;\n }\n .card .title { display: flex; align-items: center; gap: 8px; }\n .card h2 { margin: 0; font-size: 15px; font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }\n .badge {\n font-size: 11px; font-weight: 700; letter-spacing: .03em; padding: 2px 6px;\n border-radius: 5px; color: #fff;\n }\n .badge.get { background: var(--accent); }\n .badge.post { background: var(--action); }\n .desc { margin: 0; color: var(--muted); font-size: 13px; }\n .fields { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }\n .field { display: flex; flex-direction: column; gap: 3px; }\n .field.wide { grid-column: 1 / -1; }\n .field label { font-size: 12px; color: var(--muted); }\n .field input, .field select {\n padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px;\n background: var(--bg); color: var(--ink); font-size: 14px; width: 100%;\n }\n .row { display: flex; align-items: center; gap: 8px; margin-top: 2px; }\n button {\n align-self: flex-start; padding: 7px 14px; border: 0; border-radius: 7px;\n background: var(--accent); color: #fff; font-size: 14px; font-weight: 600;\n cursor: pointer;\n }\n .card.action button { background: var(--action); }\n button:disabled { opacity: .55; cursor: default; }\n pre.result {\n margin: 0; padding: 10px 12px; border-radius: 8px; background: var(--code-bg);\n color: var(--code-ink); font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;\n max-height: 340px; overflow: auto; white-space: pre-wrap; word-break: break-word;\n border-left: 3px solid var(--line);\n }\n pre.result.ok { border-left-color: var(--ok); }\n pre.result.err { border-left-color: var(--err); }\n pre.result.running { border-left-color: var(--accent); color: var(--muted); }\n</style>\n</head>\n<body>\n<header>\n <h1>Tesla Superchargers</h1>\n <p>Run a command against the price-history database. Actions are highlighted and ask to confirm.</p>\n</header>\n<main id=\"commands\"></main>\n<script>\n(function () {\n var F = {\n lat: { name: \"lat\", label: \"Latitude\", type: \"text\", placeholder: \"49.3135644\", required: true },\n lon: { name: \"lon\", label: \"Longitude\", type: \"text\", placeholder: \"12.1445587\", required: true },\n radiusKm: { name: \"radiusKm\", label: \"Radius (km)\", type: \"number\", placeholder: \"default\" },\n locale: { name: \"locale\", label: \"Locale\", type: \"text\", placeholder: \"de-DE\" },\n maxFetches: { name: \"maxFetches\", label: \"Max fetches\", type: \"number\", placeholder: \"default\" },\n at: { name: \"at\", label: \"At (local)\", type: \"datetime-local\", wide: true },\n source: { name: \"source\", label: \"Source\", type: \"select\", options: [\"all\", \"charges\", \"chargers\", \"slugs\"] },\n sourceCon: { name: \"source\", label: \"Source\", type: \"select\", options: [\"charges\", \"chargers\", \"slugs\", \"all\"] },\n threshold: { name: \"threshold\", label: \"Threshold\", type: \"number\", placeholder: \"default\" },\n id: { name: \"id\", label: \"Id\", type: \"text\", placeholder: \"reset all if empty\", wide: true }\n };\n\n var COMMANDS = [\n { name: \"query-slugs\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.radiusKm],\n desc: \"Nearest location slugs (tesla_uuid) to a coordinate.\" },\n { name: \"fetch-chargers\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.locale, F.radiusKm, F.maxFetches],\n desc: \"Nearest chargers to a coordinate. May fetch tesla.com on demand \u2014 can be slow.\" },\n { name: \"fetch-prices\", method: \"GET\", kind: \"read\", fields: [F.lat, F.lon, F.at, F.radiusKm],\n desc: \"Supercharger prices valid at a time (default now) for a coordinate.\" },\n { name: \"query-unpriced-charges\", method: \"GET\", kind: \"read\", fields: [],\n desc: \"TeslaMate Supercharger charges with no cost yet.\" },\n { name: \"query-failures\", method: \"GET\", kind: \"read\", fields: [F.source, F.threshold],\n desc: \"Rows with repeated failures at or above the threshold.\" },\n { name: \"query-unmatched-invoices\", method: \"GET\", kind: \"read\", fields: [],\n desc: \"Supercharger charges without a matched invoice.\" },\n { name: \"sync-invoices-dropbox\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Import Tesla charging-history CSV exports from Dropbox.\" },\n { name: \"run-unpriced-charges\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Backfill cost on unpriced charges from stored Supercharger prices.\" },\n { name: \"sync-slugs\", method: \"POST\", kind: \"action\", fields: [],\n desc: \"Snapshot-sync pic_slugs against the live Tesla map feed.\" },\n { name: \"reset-failures\", method: \"POST\", kind: \"action\", fields: [F.sourceCon, F.id],\n desc: \"Clear failure state. Leave id empty to reset ALL rows of the source.\",\n buildBody: function (v) { return v.id ? { source: v.source, id: v.id } : { source: v.source, all: true }; } }\n ];\n\n function el(tag, attrs, text) {\n var e = document.createElement(tag);\n if (attrs) for (var k in attrs) e.setAttribute(k, attrs[k]);\n if (text != null) e.textContent = text;\n return e;\n }\n\n function fieldNode(f) {\n var wrap = el(\"div\", { class: \"field\" + (f.wide ? \" wide\" : \"\") });\n wrap.appendChild(el(\"label\", null, f.label));\n var input;\n if (f.type === \"select\") {\n input = el(\"select\", { name: f.name });\n f.options.forEach(function (o) { input.appendChild(el(\"option\", { value: o }, o)); });\n } else {\n input = el(\"input\", { name: f.name, type: f.type });\n if (f.placeholder) input.setAttribute(\"placeholder\", f.placeholder);\n }\n wrap.appendChild(input);\n return wrap;\n }\n\n function collect(cmd, form) {\n var values = {};\n cmd.fields.forEach(function (f) {\n var input = form.elements[f.name];\n var val = input ? String(input.value).trim() : \"\";\n if (f.type === \"datetime-local\" && val) val = new Date(val).toISOString();\n if (val !== \"\") values[f.name] = val;\n });\n return values;\n }\n\n function show(out, cls, text) {\n out.hidden = false;\n out.className = \"result \" + cls;\n out.textContent = text;\n }\n\n function pretty(text) {\n try { return JSON.stringify(JSON.parse(text), null, 2); } catch (e) { return text; }\n }\n\n function run(cmd, form, out, btn) {\n var values = collect(cmd, form);\n for (var i = 0; i < cmd.fields.length; i++) {\n var f = cmd.fields[i];\n if (f.required && !values[f.name]) { show(out, \"err\", \"Please fill in \" + f.label + \".\"); return; }\n }\n\n var url = \"/\" + cmd.name;\n var opts = { method: cmd.method, headers: {} };\n if (cmd.method === \"GET\") {\n var qs = new URLSearchParams(values).toString();\n if (qs) url += \"?\" + qs;\n } else {\n if (!window.confirm(\"Run \" + cmd.name + \"? This performs a real action.\")) return;\n var body = cmd.buildBody ? cmd.buildBody(values) : values;\n opts.headers[\"content-type\"] = \"application/json\";\n opts.body = JSON.stringify(body);\n }\n\n btn.disabled = true;\n show(out, \"running\", \"Running\u2026\");\n fetch(url, opts).then(function (res) {\n return res.text().then(function (text) {\n if (res.ok) show(out, \"ok\", pretty(text));\n else if (res.status === 401) show(out, \"err\", \"401 Unauthorized \u2014 sign in via the SSO portal (running locally, the command endpoints need the bearer token).\");\n else show(out, \"err\", res.status + \" \u2014 \" + pretty(text));\n });\n }).catch(function (e) {\n show(out, \"err\", \"Request failed: \" + (e && e.message ? e.message : e));\n }).then(function () { btn.disabled = false; });\n }\n\n function card(cmd) {\n var form = el(\"form\", { class: \"card \" + cmd.kind });\n var title = el(\"div\", { class: \"title\" });\n title.appendChild(el(\"span\", { class: \"badge \" + (cmd.method === \"GET\" ? \"get\" : \"post\") }, cmd.method));\n title.appendChild(el(\"h2\", null, cmd.name));\n form.appendChild(title);\n form.appendChild(el(\"p\", { class: \"desc\" }, cmd.desc));\n\n if (cmd.fields.length) {\n var fields = el(\"div\", { class: \"fields\" });\n cmd.fields.forEach(function (f) { fields.appendChild(fieldNode(f)); });\n form.appendChild(fields);\n }\n\n var btn = el(\"button\", { type: \"submit\" }, cmd.kind === \"action\" ? \"Run action\" : \"Run\");\n form.appendChild(btn);\n var out = el(\"pre\", { class: \"result\", hidden: \"hidden\" });\n form.appendChild(out);\n\n form.addEventListener(\"submit\", function (e) { e.preventDefault(); run(cmd, form, out, btn); });\n return form;\n }\n\n var root = document.getElementById(\"commands\");\n COMMANDS.forEach(function (cmd) { root.appendChild(card(cmd)); });\n})();\n</script>\n</body>\n</html>\n";
17
17
  //# sourceMappingURL=ui.d.ts.map
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,q/UAgOnB,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,u/UAgOnB,CAAC"}
package/dist/ui.js CHANGED
@@ -110,21 +110,21 @@ export const UI_HTML = `<!doctype html>
110
110
  };
111
111
 
112
112
  var COMMANDS = [
113
- { name: "find-slugs", method: "GET", kind: "read", fields: [F.lat, F.lon, F.radiusKm],
113
+ { name: "query-slugs", method: "GET", kind: "read", fields: [F.lat, F.lon, F.radiusKm],
114
114
  desc: "Nearest location slugs (tesla_uuid) to a coordinate." },
115
- { name: "find-chargers", method: "GET", kind: "read", fields: [F.lat, F.lon, F.locale, F.radiusKm, F.maxFetches],
115
+ { name: "fetch-chargers", method: "GET", kind: "read", fields: [F.lat, F.lon, F.locale, F.radiusKm, F.maxFetches],
116
116
  desc: "Nearest chargers to a coordinate. May fetch tesla.com on demand — can be slow." },
117
- { name: "find-prices", method: "GET", kind: "read", fields: [F.lat, F.lon, F.at, F.radiusKm],
117
+ { name: "fetch-prices", method: "GET", kind: "read", fields: [F.lat, F.lon, F.at, F.radiusKm],
118
118
  desc: "Supercharger prices valid at a time (default now) for a coordinate." },
119
- { name: "find-unpriced-charges", method: "GET", kind: "read", fields: [],
119
+ { name: "query-unpriced-charges", method: "GET", kind: "read", fields: [],
120
120
  desc: "TeslaMate Supercharger charges with no cost yet." },
121
- { name: "find-failures", method: "GET", kind: "read", fields: [F.source, F.threshold],
121
+ { name: "query-failures", method: "GET", kind: "read", fields: [F.source, F.threshold],
122
122
  desc: "Rows with repeated failures at or above the threshold." },
123
- { name: "find-unmatched-invoices", method: "GET", kind: "read", fields: [],
123
+ { name: "query-unmatched-invoices", method: "GET", kind: "read", fields: [],
124
124
  desc: "Supercharger charges without a matched invoice." },
125
125
  { name: "sync-invoices-dropbox", method: "POST", kind: "action", fields: [],
126
126
  desc: "Import Tesla charging-history CSV exports from Dropbox." },
127
- { name: "process-unpriced-charges", method: "POST", kind: "action", fields: [],
127
+ { name: "run-unpriced-charges", method: "POST", kind: "action", fields: [],
128
128
  desc: "Backfill cost on unpriced charges from stored Supercharger prices." },
129
129
  { name: "sync-slugs", method: "POST", kind: "action", fields: [],
130
130
  desc: "Snapshot-sync pic_slugs against the live Tesla map feed." },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mxpicture/tesla-superchargers-http",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "Http server for interacting with superchargers",
5
5
  "type": "module",
6
6
  "author": "MXPicture",
@@ -32,8 +32,8 @@
32
32
  "access": "public"
33
33
  },
34
34
  "dependencies": {
35
- "@mxpicture/tesla-superchargers-api": "^0.1.26",
36
- "@mxpicture/tesla-superchargers-mate": "^0.1.26"
35
+ "@mxpicture/tesla-superchargers-api": "^0.1.27",
36
+ "@mxpicture/tesla-superchargers-mate": "^0.1.27"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^25.2.3",