@inkindcards/semantic-layer 2.1.0 → 2.2.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.
@@ -31,7 +31,7 @@ var SemanticLayerClient = class {
31
31
  this.gatewayUrl = config.gatewayUrl;
32
32
  if (typeof window !== "undefined") {
33
33
  try {
34
- const stored = sessionStorage.getItem(TOKEN_STORAGE_KEY);
34
+ const stored = localStorage.getItem(TOKEN_STORAGE_KEY);
35
35
  if (stored) {
36
36
  const parsed = JSON.parse(stored);
37
37
  if (parsed.expiresAt > Date.now()) {
@@ -39,7 +39,7 @@ var SemanticLayerClient = class {
39
39
  this.tokenExpiry = parsed.expiresAt;
40
40
  this.userEmail = parsed.email || null;
41
41
  } else {
42
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
42
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
43
43
  }
44
44
  }
45
45
  } catch {
@@ -56,6 +56,65 @@ var SemanticLayerClient = class {
56
56
  const target = returnUrl || (typeof window !== "undefined" ? window.location.href.split("#")[0] : "");
57
57
  return `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(target)}`;
58
58
  }
59
+ /**
60
+ * Returns true if the current page is running inside an iframe.
61
+ */
62
+ isInIframe() {
63
+ if (typeof window === "undefined") return false;
64
+ try {
65
+ return window.self !== window.top;
66
+ } catch {
67
+ return true;
68
+ }
69
+ }
70
+ /**
71
+ * Opens a popup window for Google sign-in. Used when the app is in an iframe
72
+ * (e.g., Lovable preview) where redirects to Google are blocked.
73
+ * Returns a promise that resolves when auth completes.
74
+ */
75
+ signInWithPopup(returnUrl) {
76
+ return new Promise((resolve, reject) => {
77
+ const callbackUrl = `${this.gatewayUrl}/auth/popup-callback`;
78
+ const signInUrl = `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(callbackUrl)}`;
79
+ const width = 500;
80
+ const height = 600;
81
+ const left = window.screenX + (window.outerWidth - width) / 2;
82
+ const top = window.screenY + (window.outerHeight - height) / 2;
83
+ const popup = window.open(
84
+ signInUrl,
85
+ "semantic-layer-signin",
86
+ `width=${width},height=${height},left=${left},top=${top},popup=true`
87
+ );
88
+ if (!popup) {
89
+ reject(new SemanticLayerError("Popup blocked by browser", "AUTH_ERROR"));
90
+ return;
91
+ }
92
+ const handleMessage = (event) => {
93
+ if (event.origin !== this.gatewayUrl) return;
94
+ const { access_token, email, expires_in, auth_error } = event.data || {};
95
+ window.removeEventListener("message", handleMessage);
96
+ clearInterval(pollTimer);
97
+ if (auth_error) {
98
+ reject(new SemanticLayerError(auth_error, "AUTH_ERROR"));
99
+ return;
100
+ }
101
+ if (access_token && email) {
102
+ this.setAccessToken(access_token, email, parseInt(expires_in || "3600", 10));
103
+ resolve(true);
104
+ } else {
105
+ resolve(false);
106
+ }
107
+ };
108
+ window.addEventListener("message", handleMessage);
109
+ const pollTimer = setInterval(() => {
110
+ if (popup.closed) {
111
+ clearInterval(pollTimer);
112
+ window.removeEventListener("message", handleMessage);
113
+ resolve(false);
114
+ }
115
+ }, 500);
116
+ });
117
+ }
59
118
  /**
60
119
  * Check the current URL hash for auth tokens (set by the gateway callback redirect).
61
120
  * If found, extracts them, stores the session, clears the hash, and returns true.
@@ -87,7 +146,7 @@ var SemanticLayerClient = class {
87
146
  this.tokenExpiry = Date.now() + expiresIn * 1e3;
88
147
  if (typeof window !== "undefined") {
89
148
  try {
90
- sessionStorage.setItem(
149
+ localStorage.setItem(
91
150
  TOKEN_STORAGE_KEY,
92
151
  JSON.stringify({ token, email, expiresAt: this.tokenExpiry })
93
152
  );
@@ -112,7 +171,7 @@ var SemanticLayerClient = class {
112
171
  this.metadataCache = null;
113
172
  if (typeof window !== "undefined") {
114
173
  try {
115
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
174
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
116
175
  } catch {
117
176
  }
118
177
  }
@@ -221,5 +280,5 @@ var SemanticLayerError = class extends Error {
221
280
 
222
281
  exports.SemanticLayerClient = SemanticLayerClient;
223
282
  exports.SemanticLayerError = SemanticLayerError;
224
- //# sourceMappingURL=chunk-W64RGDXH.cjs.map
225
- //# sourceMappingURL=chunk-W64RGDXH.cjs.map
283
+ //# sourceMappingURL=chunk-JLZMOWJ2.cjs.map
284
+ //# sourceMappingURL=chunk-JLZMOWJ2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"chunk-JLZMOWJ2.cjs","sourcesContent":["import type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n CuratedField,\n AccessRole,\n UserRoleAssignment,\n UserFieldOverride,\n} from \"./types\";\n\nconst TOKEN_STORAGE_KEY = \"semantic-layer-token\";\n\nexport class SemanticLayerClient {\n readonly gatewayUrl: string;\n private accessToken: string | null = null;\n private tokenExpiry = 0;\n private userEmail: string | null = null;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000;\n private authListeners = new Set<(event: string, session: SessionLike | null) => void>();\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n\n if (typeof window !== \"undefined\") {\n try {\n const stored = localStorage.getItem(TOKEN_STORAGE_KEY);\n if (stored) {\n const parsed = JSON.parse(stored);\n if (parsed.expiresAt > Date.now()) {\n this.accessToken = parsed.token;\n this.tokenExpiry = parsed.expiresAt;\n this.userEmail = parsed.email || null;\n } else {\n localStorage.removeItem(TOKEN_STORAGE_KEY);\n }\n }\n } catch {\n // Ignore storage errors\n }\n }\n }\n\n // -- Auth ------------------------------------------------------------------\n\n /**\n * Returns the URL to redirect the browser to for Google sign-in.\n * After the user authenticates, the gateway redirects back to returnUrl\n * with the access token in the URL hash fragment.\n */\n getSignInUrl(returnUrl?: string): string {\n const target = returnUrl || (typeof window !== \"undefined\" ? window.location.href.split(\"#\")[0] : \"\");\n return `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(target)}`;\n }\n\n /**\n * Returns true if the current page is running inside an iframe.\n */\n isInIframe(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return window.self !== window.top;\n } catch {\n return true;\n }\n }\n\n /**\n * Opens a popup window for Google sign-in. Used when the app is in an iframe\n * (e.g., Lovable preview) where redirects to Google are blocked.\n * Returns a promise that resolves when auth completes.\n */\n signInWithPopup(returnUrl?: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n const callbackUrl = `${this.gatewayUrl}/auth/popup-callback`;\n const signInUrl = `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(callbackUrl)}`;\n\n const width = 500;\n const height = 600;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n const popup = window.open(\n signInUrl,\n \"semantic-layer-signin\",\n `width=${width},height=${height},left=${left},top=${top},popup=true`,\n );\n\n if (!popup) {\n reject(new SemanticLayerError(\"Popup blocked by browser\", \"AUTH_ERROR\"));\n return;\n }\n\n const handleMessage = (event: MessageEvent) => {\n if (event.origin !== this.gatewayUrl) return;\n const { access_token, email, expires_in, auth_error } = event.data || {};\n\n window.removeEventListener(\"message\", handleMessage);\n clearInterval(pollTimer);\n\n if (auth_error) {\n reject(new SemanticLayerError(auth_error, \"AUTH_ERROR\"));\n return;\n }\n\n if (access_token && email) {\n this.setAccessToken(access_token, email, parseInt(expires_in || \"3600\", 10));\n resolve(true);\n } else {\n resolve(false);\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n\n const pollTimer = setInterval(() => {\n if (popup.closed) {\n clearInterval(pollTimer);\n window.removeEventListener(\"message\", handleMessage);\n resolve(false);\n }\n }, 500);\n });\n }\n\n /**\n * Check the current URL hash for auth tokens (set by the gateway callback redirect).\n * If found, extracts them, stores the session, clears the hash, and returns true.\n */\n handleAuthCallback(): boolean {\n if (typeof window === \"undefined\") return false;\n\n const hash = window.location.hash.slice(1);\n if (!hash) return false;\n\n const params = new URLSearchParams(hash);\n\n const authError = params.get(\"auth_error\");\n if (authError) {\n window.history.replaceState(null, \"\", window.location.pathname + window.location.search);\n throw new SemanticLayerError(authError, \"AUTH_ERROR\");\n }\n\n const accessToken = params.get(\"access_token\");\n const email = params.get(\"email\");\n const expiresIn = parseInt(params.get(\"expires_in\") || \"0\", 10);\n\n if (!accessToken || !email) return false;\n\n window.history.replaceState(null, \"\", window.location.pathname + window.location.search);\n this.setAccessToken(accessToken, email, expiresIn);\n return true;\n }\n\n /**\n * Set the Google access token (called after OAuth redirect callback).\n */\n setAccessToken(token: string, email: string, expiresIn: number) {\n this.accessToken = token;\n this.userEmail = email;\n this.tokenExpiry = Date.now() + expiresIn * 1000;\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(\n TOKEN_STORAGE_KEY,\n JSON.stringify({ token, email, expiresAt: this.tokenExpiry }),\n );\n } catch {\n // Ignore storage errors\n }\n }\n\n const session: SessionLike = { user: { id: email, email } };\n for (const listener of this.authListeners) {\n listener(\"SIGNED_IN\", session);\n }\n }\n\n async getSession(): Promise<SessionLike | null> {\n if (this.accessToken && Date.now() < this.tokenExpiry) {\n return { user: { id: this.userEmail || \"\", email: this.userEmail || \"\" } };\n }\n return null;\n }\n\n async signOut() {\n this.accessToken = null;\n this.tokenExpiry = 0;\n this.userEmail = null;\n this.metadataCache = null;\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(TOKEN_STORAGE_KEY);\n } catch {\n // Ignore storage errors\n }\n }\n\n for (const listener of this.authListeners) {\n listener(\"SIGNED_OUT\", null);\n }\n\n return { error: null };\n }\n\n onAuthStateChange(callback: (event: string, session: SessionLike | null) => void) {\n this.authListeners.add(callback);\n return {\n data: {\n subscription: {\n unsubscribe: () => {\n this.authListeners.delete(callback);\n },\n },\n },\n };\n }\n\n // -- API calls -------------------------------------------------------------\n\n private async apiCall<T>(path: string, body?: unknown): Promise<T> {\n if (!this.accessToken) {\n throw new SemanticLayerError(\"Not authenticated\", \"AUTH_ERROR\");\n }\n\n const resp = await fetch(`${this.gatewayUrl}${path}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const data = await resp.json();\n\n if (!resp.ok || data?.error) {\n throw new SemanticLayerError(\n data?.error || `Request failed: ${resp.status}`,\n resp.status === 401 ? \"AUTH_ERROR\" : \"API_ERROR\",\n );\n }\n\n return data as T;\n }\n\n // -- Metadata --------------------------------------------------------------\n\n async getMetadata(forceRefresh = false): Promise<MetadataResponse> {\n const now = Date.now();\n if (!forceRefresh && this.metadataCache && now - this.metadataCacheTime < this.CACHE_TTL_MS) {\n return this.metadataCache;\n }\n\n const data = await this.apiCall<MetadataResponse>(\"/v1/metadata\");\n this.metadataCache = data;\n this.metadataCacheTime = now;\n return data;\n }\n\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n async getDimensions(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\");\n }\n\n async getField(nameOrId: string): Promise<SemanticField | undefined> {\n const { fields } = await this.getMetadata();\n return fields.find((f) => f.name === nameOrId || f.id === nameOrId);\n }\n\n // -- Query -----------------------------------------------------------------\n\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n return this.apiCall<QueryResult>(\"/v1/query\", { config });\n }\n\n async simpleQuery(input: SimpleQueryInput): Promise<QueryResult> {\n const { fields } = await this.getMetadata();\n const fieldMap = new Map(fields.map((f) => [f.name, f]));\n\n const values = input.metrics.map((name) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown metric: \"${name}\"`, \"UNKNOWN_FIELD\");\n return { fieldId: field.id, field };\n });\n\n const rows = (input.groupBy || []).map((name) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown dimension: \"${name}\"`, \"UNKNOWN_FIELD\");\n const grain = field.type === \"time_dimension\" ? input.grain : undefined;\n return { fieldId: field.id, field, grain };\n });\n\n const filters = Object.entries(input.filters || {}).map(([name, filterValues]) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown filter field: \"${name}\"`, \"UNKNOWN_FIELD\");\n return { fieldId: field.id, field, filterValues };\n });\n\n return this.query({ values, rows, columns: [], filters });\n }\n\n // -- Admin -----------------------------------------------------------------\n\n private async adminCall<T>(action: string, body: Record<string, unknown> = {}): Promise<T> {\n return this.apiCall<T>(\"/v1/admin\", { action, ...body });\n }\n\n readonly admin = {\n listFields: () => this.adminCall<{ fields: CuratedField[] }>(\"fields.list\"),\n createField: (input: { field_name: string; field_type: string; display_name?: string; description?: string }) =>\n this.adminCall<{ field: CuratedField }>(\"fields.create\", input),\n updateField: (input: { id: number; field_name?: string; display_name?: string; description?: string; is_active?: boolean }) =>\n this.adminCall<{ field: CuratedField }>(\"fields.update\", input),\n deleteField: (id: number) =>\n this.adminCall<{ deleted: boolean }>(\"fields.delete\", { id }),\n\n listRoles: () => this.adminCall<{ roles: AccessRole[] }>(\"roles.list\"),\n createRole: (input: { name: string; description?: string; is_default?: boolean }) =>\n this.adminCall<{ role: AccessRole }>(\"roles.create\", input),\n updateRole: (input: { id: number; name?: string; description?: string; is_default?: boolean }) =>\n this.adminCall<{ role: AccessRole }>(\"roles.update\", input),\n deleteRole: (id: number) =>\n this.adminCall<{ deleted: boolean }>(\"roles.delete\", { id }),\n setRoleFields: (role_id: number, curated_field_ids: number[]) =>\n this.adminCall<{ role_id: number; field_count: number }>(\"roles.setFields\", { role_id, curated_field_ids }),\n\n listUsers: () => this.adminCall<{ users: UserRoleAssignment[] }>(\"users.list\"),\n assignUserRole: (input: { email: string; role_id: number; is_admin?: boolean }) =>\n this.adminCall<{ assignment: UserRoleAssignment }>(\"users.assignRole\", input),\n removeUserRole: (input: { email: string; role_id: number }) =>\n this.adminCall<{ deleted: boolean }>(\"users.removeRole\", input),\n\n listUserOverrides: (user_id: string) =>\n this.adminCall<{ overrides: UserFieldOverride[] }>(\"users.listOverrides\", { user_id }),\n setUserOverride: (input: { user_id: string; curated_field_id: number; access: \"grant\" | \"deny\" }) =>\n this.adminCall<{ override: UserFieldOverride }>(\"users.setOverride\", input),\n removeUserOverride: (input: { user_id: string; curated_field_id: number }) =>\n this.adminCall<{ deleted: boolean }>(\"users.removeOverride\", input),\n };\n}\n\nexport interface SessionLike {\n user: { id: string; email: string };\n}\n\nexport class SemanticLayerError extends Error {\n code: string;\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SemanticLayerError\";\n this.code = code;\n }\n}\n"]}
@@ -29,7 +29,7 @@ var SemanticLayerClient = class {
29
29
  this.gatewayUrl = config.gatewayUrl;
30
30
  if (typeof window !== "undefined") {
31
31
  try {
32
- const stored = sessionStorage.getItem(TOKEN_STORAGE_KEY);
32
+ const stored = localStorage.getItem(TOKEN_STORAGE_KEY);
33
33
  if (stored) {
34
34
  const parsed = JSON.parse(stored);
35
35
  if (parsed.expiresAt > Date.now()) {
@@ -37,7 +37,7 @@ var SemanticLayerClient = class {
37
37
  this.tokenExpiry = parsed.expiresAt;
38
38
  this.userEmail = parsed.email || null;
39
39
  } else {
40
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
40
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
41
41
  }
42
42
  }
43
43
  } catch {
@@ -54,6 +54,65 @@ var SemanticLayerClient = class {
54
54
  const target = returnUrl || (typeof window !== "undefined" ? window.location.href.split("#")[0] : "");
55
55
  return `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(target)}`;
56
56
  }
57
+ /**
58
+ * Returns true if the current page is running inside an iframe.
59
+ */
60
+ isInIframe() {
61
+ if (typeof window === "undefined") return false;
62
+ try {
63
+ return window.self !== window.top;
64
+ } catch {
65
+ return true;
66
+ }
67
+ }
68
+ /**
69
+ * Opens a popup window for Google sign-in. Used when the app is in an iframe
70
+ * (e.g., Lovable preview) where redirects to Google are blocked.
71
+ * Returns a promise that resolves when auth completes.
72
+ */
73
+ signInWithPopup(returnUrl) {
74
+ return new Promise((resolve, reject) => {
75
+ const callbackUrl = `${this.gatewayUrl}/auth/popup-callback`;
76
+ const signInUrl = `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(callbackUrl)}`;
77
+ const width = 500;
78
+ const height = 600;
79
+ const left = window.screenX + (window.outerWidth - width) / 2;
80
+ const top = window.screenY + (window.outerHeight - height) / 2;
81
+ const popup = window.open(
82
+ signInUrl,
83
+ "semantic-layer-signin",
84
+ `width=${width},height=${height},left=${left},top=${top},popup=true`
85
+ );
86
+ if (!popup) {
87
+ reject(new SemanticLayerError("Popup blocked by browser", "AUTH_ERROR"));
88
+ return;
89
+ }
90
+ const handleMessage = (event) => {
91
+ if (event.origin !== this.gatewayUrl) return;
92
+ const { access_token, email, expires_in, auth_error } = event.data || {};
93
+ window.removeEventListener("message", handleMessage);
94
+ clearInterval(pollTimer);
95
+ if (auth_error) {
96
+ reject(new SemanticLayerError(auth_error, "AUTH_ERROR"));
97
+ return;
98
+ }
99
+ if (access_token && email) {
100
+ this.setAccessToken(access_token, email, parseInt(expires_in || "3600", 10));
101
+ resolve(true);
102
+ } else {
103
+ resolve(false);
104
+ }
105
+ };
106
+ window.addEventListener("message", handleMessage);
107
+ const pollTimer = setInterval(() => {
108
+ if (popup.closed) {
109
+ clearInterval(pollTimer);
110
+ window.removeEventListener("message", handleMessage);
111
+ resolve(false);
112
+ }
113
+ }, 500);
114
+ });
115
+ }
57
116
  /**
58
117
  * Check the current URL hash for auth tokens (set by the gateway callback redirect).
59
118
  * If found, extracts them, stores the session, clears the hash, and returns true.
@@ -85,7 +144,7 @@ var SemanticLayerClient = class {
85
144
  this.tokenExpiry = Date.now() + expiresIn * 1e3;
86
145
  if (typeof window !== "undefined") {
87
146
  try {
88
- sessionStorage.setItem(
147
+ localStorage.setItem(
89
148
  TOKEN_STORAGE_KEY,
90
149
  JSON.stringify({ token, email, expiresAt: this.tokenExpiry })
91
150
  );
@@ -110,7 +169,7 @@ var SemanticLayerClient = class {
110
169
  this.metadataCache = null;
111
170
  if (typeof window !== "undefined") {
112
171
  try {
113
- sessionStorage.removeItem(TOKEN_STORAGE_KEY);
172
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
114
173
  } catch {
115
174
  }
116
175
  }
@@ -218,5 +277,5 @@ var SemanticLayerError = class extends Error {
218
277
  };
219
278
 
220
279
  export { SemanticLayerClient, SemanticLayerError };
221
- //# sourceMappingURL=chunk-WR4D3UI6.js.map
222
- //# sourceMappingURL=chunk-WR4D3UI6.js.map
280
+ //# sourceMappingURL=chunk-ZYY77QMO.js.map
281
+ //# sourceMappingURL=chunk-ZYY77QMO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"chunk-ZYY77QMO.js","sourcesContent":["import type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n CuratedField,\n AccessRole,\n UserRoleAssignment,\n UserFieldOverride,\n} from \"./types\";\n\nconst TOKEN_STORAGE_KEY = \"semantic-layer-token\";\n\nexport class SemanticLayerClient {\n readonly gatewayUrl: string;\n private accessToken: string | null = null;\n private tokenExpiry = 0;\n private userEmail: string | null = null;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000;\n private authListeners = new Set<(event: string, session: SessionLike | null) => void>();\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n\n if (typeof window !== \"undefined\") {\n try {\n const stored = localStorage.getItem(TOKEN_STORAGE_KEY);\n if (stored) {\n const parsed = JSON.parse(stored);\n if (parsed.expiresAt > Date.now()) {\n this.accessToken = parsed.token;\n this.tokenExpiry = parsed.expiresAt;\n this.userEmail = parsed.email || null;\n } else {\n localStorage.removeItem(TOKEN_STORAGE_KEY);\n }\n }\n } catch {\n // Ignore storage errors\n }\n }\n }\n\n // -- Auth ------------------------------------------------------------------\n\n /**\n * Returns the URL to redirect the browser to for Google sign-in.\n * After the user authenticates, the gateway redirects back to returnUrl\n * with the access token in the URL hash fragment.\n */\n getSignInUrl(returnUrl?: string): string {\n const target = returnUrl || (typeof window !== \"undefined\" ? window.location.href.split(\"#\")[0] : \"\");\n return `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(target)}`;\n }\n\n /**\n * Returns true if the current page is running inside an iframe.\n */\n isInIframe(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return window.self !== window.top;\n } catch {\n return true;\n }\n }\n\n /**\n * Opens a popup window for Google sign-in. Used when the app is in an iframe\n * (e.g., Lovable preview) where redirects to Google are blocked.\n * Returns a promise that resolves when auth completes.\n */\n signInWithPopup(returnUrl?: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n const callbackUrl = `${this.gatewayUrl}/auth/popup-callback`;\n const signInUrl = `${this.gatewayUrl}/auth/google?returnUrl=${encodeURIComponent(callbackUrl)}`;\n\n const width = 500;\n const height = 600;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n const popup = window.open(\n signInUrl,\n \"semantic-layer-signin\",\n `width=${width},height=${height},left=${left},top=${top},popup=true`,\n );\n\n if (!popup) {\n reject(new SemanticLayerError(\"Popup blocked by browser\", \"AUTH_ERROR\"));\n return;\n }\n\n const handleMessage = (event: MessageEvent) => {\n if (event.origin !== this.gatewayUrl) return;\n const { access_token, email, expires_in, auth_error } = event.data || {};\n\n window.removeEventListener(\"message\", handleMessage);\n clearInterval(pollTimer);\n\n if (auth_error) {\n reject(new SemanticLayerError(auth_error, \"AUTH_ERROR\"));\n return;\n }\n\n if (access_token && email) {\n this.setAccessToken(access_token, email, parseInt(expires_in || \"3600\", 10));\n resolve(true);\n } else {\n resolve(false);\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n\n const pollTimer = setInterval(() => {\n if (popup.closed) {\n clearInterval(pollTimer);\n window.removeEventListener(\"message\", handleMessage);\n resolve(false);\n }\n }, 500);\n });\n }\n\n /**\n * Check the current URL hash for auth tokens (set by the gateway callback redirect).\n * If found, extracts them, stores the session, clears the hash, and returns true.\n */\n handleAuthCallback(): boolean {\n if (typeof window === \"undefined\") return false;\n\n const hash = window.location.hash.slice(1);\n if (!hash) return false;\n\n const params = new URLSearchParams(hash);\n\n const authError = params.get(\"auth_error\");\n if (authError) {\n window.history.replaceState(null, \"\", window.location.pathname + window.location.search);\n throw new SemanticLayerError(authError, \"AUTH_ERROR\");\n }\n\n const accessToken = params.get(\"access_token\");\n const email = params.get(\"email\");\n const expiresIn = parseInt(params.get(\"expires_in\") || \"0\", 10);\n\n if (!accessToken || !email) return false;\n\n window.history.replaceState(null, \"\", window.location.pathname + window.location.search);\n this.setAccessToken(accessToken, email, expiresIn);\n return true;\n }\n\n /**\n * Set the Google access token (called after OAuth redirect callback).\n */\n setAccessToken(token: string, email: string, expiresIn: number) {\n this.accessToken = token;\n this.userEmail = email;\n this.tokenExpiry = Date.now() + expiresIn * 1000;\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(\n TOKEN_STORAGE_KEY,\n JSON.stringify({ token, email, expiresAt: this.tokenExpiry }),\n );\n } catch {\n // Ignore storage errors\n }\n }\n\n const session: SessionLike = { user: { id: email, email } };\n for (const listener of this.authListeners) {\n listener(\"SIGNED_IN\", session);\n }\n }\n\n async getSession(): Promise<SessionLike | null> {\n if (this.accessToken && Date.now() < this.tokenExpiry) {\n return { user: { id: this.userEmail || \"\", email: this.userEmail || \"\" } };\n }\n return null;\n }\n\n async signOut() {\n this.accessToken = null;\n this.tokenExpiry = 0;\n this.userEmail = null;\n this.metadataCache = null;\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(TOKEN_STORAGE_KEY);\n } catch {\n // Ignore storage errors\n }\n }\n\n for (const listener of this.authListeners) {\n listener(\"SIGNED_OUT\", null);\n }\n\n return { error: null };\n }\n\n onAuthStateChange(callback: (event: string, session: SessionLike | null) => void) {\n this.authListeners.add(callback);\n return {\n data: {\n subscription: {\n unsubscribe: () => {\n this.authListeners.delete(callback);\n },\n },\n },\n };\n }\n\n // -- API calls -------------------------------------------------------------\n\n private async apiCall<T>(path: string, body?: unknown): Promise<T> {\n if (!this.accessToken) {\n throw new SemanticLayerError(\"Not authenticated\", \"AUTH_ERROR\");\n }\n\n const resp = await fetch(`${this.gatewayUrl}${path}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const data = await resp.json();\n\n if (!resp.ok || data?.error) {\n throw new SemanticLayerError(\n data?.error || `Request failed: ${resp.status}`,\n resp.status === 401 ? \"AUTH_ERROR\" : \"API_ERROR\",\n );\n }\n\n return data as T;\n }\n\n // -- Metadata --------------------------------------------------------------\n\n async getMetadata(forceRefresh = false): Promise<MetadataResponse> {\n const now = Date.now();\n if (!forceRefresh && this.metadataCache && now - this.metadataCacheTime < this.CACHE_TTL_MS) {\n return this.metadataCache;\n }\n\n const data = await this.apiCall<MetadataResponse>(\"/v1/metadata\");\n this.metadataCache = data;\n this.metadataCacheTime = now;\n return data;\n }\n\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n async getDimensions(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\");\n }\n\n async getField(nameOrId: string): Promise<SemanticField | undefined> {\n const { fields } = await this.getMetadata();\n return fields.find((f) => f.name === nameOrId || f.id === nameOrId);\n }\n\n // -- Query -----------------------------------------------------------------\n\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n return this.apiCall<QueryResult>(\"/v1/query\", { config });\n }\n\n async simpleQuery(input: SimpleQueryInput): Promise<QueryResult> {\n const { fields } = await this.getMetadata();\n const fieldMap = new Map(fields.map((f) => [f.name, f]));\n\n const values = input.metrics.map((name) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown metric: \"${name}\"`, \"UNKNOWN_FIELD\");\n return { fieldId: field.id, field };\n });\n\n const rows = (input.groupBy || []).map((name) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown dimension: \"${name}\"`, \"UNKNOWN_FIELD\");\n const grain = field.type === \"time_dimension\" ? input.grain : undefined;\n return { fieldId: field.id, field, grain };\n });\n\n const filters = Object.entries(input.filters || {}).map(([name, filterValues]) => {\n const field = fieldMap.get(name);\n if (!field) throw new SemanticLayerError(`Unknown filter field: \"${name}\"`, \"UNKNOWN_FIELD\");\n return { fieldId: field.id, field, filterValues };\n });\n\n return this.query({ values, rows, columns: [], filters });\n }\n\n // -- Admin -----------------------------------------------------------------\n\n private async adminCall<T>(action: string, body: Record<string, unknown> = {}): Promise<T> {\n return this.apiCall<T>(\"/v1/admin\", { action, ...body });\n }\n\n readonly admin = {\n listFields: () => this.adminCall<{ fields: CuratedField[] }>(\"fields.list\"),\n createField: (input: { field_name: string; field_type: string; display_name?: string; description?: string }) =>\n this.adminCall<{ field: CuratedField }>(\"fields.create\", input),\n updateField: (input: { id: number; field_name?: string; display_name?: string; description?: string; is_active?: boolean }) =>\n this.adminCall<{ field: CuratedField }>(\"fields.update\", input),\n deleteField: (id: number) =>\n this.adminCall<{ deleted: boolean }>(\"fields.delete\", { id }),\n\n listRoles: () => this.adminCall<{ roles: AccessRole[] }>(\"roles.list\"),\n createRole: (input: { name: string; description?: string; is_default?: boolean }) =>\n this.adminCall<{ role: AccessRole }>(\"roles.create\", input),\n updateRole: (input: { id: number; name?: string; description?: string; is_default?: boolean }) =>\n this.adminCall<{ role: AccessRole }>(\"roles.update\", input),\n deleteRole: (id: number) =>\n this.adminCall<{ deleted: boolean }>(\"roles.delete\", { id }),\n setRoleFields: (role_id: number, curated_field_ids: number[]) =>\n this.adminCall<{ role_id: number; field_count: number }>(\"roles.setFields\", { role_id, curated_field_ids }),\n\n listUsers: () => this.adminCall<{ users: UserRoleAssignment[] }>(\"users.list\"),\n assignUserRole: (input: { email: string; role_id: number; is_admin?: boolean }) =>\n this.adminCall<{ assignment: UserRoleAssignment }>(\"users.assignRole\", input),\n removeUserRole: (input: { email: string; role_id: number }) =>\n this.adminCall<{ deleted: boolean }>(\"users.removeRole\", input),\n\n listUserOverrides: (user_id: string) =>\n this.adminCall<{ overrides: UserFieldOverride[] }>(\"users.listOverrides\", { user_id }),\n setUserOverride: (input: { user_id: string; curated_field_id: number; access: \"grant\" | \"deny\" }) =>\n this.adminCall<{ override: UserFieldOverride }>(\"users.setOverride\", input),\n removeUserOverride: (input: { user_id: string; curated_field_id: number }) =>\n this.adminCall<{ deleted: boolean }>(\"users.removeOverride\", input),\n };\n}\n\nexport interface SessionLike {\n user: { id: string; email: string };\n}\n\nexport class SemanticLayerError extends Error {\n code: string;\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SemanticLayerError\";\n this.code = code;\n }\n}\n"]}
@@ -864,48 +864,59 @@ function Inspectable({
864
864
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
865
865
  }
866
866
  const isSelected = registry.selectedId === id;
867
- const showOutline = registry.inspectActive;
867
+ const inspecting = registry.inspectActive;
868
868
  const handleClick = (e) => {
869
- if (!registry.inspectActive) return;
870
869
  e.stopPropagation();
870
+ e.preventDefault();
871
871
  registry.setSelectedId(isSelected ? null : id);
872
872
  };
873
+ if (!inspecting) {
874
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, children });
875
+ }
873
876
  return /* @__PURE__ */ jsxRuntime.jsxs(
874
877
  "div",
875
878
  {
876
879
  ref,
877
- onClick: handleClick,
878
- style: {
879
- position: "relative",
880
- outline: showOutline ? isSelected ? "2px solid #3b82f6" : "2px dashed #93c5fd" : "none",
881
- outlineOffset: 2,
882
- borderRadius: 4,
883
- cursor: showOutline ? "pointer" : "inherit",
884
- transition: "outline 0.15s ease"
885
- },
880
+ style: { position: "relative" },
886
881
  children: [
887
- showOutline && /* @__PURE__ */ jsxRuntime.jsx(
882
+ children,
883
+ /* @__PURE__ */ jsxRuntime.jsx(
888
884
  "div",
889
885
  {
886
+ onClick: handleClick,
890
887
  style: {
891
888
  position: "absolute",
892
- top: -10,
893
- left: 4,
894
- fontSize: 10,
895
- fontWeight: 600,
896
- fontFamily: "system-ui, -apple-system, sans-serif",
897
- color: "#fff",
898
- backgroundColor: isSelected ? "#3b82f6" : "#93c5fd",
899
- padding: "1px 6px",
900
- borderRadius: 3,
901
- zIndex: 1e4,
902
- pointerEvents: "none",
903
- whiteSpace: "nowrap"
889
+ inset: 0,
890
+ zIndex: 9999,
891
+ cursor: "pointer",
892
+ outline: isSelected ? "2px solid #3b82f6" : "2px dashed #93c5fd",
893
+ outlineOffset: 2,
894
+ borderRadius: 4,
895
+ transition: "outline 0.15s ease",
896
+ background: isSelected ? "rgba(59,130,246,0.05)" : "transparent"
904
897
  },
905
- children: label
898
+ children: /* @__PURE__ */ jsxRuntime.jsx(
899
+ "div",
900
+ {
901
+ style: {
902
+ position: "absolute",
903
+ top: -10,
904
+ left: 4,
905
+ fontSize: 10,
906
+ fontWeight: 600,
907
+ fontFamily: "system-ui, -apple-system, sans-serif",
908
+ color: "#fff",
909
+ backgroundColor: isSelected ? "#3b82f6" : "#93c5fd",
910
+ padding: "1px 6px",
911
+ borderRadius: 3,
912
+ pointerEvents: "none",
913
+ whiteSpace: "nowrap"
914
+ },
915
+ children: label
916
+ }
917
+ )
906
918
  }
907
- ),
908
- children
919
+ )
909
920
  ]
910
921
  }
911
922
  );