@flowselections/google-maps-api-installatie-techniek 1.0.3 → 1.0.5

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.
@@ -4,7 +4,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, Switch, Tabs, TabsContent, TabsList, TabsTrigger, toast, } from "@flowselections/core";
6
6
  import { MapPin, RefreshCw, Trash2, Timer } from "lucide-react";
7
- import { clearMapsCache, getMapsOverview, getMapsStatus, processMapsQueue, purgeExpiredTravelTimes, updateMapsSettings, } from "../lib/maps.functions";
7
+ import { clearMapsCache, getMapsOverview, getMapsStatus, processMapsQueue, purgeExpiredTravelTimes, updateMapsSettings, } from "../lib/maps.functions.js";
8
8
  import { MapsStatusPanel } from "./maps/MapsStatusPanel";
9
9
  import { MapsDiagnosticsPanel } from "./maps/MapsDiagnosticsPanel";
10
10
  function Stat({ label, value }) {
@@ -5,7 +5,7 @@ import { useState } from "react";
5
5
  import { useServerFn } from "@tanstack/react-start";
6
6
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@flowselections/core";
7
7
  import { AlertTriangle, CheckCircle2, ClipboardCopy, Loader2, XCircle, } from "lucide-react";
8
- import { getMapsDiagnostics } from "../../lib/maps.functions";
8
+ import { getMapsDiagnostics } from "../../lib/maps.functions.js";
9
9
  function formatDateTime(value) {
10
10
  const parsed = Date.parse(value);
11
11
  if (Number.isNaN(parsed))
@@ -1,4 +1,4 @@
1
- import type { MapsConnectionStatus } from "../../lib/central-auth.server";
1
+ import type { MapsConnectionStatus } from "../../lib/central-auth.server.js";
2
2
  export declare function MapsStatusPanel({ status, }: {
3
3
  status: MapsConnectionStatus | null;
4
4
  }): import("react").JSX.Element;
@@ -6,7 +6,7 @@ import { useServerFn } from "@tanstack/react-start";
6
6
  import { useQuery } from "@tanstack/react-query";
7
7
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, toast, } from "@flowselections/core";
8
8
  import { AlertTriangle, CheckCircle2, RefreshCw, ShieldCheck, XCircle, } from "lucide-react";
9
- import { getMapsOverview, testMapsConnection } from "../../lib/maps.functions";
9
+ import { getMapsOverview, testMapsConnection } from "../../lib/maps.functions.js";
10
10
  function formatDateTime(value) {
11
11
  if (!value)
12
12
  return "onbekend";
@@ -4,7 +4,7 @@ import { useServerFn } from "@tanstack/react-start";
4
4
  import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@flowselections/core";
5
5
  import { Link } from "@tanstack/react-router";
6
6
  import { MapPin } from "lucide-react";
7
- import { getMapsOverview } from "../../lib/maps.functions";
7
+ import { getMapsOverview } from "../../lib/maps.functions.js";
8
8
  export function MapsSettingsCard() {
9
9
  const fetchOverview = useServerFn(getMapsOverview);
10
10
  const { data } = useQuery({
@@ -19,7 +19,7 @@ function createSupabaseClient() {
19
19
  }
20
20
  let _supabase;
21
21
  // Import the supabase client like this:
22
- // import { supabase } from "../../integrations/supabase/client";
22
+ // import { supabase } from "./client.js";
23
23
  export const supabase = new Proxy({}, {
24
24
  get(_, prop, receiver) {
25
25
  if (!_supabase)
@@ -20,7 +20,7 @@ function createSupabaseAdminClient() {
20
20
  let _supabaseAdmin;
21
21
  // Server-side Supabase client with service role - bypasses RLS
22
22
  // SECURITY: Only use this for trusted server-side operations, never expose to client code
23
- // Import like: import { supabaseAdmin } from "../../integrations/supabase/client.server";
23
+ // Import like: import { supabaseAdmin } from "./client.server.js";
24
24
  export const supabaseAdmin = new Proxy({}, {
25
25
  get(_, prop, receiver) {
26
26
  if (!_supabaseAdmin)
@@ -1,6 +1,12 @@
1
- export declare function brokeredPreviewStorage(): Storage | {
2
- getItem: (key: string) => Promise<string | null>;
3
- setItem: (key: string, value: string) => Promise<void>;
4
- removeItem: (key: string) => Promise<undefined>;
5
- } | undefined;
1
+ /** Storage accepted by Supabase's `auth.storage` option; `localStorage` and the editor broker both satisfy it. */
2
+ export interface PreviewAuthStorage {
3
+ getItem: (key: string) => string | null | Promise<string | null>;
4
+ setItem: (key: string, value: string) => void | Promise<void>;
5
+ removeItem: (key: string) => void | Promise<void>;
6
+ }
7
+ /**
8
+ * On a Lovable preview surface, broker the auth session to the editor over
9
+ * postMessage so the project's preview surfaces share one login; else localStorage.
10
+ */
11
+ export declare function brokeredPreviewStorage(): PreviewAuthStorage | undefined;
6
12
  //# sourceMappingURL=previewAuthStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"previewAuthStorage.d.ts","sourceRoot":"","sources":["../../../src/integrations/supabase/previewAuthStorage.ts"],"names":[],"mappings":"AAIA,wBAAgB,sBAAsB;mBA2Db,MAAM;mBAeZ,MAAM,SAAS,MAAM;sBASlB,MAAM;cAK3B"}
1
+ {"version":3,"file":"previewAuthStorage.d.ts","sourceRoot":"","sources":["../../../src/integrations/supabase/previewAuthStorage.ts"],"names":[],"mappings":"AAEA,kHAAkH;AAClH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AA6BD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,kBAAkB,GAAG,SAAS,CAsGvE"}
@@ -1,6 +1,21 @@
1
1
  // This file is automatically generated. Do not edit it directly.
2
- // On a Lovable preview surface, broker the auth session to the editor over
3
- // postMessage so the project's preview surfaces share one login; else localStorage.
2
+ const RESULT = 'lovable-preview-auth:result';
3
+ function readBrokerReply(data, requestId) {
4
+ if (typeof data !== 'object' || data === null)
5
+ return null;
6
+ if (!('type' in data) || data.type !== RESULT)
7
+ return null;
8
+ if (!('requestId' in data) || data.requestId !== requestId)
9
+ return null;
10
+ return {
11
+ ok: 'ok' in data && Boolean(data.ok),
12
+ value: 'value' in data && typeof data.value === 'string' ? data.value : null,
13
+ };
14
+ }
15
+ /**
16
+ * On a Lovable preview surface, broker the auth session to the editor over
17
+ * postMessage so the project's preview surfaces share one login; else localStorage.
18
+ */
4
19
  export function brokeredPreviewStorage() {
5
20
  if (typeof window === 'undefined')
6
21
  return undefined;
@@ -11,10 +26,13 @@ export function brokeredPreviewStorage() {
11
26
  // preview--<name> host can't smuggle another project's id.
12
27
  const UUID = '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
13
28
  const projectId = onPreviewZone
14
- ? (host.match(new RegExp('^(?:id-preview(?:-[a-z0-9]+)?|project)--(' + UUID + ')(?:-dev)?(?=\\.|$)', 'i'))?.[1]
15
- ?? host.match(new RegExp('^(' + UUID + ')(?=[.-])', 'i'))?.[1])
29
+ ? (new RegExp('^(?:id-preview(?:-[a-z0-9]+)?|project)--(' + UUID + ')(?:-dev)?(?=\\.|$)', 'i').exec(host)?.[1]
30
+ ?? new RegExp('^(' + UUID + ')(?=[.-])', 'i').exec(host)?.[1])
16
31
  : undefined;
17
- const framed = window.parent && window.parent !== window;
32
+ // lib.dom types window.parent and location.ancestorOrigins as always set, but a
33
+ // detached frame has no parent and not every browser implements ancestorOrigins.
34
+ const parentWindow = window.parent;
35
+ const framed = parentWindow !== null && parentWindow !== window;
18
36
  if (!projectId || !framed)
19
37
  return localStorage;
20
38
  // Post only to the real editor ancestor, validated as a Lovable origin, so the
@@ -23,59 +41,75 @@ export function brokeredPreviewStorage() {
23
41
  const EDITOR = dev
24
42
  ? /^https:\/\/([a-z0-9-]+\.)*(lovable\.dev|gptengineer\.app)$|^http:\/\/localhost:3000$/
25
43
  : /^https:\/\/([a-z0-9-]+\.)*(lovable\.dev|gptengineer\.app)$/;
26
- const ancestor = (location.ancestorOrigins && location.ancestorOrigins[0]) || (document.referrer ? new URL(document.referrer).origin : '');
44
+ const ancestorOrigins = location.ancestorOrigins;
45
+ const ancestor = ancestorOrigins?.[0] ?? (document.referrer ? new URL(document.referrer).origin : '');
27
46
  const editorOrigins = ancestor && EDITOR.test(ancestor)
28
47
  ? [ancestor]
29
48
  : (dev ? ['https://lovable.dev', 'http://localhost:3000'] : ['https://lovable.dev']);
30
- const RESULT = 'lovable-preview-auth:result';
31
49
  const TIMEOUT = 2000;
32
50
  const newId = () => Math.random().toString(36).slice(2) + Date.now().toString(36);
33
51
  const request = (type, key, value) => new Promise((resolve) => {
34
52
  const requestId = newId();
35
53
  let done = false;
36
- let timer;
37
- const finish = (r) => {
54
+ const finish = (reply) => {
38
55
  if (done)
39
56
  return;
40
57
  done = true;
41
58
  clearTimeout(timer);
42
59
  window.removeEventListener('message', onMessage);
43
- resolve(r);
60
+ resolve(reply);
44
61
  };
45
62
  const onMessage = (e) => {
46
- if (editorOrigins.indexOf(e.origin) < 0)
63
+ if (!editorOrigins.includes(e.origin))
47
64
  return;
48
- const d = e.data;
49
- if (d && d.type === RESULT && d.requestId === requestId)
50
- finish(d);
65
+ const reply = readBrokerReply(e.data, requestId);
66
+ if (reply)
67
+ finish(reply);
51
68
  };
52
69
  window.addEventListener('message', onMessage);
70
+ const timer = setTimeout(() => { finish(null); }, TIMEOUT);
53
71
  const msg = { type, requestId, projectId, key };
54
72
  if (value !== undefined)
55
- msg['value'] = value;
73
+ msg.value = value;
56
74
  // targetOrigin per trusted editor origin, so a session token never reaches an arbitrary embedder.
57
75
  for (const origin of editorOrigins)
58
76
  window.parent.postMessage(msg, origin);
59
- timer = setTimeout(() => finish(null), TIMEOUT);
60
77
  });
61
78
  // The editor may not be listening yet at the first getItem, so retry once.
62
79
  let firstGet = true;
63
80
  const RETRY_DELAY = 250;
81
+ // Blocked third-party storage throws here; seeding must not break broker reads.
82
+ const readLocal = (key) => { try {
83
+ return localStorage.getItem(key);
84
+ }
85
+ catch {
86
+ return undefined;
87
+ } };
64
88
  return {
65
89
  getItem: async (key) => {
66
- let res = await request('lovable-preview-auth:get', key);
90
+ // Sent with GET and REMOVE so an editor that never cached this session can check or revoke it.
91
+ const local = readLocal(key);
92
+ let res = await request('lovable-preview-auth:get', key, local ?? undefined);
67
93
  if (!res && firstGet) {
68
- await new Promise((r) => setTimeout(r, RETRY_DELAY));
69
- res = await request('lovable-preview-auth:get', key);
94
+ await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
95
+ res = await request('lovable-preview-auth:get', key, local ?? undefined);
70
96
  }
71
97
  firstGet = false;
72
98
  // '' is the logout tombstone: clear the local copy too so it can't resurrect if
73
- // the broker later goes silent. A null reply means never-synced -> keep local.
74
- if (res && res.ok && typeof res.value === 'string') {
99
+ // the broker later goes silent. A null value means never-synced -> keep local.
100
+ if (res?.ok && res.value !== null) {
75
101
  if (res.value === '') {
76
- localStorage.removeItem(key);
102
+ if (local !== undefined && readLocal(key) === local)
103
+ localStorage.removeItem(key);
77
104
  return null;
78
105
  }
106
+ // Seed this origin so a new tab, whose editor holds no session, stays signed in.
107
+ if (local === null && readLocal(key) === null) {
108
+ try {
109
+ localStorage.setItem(key, res.value);
110
+ }
111
+ catch { /* storage full: still return the editor's session */ }
112
+ }
79
113
  return res.value;
80
114
  }
81
115
  return localStorage.getItem(key);
@@ -83,7 +117,7 @@ export function brokeredPreviewStorage() {
83
117
  setItem: (key, value) => {
84
118
  localStorage.setItem(key, value);
85
119
  return request('lovable-preview-auth:set', key, value).then((res) => {
86
- if (res && res.ok && typeof res.value === 'string' && localStorage.getItem(key) === value) {
120
+ if (res?.ok && res.value !== null && localStorage.getItem(key) === value) {
87
121
  if (res.value === '')
88
122
  localStorage.removeItem(key);
89
123
  else
@@ -92,8 +126,9 @@ export function brokeredPreviewStorage() {
92
126
  });
93
127
  },
94
128
  removeItem: (key) => {
129
+ const local = readLocal(key);
95
130
  localStorage.removeItem(key);
96
- return request('lovable-preview-auth:remove', key).then(() => undefined);
131
+ return request('lovable-preview-auth:remove', key, local ?? undefined).then(() => { });
97
132
  },
98
133
  };
99
134
  }