@inkindcards/semantic-layer 0.1.2 → 0.1.4

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.
@@ -40,6 +40,14 @@ var SemanticLayerClient = class {
40
40
  if (error || !data.url) return null;
41
41
  return data.url;
42
42
  }
43
+ /** Send a one-time code to the given email (for iframe/editor sign-in). */
44
+ async sendOtp(email) {
45
+ return this.supabase.auth.signInWithOtp({ email });
46
+ }
47
+ /** Verify a one-time code received via email. */
48
+ async verifyOtp(email, token) {
49
+ return this.supabase.auth.verifyOtp({ email, token, type: "email" });
50
+ }
43
51
  async signOut() {
44
52
  return this.supabase.auth.signOut();
45
53
  }
@@ -139,5 +147,5 @@ var SemanticLayerError = class extends Error {
139
147
 
140
148
  exports.SemanticLayerClient = SemanticLayerClient;
141
149
  exports.SemanticLayerError = SemanticLayerError;
142
- //# sourceMappingURL=chunk-B4AB5ZWB.cjs.map
143
- //# sourceMappingURL=chunk-B4AB5ZWB.cjs.map
150
+ //# sourceMappingURL=chunk-I4L4FFJY.cjs.map
151
+ //# sourceMappingURL=chunk-I4L4FFJY.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"names":["createClient"],"mappings":"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","file":"chunk-I4L4FFJY.cjs","sourcesContent":["import { createClient, SupabaseClient, Session } from \"@supabase/supabase-js\";\nimport type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n} from \"./types\";\n\nexport class SemanticLayerClient {\n private supabase: SupabaseClient;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n readonly gatewayUrl: string;\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n this.supabase = createClient(config.gatewayUrl, config.anonKey, {\n auth: {\n persistSession: true,\n autoRefreshToken: true,\n storageKey: \"semantic-layer-auth\",\n },\n });\n }\n\n /** Access the underlying Supabase client (for auth operations). */\n getSupabaseClient(): SupabaseClient {\n return this.supabase;\n }\n\n // ─── Auth ────────────────────────────────────────────────────────────────────\n\n async signInWithGoogle(redirectTo?: string) {\n return this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: { redirectTo },\n });\n }\n\n /** Get the Google sign-in URL without triggering a redirect (for popup flows). */\n async getSignInUrl(redirectTo?: string): Promise<string | null> {\n const { data, error } = await this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: {\n redirectTo,\n skipBrowserRedirect: true,\n },\n });\n if (error || !data.url) return null;\n return data.url;\n }\n\n /** Send a one-time code to the given email (for iframe/editor sign-in). */\n async sendOtp(email: string) {\n return this.supabase.auth.signInWithOtp({ email });\n }\n\n /** Verify a one-time code received via email. */\n async verifyOtp(email: string, token: string) {\n return this.supabase.auth.verifyOtp({ email, token, type: \"email\" });\n }\n\n async signOut() {\n return this.supabase.auth.signOut();\n }\n\n async getSession(): Promise<Session | null> {\n const { data } = await this.supabase.auth.getSession();\n return data.session;\n }\n\n onAuthStateChange(callback: (event: string, session: Session | null) => void) {\n return this.supabase.auth.onAuthStateChange(callback);\n }\n\n // ─── Metadata ────────────────────────────────────────────────────────────────\n\n /**\n * Fetch the curated catalog of metrics and dimensions from the gateway.\n * Results are cached for 5 minutes.\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, error } = await this.supabase.functions.invoke(\"dbt-metadata\");\n\n if (error) {\n throw new SemanticLayerError(`Failed to fetch metadata: ${error.message}`, \"METADATA_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"METADATA_ERROR\");\n }\n\n this.metadataCache = data as MetadataResponse;\n this.metadataCacheTime = now;\n return this.metadataCache;\n }\n\n /** Get only metrics from the catalog. */\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n /** Get only dimensions (including time dimensions) from the catalog. */\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 /** Find a field by name or id. */\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 /** Execute a query using the full PivotConfig format. */\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n\n const { data, error } = await this.supabase.functions.invoke(\"dbt-query\", {\n body: { config },\n });\n\n if (error) {\n throw new SemanticLayerError(`Query failed: ${error.message}`, \"QUERY_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"QUERY_ERROR\");\n }\n\n return data as QueryResult;\n }\n\n /**\n * Execute a query using the simplified input format.\n * Automatically resolves metric/dimension names to full field objects.\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\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"]}
@@ -12,13 +12,21 @@ function useSemanticLayer() {
12
12
  return ctx;
13
13
  }
14
14
  function useAuth() {
15
- const { client, auth } = useSemanticLayer();
15
+ const { client, auth, emailDomain } = useSemanticLayer();
16
16
  const signIn = react.useCallback(
17
17
  (redirectTo) => client.signInWithGoogle(redirectTo),
18
18
  [client]
19
19
  );
20
+ const sendOtp = react.useCallback(
21
+ (email) => client.sendOtp(email),
22
+ [client]
23
+ );
24
+ const verifyOtp = react.useCallback(
25
+ (email, token) => client.verifyOtp(email, token),
26
+ [client]
27
+ );
20
28
  const signOut = react.useCallback(() => client.signOut(), [client]);
21
- return { ...auth, signIn, signOut };
29
+ return { ...auth, signIn, sendOtp, verifyOtp, signOut, emailDomain };
22
30
  }
23
31
  function useMetrics() {
24
32
  const { client, auth } = useSemanticLayer();
@@ -123,5 +131,5 @@ exports.useAuth = useAuth;
123
131
  exports.useMetrics = useMetrics;
124
132
  exports.usePivotQuery = usePivotQuery;
125
133
  exports.useSemanticQuery = useSemanticQuery;
126
- //# sourceMappingURL=chunk-Y3A3T45C.cjs.map
127
- //# sourceMappingURL=chunk-Y3A3T45C.cjs.map
134
+ //# sourceMappingURL=chunk-OJVM3RPD.cjs.map
135
+ //# sourceMappingURL=chunk-OJVM3RPD.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/context.ts","../src/react/hooks.ts"],"names":["createContext","useContext","useCallback","useState","useRef","useEffect"],"mappings":"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","file":"chunk-OJVM3RPD.cjs","sourcesContent":["import { createContext } from \"react\";\nimport type { SemanticLayerClient } from \"../client\";\nimport type { AuthState } from \"../types\";\n\nexport interface SemanticLayerContextValue {\n client: SemanticLayerClient;\n auth: AuthState;\n emailDomain?: string;\n}\n\nexport const SemanticLayerContext = createContext<SemanticLayerContextValue | null>(null);\n","import { useContext, useCallback, useEffect, useState, useRef } from \"react\";\nimport { SemanticLayerContext } from \"./context\";\nimport type {\n SemanticField,\n FieldCategory,\n QueryResult,\n SimpleQueryInput,\n PivotConfig,\n AuthState,\n} from \"../types\";\n\nfunction useSemanticLayer() {\n const ctx = useContext(SemanticLayerContext);\n if (!ctx) {\n throw new Error(\"useSemanticLayer hooks must be used within a <SemanticLayerProvider>\");\n }\n return ctx;\n}\n\n/** Returns the current auth state and sign-in/sign-out methods. */\nexport function useAuth() {\n const { client, auth, emailDomain } = useSemanticLayer();\n\n const signIn = useCallback(\n (redirectTo?: string) => client.signInWithGoogle(redirectTo),\n [client],\n );\n\n const sendOtp = useCallback(\n (email: string) => client.sendOtp(email),\n [client],\n );\n\n const verifyOtp = useCallback(\n (email: string, token: string) => client.verifyOtp(email, token),\n [client],\n );\n\n const signOut = useCallback(() => client.signOut(), [client]);\n\n return { ...auth, signIn, sendOtp, verifyOtp, signOut, emailDomain };\n}\n\ninterface UseMetricsResult {\n fields: SemanticField[];\n metrics: SemanticField[];\n dimensions: SemanticField[];\n categories: FieldCategory[];\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/** Fetch the full curated catalog of metrics and dimensions. */\nexport function useMetrics(): UseMetricsResult {\n const { client, auth } = useSemanticLayer();\n const [fields, setFields] = useState<SemanticField[]>([]);\n const [categories, setCategories] = useState<FieldCategory[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n\n const fetch = useCallback(\n async (force = false) => {\n if (!auth.isAuthenticated) return;\n setIsLoading(true);\n setError(null);\n try {\n const data = await client.getMetadata(force);\n setFields(data.fields);\n setCategories(data.categories);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load metadata\");\n } finally {\n setIsLoading(false);\n }\n },\n [client, auth.isAuthenticated],\n );\n\n useEffect(() => {\n if (auth.isAuthenticated && !fetchedRef.current) {\n fetchedRef.current = true;\n fetch();\n }\n }, [auth.isAuthenticated, fetch]);\n\n const refetch = useCallback(() => fetch(true), [fetch]);\n\n return {\n fields,\n metrics: fields.filter((f) => f.type === \"metric\"),\n dimensions: fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\"),\n categories,\n isLoading,\n error,\n refetch,\n };\n}\n\ninterface UseSemanticQueryOptions {\n /** Set to false to prevent the query from running automatically. */\n enabled?: boolean;\n}\n\ninterface UseSemanticQueryResult {\n data: QueryResult | null;\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/**\n * Execute a query against the dbt Semantic Layer using the simple input format.\n * The query runs automatically when the input changes (unless enabled=false).\n */\nexport function useSemanticQuery(\n input: SimpleQueryInput | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const inputKey = JSON.stringify(input);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !input || !enabled) return;\n if (input.metrics.length === 0) {\n setData({ columns: [], rows: [], totalRows: 0, executionTimeMs: 0 });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.simpleQuery(input);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, inputKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n\n/**\n * Execute a query using the full PivotConfig format.\n * Use this for advanced use cases (column pivoting, custom aggregations).\n */\nexport function usePivotQuery(\n config: PivotConfig | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const configKey = JSON.stringify(config);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !config || !enabled) return;\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.query(config);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, configKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n"]}
@@ -38,6 +38,14 @@ var SemanticLayerClient = class {
38
38
  if (error || !data.url) return null;
39
39
  return data.url;
40
40
  }
41
+ /** Send a one-time code to the given email (for iframe/editor sign-in). */
42
+ async sendOtp(email) {
43
+ return this.supabase.auth.signInWithOtp({ email });
44
+ }
45
+ /** Verify a one-time code received via email. */
46
+ async verifyOtp(email, token) {
47
+ return this.supabase.auth.verifyOtp({ email, token, type: "email" });
48
+ }
41
49
  async signOut() {
42
50
  return this.supabase.auth.signOut();
43
51
  }
@@ -136,5 +144,5 @@ var SemanticLayerError = class extends Error {
136
144
  };
137
145
 
138
146
  export { SemanticLayerClient, SemanticLayerError };
139
- //# sourceMappingURL=chunk-DHFL2XZB.js.map
140
- //# sourceMappingURL=chunk-DHFL2XZB.js.map
147
+ //# sourceMappingURL=chunk-P72N6ISJ.js.map
148
+ //# sourceMappingURL=chunk-P72N6ISJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"chunk-P72N6ISJ.js","sourcesContent":["import { createClient, SupabaseClient, Session } from \"@supabase/supabase-js\";\nimport type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n} from \"./types\";\n\nexport class SemanticLayerClient {\n private supabase: SupabaseClient;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n readonly gatewayUrl: string;\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n this.supabase = createClient(config.gatewayUrl, config.anonKey, {\n auth: {\n persistSession: true,\n autoRefreshToken: true,\n storageKey: \"semantic-layer-auth\",\n },\n });\n }\n\n /** Access the underlying Supabase client (for auth operations). */\n getSupabaseClient(): SupabaseClient {\n return this.supabase;\n }\n\n // ─── Auth ────────────────────────────────────────────────────────────────────\n\n async signInWithGoogle(redirectTo?: string) {\n return this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: { redirectTo },\n });\n }\n\n /** Get the Google sign-in URL without triggering a redirect (for popup flows). */\n async getSignInUrl(redirectTo?: string): Promise<string | null> {\n const { data, error } = await this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: {\n redirectTo,\n skipBrowserRedirect: true,\n },\n });\n if (error || !data.url) return null;\n return data.url;\n }\n\n /** Send a one-time code to the given email (for iframe/editor sign-in). */\n async sendOtp(email: string) {\n return this.supabase.auth.signInWithOtp({ email });\n }\n\n /** Verify a one-time code received via email. */\n async verifyOtp(email: string, token: string) {\n return this.supabase.auth.verifyOtp({ email, token, type: \"email\" });\n }\n\n async signOut() {\n return this.supabase.auth.signOut();\n }\n\n async getSession(): Promise<Session | null> {\n const { data } = await this.supabase.auth.getSession();\n return data.session;\n }\n\n onAuthStateChange(callback: (event: string, session: Session | null) => void) {\n return this.supabase.auth.onAuthStateChange(callback);\n }\n\n // ─── Metadata ────────────────────────────────────────────────────────────────\n\n /**\n * Fetch the curated catalog of metrics and dimensions from the gateway.\n * Results are cached for 5 minutes.\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, error } = await this.supabase.functions.invoke(\"dbt-metadata\");\n\n if (error) {\n throw new SemanticLayerError(`Failed to fetch metadata: ${error.message}`, \"METADATA_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"METADATA_ERROR\");\n }\n\n this.metadataCache = data as MetadataResponse;\n this.metadataCacheTime = now;\n return this.metadataCache;\n }\n\n /** Get only metrics from the catalog. */\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n /** Get only dimensions (including time dimensions) from the catalog. */\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 /** Find a field by name or id. */\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 /** Execute a query using the full PivotConfig format. */\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n\n const { data, error } = await this.supabase.functions.invoke(\"dbt-query\", {\n body: { config },\n });\n\n if (error) {\n throw new SemanticLayerError(`Query failed: ${error.message}`, \"QUERY_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"QUERY_ERROR\");\n }\n\n return data as QueryResult;\n }\n\n /**\n * Execute a query using the simplified input format.\n * Automatically resolves metric/dimension names to full field objects.\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\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"]}
@@ -10,13 +10,21 @@ function useSemanticLayer() {
10
10
  return ctx;
11
11
  }
12
12
  function useAuth() {
13
- const { client, auth } = useSemanticLayer();
13
+ const { client, auth, emailDomain } = useSemanticLayer();
14
14
  const signIn = useCallback(
15
15
  (redirectTo) => client.signInWithGoogle(redirectTo),
16
16
  [client]
17
17
  );
18
+ const sendOtp = useCallback(
19
+ (email) => client.sendOtp(email),
20
+ [client]
21
+ );
22
+ const verifyOtp = useCallback(
23
+ (email, token) => client.verifyOtp(email, token),
24
+ [client]
25
+ );
18
26
  const signOut = useCallback(() => client.signOut(), [client]);
19
- return { ...auth, signIn, signOut };
27
+ return { ...auth, signIn, sendOtp, verifyOtp, signOut, emailDomain };
20
28
  }
21
29
  function useMetrics() {
22
30
  const { client, auth } = useSemanticLayer();
@@ -117,5 +125,5 @@ function usePivotQuery(config, options = {}) {
117
125
  }
118
126
 
119
127
  export { SemanticLayerContext, useAuth, useMetrics, usePivotQuery, useSemanticQuery };
120
- //# sourceMappingURL=chunk-NJ4IJBV3.js.map
121
- //# sourceMappingURL=chunk-NJ4IJBV3.js.map
128
+ //# sourceMappingURL=chunk-RGVYFSW2.js.map
129
+ //# sourceMappingURL=chunk-RGVYFSW2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/context.ts","../src/react/hooks.ts"],"names":[],"mappings":";;;AAUO,IAAM,oBAAA,GAAuB,cAAgD,IAAI;ACCxF,SAAS,gBAAA,GAAmB;AAC1B,EAAA,MAAM,GAAA,GAAM,WAAW,oBAAoB,CAAA;AAC3C,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,MAAM,sEAAsE,CAAA;AAAA,EACxF;AACA,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAM,WAAA,KAAgB,gBAAA,EAAiB;AAEvD,EAAA,MAAM,MAAA,GAAS,WAAA;AAAA,IACb,CAAC,UAAA,KAAwB,MAAA,CAAO,gBAAA,CAAiB,UAAU,CAAA;AAAA,IAC3D,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,OAAA,GAAU,WAAA;AAAA,IACd,CAAC,KAAA,KAAkB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAAA,IACvC,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,KAAA,EAAe,KAAA,KAAkB,MAAA,CAAO,SAAA,CAAU,OAAO,KAAK,CAAA;AAAA,IAC/D,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,OAAA,GAAU,YAAY,MAAM,MAAA,CAAO,SAAQ,EAAG,CAAC,MAAM,CAAC,CAAA;AAE5D,EAAA,OAAO,EAAE,GAAG,IAAA,EAAM,QAAQ,OAAA,EAAS,SAAA,EAAW,SAAS,WAAA,EAAY;AACrE;AAaO,SAAS,UAAA,GAA+B;AAC7C,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,gBAAA,EAAiB;AAC1C,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,QAAA,CAA0B,EAAE,CAAA;AACxD,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAA,CAA0B,EAAE,CAAA;AAChE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,UAAA,GAAa,OAAO,KAAK,CAAA;AAE/B,EAAA,MAAM,KAAA,GAAQ,WAAA;AAAA,IACZ,OAAO,QAAQ,KAAA,KAAU;AACvB,MAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AAC3B,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,WAAA,CAAY,KAAK,CAAA;AAC3C,QAAA,SAAA,CAAU,KAAK,MAAM,CAAA;AACrB,QAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAAA,MAC/B,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,yBAAyB,CAAA;AAAA,MACzE,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,CAAK,eAAe;AAAA,GAC/B;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,IAAA,CAAK,eAAA,IAAmB,CAAC,UAAA,CAAW,OAAA,EAAS;AAC/C,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA,KAAA,EAAM;AAAA,IACR;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,CAAK,eAAA,EAAiB,KAAK,CAAC,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAU,YAAY,MAAM,KAAA,CAAM,IAAI,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEtD,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,SAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,QAAQ,CAAA;AAAA,IACjD,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,WAAA,IAAe,CAAA,CAAE,IAAA,KAAS,gBAAgB,CAAA;AAAA,IACtF,UAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAkBO,SAAS,gBAAA,CACd,KAAA,EACA,OAAA,GAAmC,EAAC,EACZ;AACxB,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,gBAAA,EAAiB;AAC1C,EAAA,MAAM,EAAE,OAAA,GAAU,IAAA,EAAK,GAAI,OAAA;AAC3B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,IAAI,CAAA;AACzD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAErC,EAAA,MAAM,OAAA,GAAU,YAAY,YAAY;AACtC,IAAA,IAAI,CAAC,IAAA,CAAK,eAAA,IAAmB,CAAC,KAAA,IAAS,CAAC,OAAA,EAAS;AACjD,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,EAAE,OAAA,EAAS,EAAC,EAAG,IAAA,EAAM,EAAC,EAAG,SAAA,EAAW,CAAA,EAAG,eAAA,EAAiB,CAAA,EAAG,CAAA;AACnE,MAAA;AAAA,IACF;AAEA,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,WAAA,CAAY,KAAK,CAAA;AAC7C,MAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,cAAc,CAAA;AAC5D,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,KAAK,eAAA,EAAiB,QAAA,EAAU,OAAO,CAAC,CAAA;AAEpD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,SAAS,OAAA,EAAQ;AACpD;AAMO,SAAS,aAAA,CACd,MAAA,EACA,OAAA,GAAmC,EAAC,EACZ;AACxB,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,gBAAA,EAAiB;AAC1C,EAAA,MAAM,EAAE,OAAA,GAAU,IAAA,EAAK,GAAI,OAAA;AAC3B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,IAAI,CAAA;AACzD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAEvC,EAAA,MAAM,OAAA,GAAU,YAAY,YAAY;AACtC,IAAA,IAAI,CAAC,IAAA,CAAK,eAAA,IAAmB,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS;AAElD,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA;AACxC,MAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,cAAc,CAAA;AAC5D,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,KAAK,eAAA,EAAiB,SAAA,EAAW,OAAO,CAAC,CAAA;AAErD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,SAAS,OAAA,EAAQ;AACpD","file":"chunk-RGVYFSW2.js","sourcesContent":["import { createContext } from \"react\";\nimport type { SemanticLayerClient } from \"../client\";\nimport type { AuthState } from \"../types\";\n\nexport interface SemanticLayerContextValue {\n client: SemanticLayerClient;\n auth: AuthState;\n emailDomain?: string;\n}\n\nexport const SemanticLayerContext = createContext<SemanticLayerContextValue | null>(null);\n","import { useContext, useCallback, useEffect, useState, useRef } from \"react\";\nimport { SemanticLayerContext } from \"./context\";\nimport type {\n SemanticField,\n FieldCategory,\n QueryResult,\n SimpleQueryInput,\n PivotConfig,\n AuthState,\n} from \"../types\";\n\nfunction useSemanticLayer() {\n const ctx = useContext(SemanticLayerContext);\n if (!ctx) {\n throw new Error(\"useSemanticLayer hooks must be used within a <SemanticLayerProvider>\");\n }\n return ctx;\n}\n\n/** Returns the current auth state and sign-in/sign-out methods. */\nexport function useAuth() {\n const { client, auth, emailDomain } = useSemanticLayer();\n\n const signIn = useCallback(\n (redirectTo?: string) => client.signInWithGoogle(redirectTo),\n [client],\n );\n\n const sendOtp = useCallback(\n (email: string) => client.sendOtp(email),\n [client],\n );\n\n const verifyOtp = useCallback(\n (email: string, token: string) => client.verifyOtp(email, token),\n [client],\n );\n\n const signOut = useCallback(() => client.signOut(), [client]);\n\n return { ...auth, signIn, sendOtp, verifyOtp, signOut, emailDomain };\n}\n\ninterface UseMetricsResult {\n fields: SemanticField[];\n metrics: SemanticField[];\n dimensions: SemanticField[];\n categories: FieldCategory[];\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/** Fetch the full curated catalog of metrics and dimensions. */\nexport function useMetrics(): UseMetricsResult {\n const { client, auth } = useSemanticLayer();\n const [fields, setFields] = useState<SemanticField[]>([]);\n const [categories, setCategories] = useState<FieldCategory[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n\n const fetch = useCallback(\n async (force = false) => {\n if (!auth.isAuthenticated) return;\n setIsLoading(true);\n setError(null);\n try {\n const data = await client.getMetadata(force);\n setFields(data.fields);\n setCategories(data.categories);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load metadata\");\n } finally {\n setIsLoading(false);\n }\n },\n [client, auth.isAuthenticated],\n );\n\n useEffect(() => {\n if (auth.isAuthenticated && !fetchedRef.current) {\n fetchedRef.current = true;\n fetch();\n }\n }, [auth.isAuthenticated, fetch]);\n\n const refetch = useCallback(() => fetch(true), [fetch]);\n\n return {\n fields,\n metrics: fields.filter((f) => f.type === \"metric\"),\n dimensions: fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\"),\n categories,\n isLoading,\n error,\n refetch,\n };\n}\n\ninterface UseSemanticQueryOptions {\n /** Set to false to prevent the query from running automatically. */\n enabled?: boolean;\n}\n\ninterface UseSemanticQueryResult {\n data: QueryResult | null;\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/**\n * Execute a query against the dbt Semantic Layer using the simple input format.\n * The query runs automatically when the input changes (unless enabled=false).\n */\nexport function useSemanticQuery(\n input: SimpleQueryInput | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const inputKey = JSON.stringify(input);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !input || !enabled) return;\n if (input.metrics.length === 0) {\n setData({ columns: [], rows: [], totalRows: 0, executionTimeMs: 0 });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.simpleQuery(input);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, inputKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n\n/**\n * Execute a query using the full PivotConfig format.\n * Use this for advanced use cases (column pivoting, custom aggregations).\n */\nexport function usePivotQuery(\n config: PivotConfig | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const configKey = JSON.stringify(config);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !config || !enabled) return;\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.query(config);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, configKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkY3A3T45C_cjs = require('./chunk-Y3A3T45C.cjs');
3
+ var chunkOJVM3RPD_cjs = require('./chunk-OJVM3RPD.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -56,7 +56,7 @@ function MetricPicker({
56
56
  searchPlaceholder = "Search metrics and dimensions...",
57
57
  className
58
58
  }) {
59
- const { fields, categories, isLoading, error } = chunkY3A3T45C_cjs.useMetrics();
59
+ const { fields, categories, isLoading, error } = chunkOJVM3RPD_cjs.useMetrics();
60
60
  const [search, setSearch] = react.useState("");
61
61
  const filtered = react.useMemo(() => {
62
62
  let result = fields;
@@ -1,4 +1,4 @@
1
- import { useMetrics } from './chunk-NJ4IJBV3.js';
1
+ import { useMetrics } from './chunk-RGVYFSW2.js';
2
2
  import { useState, useMemo } from 'react';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
4
 
package/dist/index.cjs CHANGED
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var chunkB4AB5ZWB_cjs = require('./chunk-B4AB5ZWB.cjs');
3
+ var chunkI4L4FFJY_cjs = require('./chunk-I4L4FFJY.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "SemanticLayerClient", {
8
8
  enumerable: true,
9
- get: function () { return chunkB4AB5ZWB_cjs.SemanticLayerClient; }
9
+ get: function () { return chunkI4L4FFJY_cjs.SemanticLayerClient; }
10
10
  });
11
11
  Object.defineProperty(exports, "SemanticLayerError", {
12
12
  enumerable: true,
13
- get: function () { return chunkB4AB5ZWB_cjs.SemanticLayerError; }
13
+ get: function () { return chunkI4L4FFJY_cjs.SemanticLayerError; }
14
14
  });
15
15
  //# sourceMappingURL=index.cjs.map
16
16
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -15,6 +15,10 @@ declare class SemanticLayerClient {
15
15
  signInWithGoogle(redirectTo?: string): Promise<_supabase_auth_js.OAuthResponse>;
16
16
  /** Get the Google sign-in URL without triggering a redirect (for popup flows). */
17
17
  getSignInUrl(redirectTo?: string): Promise<string | null>;
18
+ /** Send a one-time code to the given email (for iframe/editor sign-in). */
19
+ sendOtp(email: string): Promise<_supabase_auth_js.AuthOtpResponse>;
20
+ /** Verify a one-time code received via email. */
21
+ verifyOtp(email: string, token: string): Promise<_supabase_auth_js.AuthResponse>;
18
22
  signOut(): Promise<{
19
23
  error: _supabase_auth_js.AuthError | null;
20
24
  }>;
package/dist/index.d.ts CHANGED
@@ -15,6 +15,10 @@ declare class SemanticLayerClient {
15
15
  signInWithGoogle(redirectTo?: string): Promise<_supabase_auth_js.OAuthResponse>;
16
16
  /** Get the Google sign-in URL without triggering a redirect (for popup flows). */
17
17
  getSignInUrl(redirectTo?: string): Promise<string | null>;
18
+ /** Send a one-time code to the given email (for iframe/editor sign-in). */
19
+ sendOtp(email: string): Promise<_supabase_auth_js.AuthOtpResponse>;
20
+ /** Verify a one-time code received via email. */
21
+ verifyOtp(email: string, token: string): Promise<_supabase_auth_js.AuthResponse>;
18
22
  signOut(): Promise<{
19
23
  error: _supabase_auth_js.AuthError | null;
20
24
  }>;
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { SemanticLayerClient, SemanticLayerError } from './chunk-DHFL2XZB.js';
1
+ export { SemanticLayerClient, SemanticLayerError } from './chunk-P72N6ISJ.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/react.cjs CHANGED
@@ -1,19 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var chunkB4AB5ZWB_cjs = require('./chunk-B4AB5ZWB.cjs');
4
- var chunkY3A3T45C_cjs = require('./chunk-Y3A3T45C.cjs');
3
+ var chunkI4L4FFJY_cjs = require('./chunk-I4L4FFJY.cjs');
4
+ var chunkOJVM3RPD_cjs = require('./chunk-OJVM3RPD.cjs');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
8
  function SemanticLayerProvider({
9
9
  gatewayUrl,
10
10
  anonKey,
11
+ emailDomain,
11
12
  client: externalClient,
12
13
  children
13
14
  }) {
14
15
  const client = react.useMemo(() => {
15
16
  if (externalClient) return externalClient;
16
- return new chunkB4AB5ZWB_cjs.SemanticLayerClient({ gatewayUrl, anonKey });
17
+ return new chunkI4L4FFJY_cjs.SemanticLayerClient({ gatewayUrl, anonKey });
17
18
  }, [gatewayUrl, anonKey, externalClient]);
18
19
  const [auth, setAuth] = react.useState({
19
20
  isAuthenticated: false,
@@ -76,27 +77,27 @@ function SemanticLayerProvider({
76
77
  subscription.unsubscribe();
77
78
  };
78
79
  }, [client]);
79
- const value = react.useMemo(() => ({ client, auth }), [client, auth]);
80
- return /* @__PURE__ */ jsxRuntime.jsx(chunkY3A3T45C_cjs.SemanticLayerContext.Provider, { value, children });
80
+ const value = react.useMemo(() => ({ client, auth, emailDomain }), [client, auth, emailDomain]);
81
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkOJVM3RPD_cjs.SemanticLayerContext.Provider, { value, children });
81
82
  }
82
- var defaultLoadingStyle = {
83
+ var containerStyle = {
83
84
  display: "flex",
85
+ flexDirection: "column",
84
86
  alignItems: "center",
85
87
  justifyContent: "center",
86
88
  minHeight: "100vh",
87
89
  fontFamily: "system-ui, -apple-system, sans-serif",
88
- color: "#6b7280"
90
+ gap: "16px"
89
91
  };
90
- var defaultContainerStyle = {
92
+ var loadingStyle = {
91
93
  display: "flex",
92
- flexDirection: "column",
93
94
  alignItems: "center",
94
95
  justifyContent: "center",
95
96
  minHeight: "100vh",
96
97
  fontFamily: "system-ui, -apple-system, sans-serif",
97
- gap: "16px"
98
+ color: "#6b7280"
98
99
  };
99
- var defaultButtonStyle = {
100
+ var buttonStyle = {
100
101
  padding: "12px 24px",
101
102
  fontSize: "16px",
102
103
  fontWeight: 500,
@@ -109,6 +110,28 @@ var defaultButtonStyle = {
109
110
  alignItems: "center",
110
111
  gap: "8px"
111
112
  };
113
+ var inputStyle = {
114
+ padding: "10px 14px",
115
+ fontSize: "16px",
116
+ border: "1px solid #d1d5db",
117
+ borderRadius: "8px",
118
+ width: "280px",
119
+ fontFamily: "system-ui, -apple-system, sans-serif"
120
+ };
121
+ var errorStyle = {
122
+ margin: 0,
123
+ color: "#ef4444",
124
+ fontSize: "14px"
125
+ };
126
+ var linkStyle = {
127
+ background: "none",
128
+ border: "none",
129
+ color: "#4285f4",
130
+ cursor: "pointer",
131
+ fontSize: "14px",
132
+ padding: 0,
133
+ textDecoration: "underline"
134
+ };
112
135
  function isInIframe() {
113
136
  try {
114
137
  return typeof window !== "undefined" && window.self !== window.top;
@@ -116,47 +139,127 @@ function isInIframe() {
116
139
  return true;
117
140
  }
118
141
  }
119
- function AuthGate({ children, loading, signInComponent }) {
120
- const { isAuthenticated, isLoading, error, signIn } = chunkY3A3T45C_cjs.useAuth();
121
- const ctx = react.useContext(chunkY3A3T45C_cjs.SemanticLayerContext);
122
- const client = ctx?.client;
123
- const inIframe = isInIframe();
124
- react.useEffect(() => {
125
- if (!inIframe || !client) return;
126
- const handler = (event) => {
127
- if (event.data?.type === "semantic-layer-auth-callback" && event.data.access_token) {
128
- client.getSupabaseClient().auth.setSession({
129
- access_token: event.data.access_token,
130
- refresh_token: event.data.refresh_token
131
- });
142
+ function OtpSignIn() {
143
+ const { sendOtp, verifyOtp, emailDomain } = chunkOJVM3RPD_cjs.useAuth();
144
+ const [email, setEmail] = react.useState("");
145
+ const [code, setCode] = react.useState("");
146
+ const [step, setStep] = react.useState("email");
147
+ const [sending, setSending] = react.useState(false);
148
+ const [error, setError] = react.useState(null);
149
+ const handleSendCode = react.useCallback(async () => {
150
+ setError(null);
151
+ const trimmed = email.trim().toLowerCase();
152
+ if (!trimmed) {
153
+ setError("Please enter your email.");
154
+ return;
155
+ }
156
+ if (emailDomain && !trimmed.endsWith(`@${emailDomain}`)) {
157
+ setError(`Please use your @${emailDomain} email.`);
158
+ return;
159
+ }
160
+ setSending(true);
161
+ try {
162
+ const { error: otpError } = await sendOtp(trimmed);
163
+ if (otpError) {
164
+ setError(otpError.message);
165
+ } else {
166
+ setStep("code");
132
167
  }
133
- };
134
- window.addEventListener("message", handler);
135
- return () => window.removeEventListener("message", handler);
136
- }, [inIframe, client]);
137
- const handleSignIn = react.useCallback(async () => {
138
- if (inIframe && client) {
139
- const callbackUrl = `${client.gatewayUrl}/functions/v1/auth-callback`;
140
- const url = await client.getSignInUrl(callbackUrl);
141
- if (url) {
142
- window.open(url, "semantic-layer-auth", "popup,width=600,height=700");
168
+ } catch (err) {
169
+ setError(err instanceof Error ? err.message : "Failed to send code");
170
+ } finally {
171
+ setSending(false);
172
+ }
173
+ }, [email, emailDomain, sendOtp]);
174
+ const handleVerifyCode = react.useCallback(async () => {
175
+ setError(null);
176
+ const trimmedCode = code.trim();
177
+ if (!trimmedCode) {
178
+ setError("Please enter the code from your email.");
179
+ return;
180
+ }
181
+ setSending(true);
182
+ try {
183
+ const { error: verifyError } = await verifyOtp(email.trim().toLowerCase(), trimmedCode);
184
+ if (verifyError) {
185
+ setError(verifyError.message);
143
186
  }
144
- } else {
145
- signIn(window.location.origin);
187
+ } catch (err) {
188
+ setError(err instanceof Error ? err.message : "Verification failed");
189
+ } finally {
190
+ setSending(false);
146
191
  }
147
- }, [inIframe, client, signIn]);
192
+ }, [email, code, verifyOtp]);
193
+ if (step === "code") {
194
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
195
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Check your email" }),
196
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { margin: 0, color: "#6b7280", textAlign: "center", maxWidth: "320px" }, children: [
197
+ "We sent a sign-in code to ",
198
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: email.trim() })
199
+ ] }),
200
+ /* @__PURE__ */ jsxRuntime.jsx(
201
+ "input",
202
+ {
203
+ style: inputStyle,
204
+ type: "text",
205
+ inputMode: "numeric",
206
+ autoComplete: "one-time-code",
207
+ placeholder: "Enter 6-digit code",
208
+ value: code,
209
+ onChange: (e) => setCode(e.target.value),
210
+ onKeyDown: (e) => e.key === "Enter" && handleVerifyCode()
211
+ }
212
+ ),
213
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: errorStyle, children: error }),
214
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: buttonStyle, onClick: handleVerifyCode, disabled: sending, children: sending ? "Verifying..." : "Verify code" }),
215
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: linkStyle, onClick: () => {
216
+ setStep("email");
217
+ setCode("");
218
+ setError(null);
219
+ }, children: "Use a different email" })
220
+ ] });
221
+ }
222
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
223
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Sign in to continue" }),
224
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { margin: 0, color: "#6b7280" }, children: [
225
+ "Enter your ",
226
+ emailDomain ? `@${emailDomain} ` : "",
227
+ "email to receive a sign-in code."
228
+ ] }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(
230
+ "input",
231
+ {
232
+ style: inputStyle,
233
+ type: "email",
234
+ placeholder: emailDomain ? `you@${emailDomain}` : "you@company.com",
235
+ value: email,
236
+ onChange: (e) => setEmail(e.target.value),
237
+ onKeyDown: (e) => e.key === "Enter" && handleSendCode()
238
+ }
239
+ ),
240
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: errorStyle, children: error }),
241
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: buttonStyle, onClick: handleSendCode, disabled: sending, children: sending ? "Sending..." : "Send sign-in code" })
242
+ ] });
243
+ }
244
+ function AuthGate({ children, loading, signInComponent, useEmailOtp }) {
245
+ const { isAuthenticated, isLoading, error, signIn } = chunkOJVM3RPD_cjs.useAuth();
246
+ const inIframe = isInIframe();
247
+ const shouldUseOtp = useEmailOtp || inIframe;
148
248
  if (isLoading) {
149
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loading || /* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultLoadingStyle, children: "Loading..." }) });
249
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loading || /* @__PURE__ */ jsxRuntime.jsx("div", { style: loadingStyle, children: "Loading..." }) });
150
250
  }
151
251
  if (!isAuthenticated) {
252
+ if (shouldUseOtp) {
253
+ return /* @__PURE__ */ jsxRuntime.jsx(OtpSignIn, {});
254
+ }
152
255
  if (signInComponent) {
153
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: signInComponent({ signIn: handleSignIn }) });
256
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: signInComponent({ signIn: () => signIn(window.location.origin) }) });
154
257
  }
155
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultContainerStyle, children: [
258
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
156
259
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Sign in to continue" }),
157
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "#6b7280" }, children: "Use your inKind Google account to access data." }),
158
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "#ef4444", fontSize: "14px" }, children: error }),
159
- /* @__PURE__ */ jsxRuntime.jsx("button", { style: defaultButtonStyle, onClick: handleSignIn, children: "Sign in with Google" })
260
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "#6b7280" }, children: "Use your Google account to access data." }),
261
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: errorStyle, children: error }),
262
+ /* @__PURE__ */ jsxRuntime.jsx("button", { style: buttonStyle, onClick: () => signIn(window.location.origin), children: "Sign in with Google" })
160
263
  ] });
161
264
  }
162
265
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
@@ -164,23 +267,23 @@ function AuthGate({ children, loading, signInComponent }) {
164
267
 
165
268
  Object.defineProperty(exports, "SemanticLayerContext", {
166
269
  enumerable: true,
167
- get: function () { return chunkY3A3T45C_cjs.SemanticLayerContext; }
270
+ get: function () { return chunkOJVM3RPD_cjs.SemanticLayerContext; }
168
271
  });
169
272
  Object.defineProperty(exports, "useAuth", {
170
273
  enumerable: true,
171
- get: function () { return chunkY3A3T45C_cjs.useAuth; }
274
+ get: function () { return chunkOJVM3RPD_cjs.useAuth; }
172
275
  });
173
276
  Object.defineProperty(exports, "useMetrics", {
174
277
  enumerable: true,
175
- get: function () { return chunkY3A3T45C_cjs.useMetrics; }
278
+ get: function () { return chunkOJVM3RPD_cjs.useMetrics; }
176
279
  });
177
280
  Object.defineProperty(exports, "usePivotQuery", {
178
281
  enumerable: true,
179
- get: function () { return chunkY3A3T45C_cjs.usePivotQuery; }
282
+ get: function () { return chunkOJVM3RPD_cjs.usePivotQuery; }
180
283
  });
181
284
  Object.defineProperty(exports, "useSemanticQuery", {
182
285
  enumerable: true,
183
- get: function () { return chunkY3A3T45C_cjs.useSemanticQuery; }
286
+ get: function () { return chunkOJVM3RPD_cjs.useSemanticQuery; }
184
287
  });
185
288
  exports.AuthGate = AuthGate;
186
289
  exports.SemanticLayerProvider = SemanticLayerProvider;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/provider.tsx","../src/react/auth-gate.tsx"],"names":["useMemo","SemanticLayerClient","useState","useEffect","jsx","SemanticLayerContext","useAuth","useContext","useCallback","Fragment","jsxs"],"mappings":"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","file":"react.cjs","sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { SemanticLayerClient } from \"../client\";\nimport type { SemanticLayerConfig, AuthState } from \"../types\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface SemanticLayerProviderProps {\n /** The Supabase URL of the gateway project. */\n gatewayUrl: string;\n /** The Supabase anon/publishable key of the gateway project. */\n anonKey: string;\n /**\n * Optional: a pre-constructed client instance.\n * If provided, gatewayUrl and anonKey are ignored.\n */\n client?: SemanticLayerClient;\n children: React.ReactNode;\n}\n\nexport function SemanticLayerProvider({\n gatewayUrl,\n anonKey,\n client: externalClient,\n children,\n}: SemanticLayerProviderProps) {\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n return new SemanticLayerClient({ gatewayUrl, anonKey });\n }, [gatewayUrl, anonKey, externalClient]);\n\n const [auth, setAuth] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n error: null,\n });\n\n useEffect(() => {\n let mounted = true;\n\n async function initAuth() {\n try {\n const session = await client.getSession();\n if (!mounted) return;\n\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n } catch (err) {\n if (!mounted) return;\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: err instanceof Error ? err.message : \"Auth initialization failed\",\n });\n }\n }\n\n initAuth();\n\n const { data: { subscription } } = client.onAuthStateChange((_event, session) => {\n if (!mounted) return;\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n });\n\n return () => {\n mounted = false;\n subscription.unsubscribe();\n };\n }, [client]);\n\n const value = useMemo(() => ({ client, auth }), [client, auth]);\n\n return (\n <SemanticLayerContext.Provider value={value}>\n {children}\n </SemanticLayerContext.Provider>\n );\n}\n","import React, { useCallback, useContext, useEffect } from \"react\";\nimport { useAuth } from \"./hooks\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface AuthGateProps {\n children: React.ReactNode;\n /** Custom loading component. */\n loading?: React.ReactNode;\n /** Custom sign-in component. Receives a signIn callback. */\n signInComponent?: (props: { signIn: () => void }) => React.ReactNode;\n}\n\nconst defaultLoadingStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n color: \"#6b7280\",\n};\n\nconst defaultContainerStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n gap: \"16px\",\n};\n\nconst defaultButtonStyle: React.CSSProperties = {\n padding: \"12px 24px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#4285f4\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n};\n\nfunction isInIframe(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top;\n } catch {\n return true;\n }\n}\n\n/**\n * Wraps children and only renders them when the user is authenticated.\n * Shows a sign-in screen when unauthenticated.\n * When running inside an iframe (e.g. Lovable preview), uses a popup\n * for OAuth so the editor isn't navigated away.\n */\nexport function AuthGate({ children, loading, signInComponent }: AuthGateProps) {\n const { isAuthenticated, isLoading, error, signIn } = useAuth();\n const ctx = useContext(SemanticLayerContext);\n const client = ctx?.client;\n const inIframe = isInIframe();\n\n // Listen for auth tokens relayed from the popup via postMessage\n useEffect(() => {\n if (!inIframe || !client) return;\n\n const handler = (event: MessageEvent) => {\n if (event.data?.type === \"semantic-layer-auth-callback\" && event.data.access_token) {\n client.getSupabaseClient().auth.setSession({\n access_token: event.data.access_token,\n refresh_token: event.data.refresh_token,\n });\n }\n };\n\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [inIframe, client]);\n\n const handleSignIn = useCallback(async () => {\n if (inIframe && client) {\n const callbackUrl = `${client.gatewayUrl}/functions/v1/auth-callback`;\n const url = await client.getSignInUrl(callbackUrl);\n if (url) {\n window.open(url, \"semantic-layer-auth\", \"popup,width=600,height=700\");\n }\n } else {\n signIn(window.location.origin);\n }\n }, [inIframe, client, signIn]);\n\n if (isLoading) {\n return <>{loading || <div style={defaultLoadingStyle}>Loading...</div>}</>;\n }\n\n if (!isAuthenticated) {\n if (signInComponent) {\n return <>{signInComponent({ signIn: handleSignIn })}</>;\n }\n\n return (\n <div style={defaultContainerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Use your inKind Google account to access data.\n </p>\n {error && (\n <p style={{ margin: 0, color: \"#ef4444\", fontSize: \"14px\" }}>{error}</p>\n )}\n <button style={defaultButtonStyle} onClick={handleSignIn}>\n Sign in with Google\n </button>\n </div>\n );\n }\n\n return <>{children}</>;\n}\n"]}
1
+ {"version":3,"sources":["../src/react/provider.tsx","../src/react/auth-gate.tsx"],"names":["useMemo","SemanticLayerClient","useState","useEffect","jsx","SemanticLayerContext","useAuth","useCallback","jsxs","Fragment"],"mappings":"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","file":"react.cjs","sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { SemanticLayerClient } from \"../client\";\nimport type { SemanticLayerConfig, AuthState } from \"../types\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface SemanticLayerProviderProps {\n /** The Supabase URL of the gateway project. */\n gatewayUrl: string;\n /** The Supabase anon/publishable key of the gateway project. */\n anonKey: string;\n /**\n * Optional: restrict sign-in to emails matching this domain (e.g. \"inkind.com\").\n * Used for client-side validation in the OTP sign-in form.\n */\n emailDomain?: string;\n /**\n * Optional: a pre-constructed client instance.\n * If provided, gatewayUrl and anonKey are ignored.\n */\n client?: SemanticLayerClient;\n children: React.ReactNode;\n}\n\nexport function SemanticLayerProvider({\n gatewayUrl,\n anonKey,\n emailDomain,\n client: externalClient,\n children,\n}: SemanticLayerProviderProps) {\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n return new SemanticLayerClient({ gatewayUrl, anonKey });\n }, [gatewayUrl, anonKey, externalClient]);\n\n const [auth, setAuth] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n error: null,\n });\n\n useEffect(() => {\n let mounted = true;\n\n async function initAuth() {\n try {\n const session = await client.getSession();\n if (!mounted) return;\n\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n } catch (err) {\n if (!mounted) return;\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: err instanceof Error ? err.message : \"Auth initialization failed\",\n });\n }\n }\n\n initAuth();\n\n const { data: { subscription } } = client.onAuthStateChange((_event, session) => {\n if (!mounted) return;\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n });\n\n return () => {\n mounted = false;\n subscription.unsubscribe();\n };\n }, [client]);\n\n const value = useMemo(() => ({ client, auth, emailDomain }), [client, auth, emailDomain]);\n\n return (\n <SemanticLayerContext.Provider value={value}>\n {children}\n </SemanticLayerContext.Provider>\n );\n}\n","import React, { useCallback, useState } from \"react\";\nimport { useAuth } from \"./hooks\";\n\nexport interface AuthGateProps {\n children: React.ReactNode;\n /** Custom loading component. */\n loading?: React.ReactNode;\n /** Custom sign-in component. Receives a signIn callback. */\n signInComponent?: (props: { signIn: () => void }) => React.ReactNode;\n /** Force email OTP sign-in instead of Google OAuth (recommended for Lovable editor). */\n useEmailOtp?: boolean;\n}\n\nconst containerStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n gap: \"16px\",\n};\n\nconst loadingStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n color: \"#6b7280\",\n};\n\nconst buttonStyle: React.CSSProperties = {\n padding: \"12px 24px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#4285f4\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n};\n\nconst inputStyle: React.CSSProperties = {\n padding: \"10px 14px\",\n fontSize: \"16px\",\n border: \"1px solid #d1d5db\",\n borderRadius: \"8px\",\n width: \"280px\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n};\n\nconst errorStyle: React.CSSProperties = {\n margin: 0,\n color: \"#ef4444\",\n fontSize: \"14px\",\n};\n\nconst linkStyle: React.CSSProperties = {\n background: \"none\",\n border: \"none\",\n color: \"#4285f4\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n padding: 0,\n textDecoration: \"underline\",\n};\n\nfunction isInIframe(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top;\n } catch {\n return true;\n }\n}\n\n/**\n * Email OTP sign-in form for use inside iframes (Lovable editor preview).\n * Two-step: enter email → enter code from inbox.\n */\nfunction OtpSignIn() {\n const { sendOtp, verifyOtp, emailDomain } = useAuth();\n const [email, setEmail] = useState(\"\");\n const [code, setCode] = useState(\"\");\n const [step, setStep] = useState<\"email\" | \"code\">(\"email\");\n const [sending, setSending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleSendCode = useCallback(async () => {\n setError(null);\n const trimmed = email.trim().toLowerCase();\n if (!trimmed) {\n setError(\"Please enter your email.\");\n return;\n }\n if (emailDomain && !trimmed.endsWith(`@${emailDomain}`)) {\n setError(`Please use your @${emailDomain} email.`);\n return;\n }\n setSending(true);\n try {\n const { error: otpError } = await sendOtp(trimmed);\n if (otpError) {\n setError(otpError.message);\n } else {\n setStep(\"code\");\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to send code\");\n } finally {\n setSending(false);\n }\n }, [email, emailDomain, sendOtp]);\n\n const handleVerifyCode = useCallback(async () => {\n setError(null);\n const trimmedCode = code.trim();\n if (!trimmedCode) {\n setError(\"Please enter the code from your email.\");\n return;\n }\n setSending(true);\n try {\n const { error: verifyError } = await verifyOtp(email.trim().toLowerCase(), trimmedCode);\n if (verifyError) {\n setError(verifyError.message);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Verification failed\");\n } finally {\n setSending(false);\n }\n }, [email, code, verifyOtp]);\n\n if (step === \"code\") {\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Check your email</h2>\n <p style={{ margin: 0, color: \"#6b7280\", textAlign: \"center\", maxWidth: \"320px\" }}>\n We sent a sign-in code to <strong>{email.trim()}</strong>\n </p>\n <input\n style={inputStyle}\n type=\"text\"\n inputMode=\"numeric\"\n autoComplete=\"one-time-code\"\n placeholder=\"Enter 6-digit code\"\n value={code}\n onChange={(e) => setCode(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleVerifyCode()}\n />\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={handleVerifyCode} disabled={sending}>\n {sending ? \"Verifying...\" : \"Verify code\"}\n </button>\n <button style={linkStyle} onClick={() => { setStep(\"email\"); setCode(\"\"); setError(null); }}>\n Use a different email\n </button>\n </div>\n );\n }\n\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Enter your {emailDomain ? `@${emailDomain} ` : \"\"}email to receive a sign-in code.\n </p>\n <input\n style={inputStyle}\n type=\"email\"\n placeholder={emailDomain ? `you@${emailDomain}` : \"you@company.com\"}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleSendCode()}\n />\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={handleSendCode} disabled={sending}>\n {sending ? \"Sending...\" : \"Send sign-in code\"}\n </button>\n </div>\n );\n}\n\n/**\n * Wraps children and only renders them when the user is authenticated.\n * In iframes (e.g. Lovable editor preview), shows an email OTP form.\n * In standalone tabs, shows the Google OAuth sign-in button.\n */\nexport function AuthGate({ children, loading, signInComponent, useEmailOtp }: AuthGateProps) {\n const { isAuthenticated, isLoading, error, signIn } = useAuth();\n const inIframe = isInIframe();\n const shouldUseOtp = useEmailOtp || inIframe;\n\n if (isLoading) {\n return <>{loading || <div style={loadingStyle}>Loading...</div>}</>;\n }\n\n if (!isAuthenticated) {\n if (shouldUseOtp) {\n return <OtpSignIn />;\n }\n\n if (signInComponent) {\n return <>{signInComponent({ signIn: () => signIn(window.location.origin) })}</>;\n }\n\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Use your Google account to access data.\n </p>\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={() => signIn(window.location.origin)}>\n Sign in with Google\n </button>\n </div>\n );\n }\n\n return <>{children}</>;\n}\n"]}
package/dist/react.d.cts CHANGED
@@ -11,6 +11,11 @@ interface SemanticLayerProviderProps {
11
11
  gatewayUrl: string;
12
12
  /** The Supabase anon/publishable key of the gateway project. */
13
13
  anonKey: string;
14
+ /**
15
+ * Optional: restrict sign-in to emails matching this domain (e.g. "inkind.com").
16
+ * Used for client-side validation in the OTP sign-in form.
17
+ */
18
+ emailDomain?: string;
14
19
  /**
15
20
  * Optional: a pre-constructed client instance.
16
21
  * If provided, gatewayUrl and anonKey are ignored.
@@ -18,7 +23,7 @@ interface SemanticLayerProviderProps {
18
23
  client?: SemanticLayerClient;
19
24
  children: React__default.ReactNode;
20
25
  }
21
- declare function SemanticLayerProvider({ gatewayUrl, anonKey, client: externalClient, children, }: SemanticLayerProviderProps): react_jsx_runtime.JSX.Element;
26
+ declare function SemanticLayerProvider({ gatewayUrl, anonKey, emailDomain, client: externalClient, children, }: SemanticLayerProviderProps): react_jsx_runtime.JSX.Element;
22
27
 
23
28
  interface AuthGateProps {
24
29
  children: React__default.ReactNode;
@@ -28,21 +33,25 @@ interface AuthGateProps {
28
33
  signInComponent?: (props: {
29
34
  signIn: () => void;
30
35
  }) => React__default.ReactNode;
36
+ /** Force email OTP sign-in instead of Google OAuth (recommended for Lovable editor). */
37
+ useEmailOtp?: boolean;
31
38
  }
32
39
  /**
33
40
  * Wraps children and only renders them when the user is authenticated.
34
- * Shows a sign-in screen when unauthenticated.
35
- * When running inside an iframe (e.g. Lovable preview), uses a popup
36
- * for OAuth so the editor isn't navigated away.
41
+ * In iframes (e.g. Lovable editor preview), shows an email OTP form.
42
+ * In standalone tabs, shows the Google OAuth sign-in button.
37
43
  */
38
- declare function AuthGate({ children, loading, signInComponent }: AuthGateProps): react_jsx_runtime.JSX.Element;
44
+ declare function AuthGate({ children, loading, signInComponent, useEmailOtp }: AuthGateProps): react_jsx_runtime.JSX.Element;
39
45
 
40
46
  /** Returns the current auth state and sign-in/sign-out methods. */
41
47
  declare function useAuth(): {
42
48
  signIn: (redirectTo?: string) => Promise<_supabase_auth_js.OAuthResponse>;
49
+ sendOtp: (email: string) => Promise<_supabase_auth_js.AuthOtpResponse>;
50
+ verifyOtp: (email: string, token: string) => Promise<_supabase_auth_js.AuthResponse>;
43
51
  signOut: () => Promise<{
44
52
  error: _supabase_auth_js.AuthError | null;
45
53
  }>;
54
+ emailDomain: string | undefined;
46
55
  isAuthenticated: boolean;
47
56
  isLoading: boolean;
48
57
  user: {
@@ -86,6 +95,7 @@ declare function usePivotQuery(config: PivotConfig | null, options?: UseSemantic
86
95
  interface SemanticLayerContextValue {
87
96
  client: SemanticLayerClient;
88
97
  auth: AuthState;
98
+ emailDomain?: string;
89
99
  }
90
100
  declare const SemanticLayerContext: React.Context<SemanticLayerContextValue | null>;
91
101
 
package/dist/react.d.ts CHANGED
@@ -11,6 +11,11 @@ interface SemanticLayerProviderProps {
11
11
  gatewayUrl: string;
12
12
  /** The Supabase anon/publishable key of the gateway project. */
13
13
  anonKey: string;
14
+ /**
15
+ * Optional: restrict sign-in to emails matching this domain (e.g. "inkind.com").
16
+ * Used for client-side validation in the OTP sign-in form.
17
+ */
18
+ emailDomain?: string;
14
19
  /**
15
20
  * Optional: a pre-constructed client instance.
16
21
  * If provided, gatewayUrl and anonKey are ignored.
@@ -18,7 +23,7 @@ interface SemanticLayerProviderProps {
18
23
  client?: SemanticLayerClient;
19
24
  children: React__default.ReactNode;
20
25
  }
21
- declare function SemanticLayerProvider({ gatewayUrl, anonKey, client: externalClient, children, }: SemanticLayerProviderProps): react_jsx_runtime.JSX.Element;
26
+ declare function SemanticLayerProvider({ gatewayUrl, anonKey, emailDomain, client: externalClient, children, }: SemanticLayerProviderProps): react_jsx_runtime.JSX.Element;
22
27
 
23
28
  interface AuthGateProps {
24
29
  children: React__default.ReactNode;
@@ -28,21 +33,25 @@ interface AuthGateProps {
28
33
  signInComponent?: (props: {
29
34
  signIn: () => void;
30
35
  }) => React__default.ReactNode;
36
+ /** Force email OTP sign-in instead of Google OAuth (recommended for Lovable editor). */
37
+ useEmailOtp?: boolean;
31
38
  }
32
39
  /**
33
40
  * Wraps children and only renders them when the user is authenticated.
34
- * Shows a sign-in screen when unauthenticated.
35
- * When running inside an iframe (e.g. Lovable preview), uses a popup
36
- * for OAuth so the editor isn't navigated away.
41
+ * In iframes (e.g. Lovable editor preview), shows an email OTP form.
42
+ * In standalone tabs, shows the Google OAuth sign-in button.
37
43
  */
38
- declare function AuthGate({ children, loading, signInComponent }: AuthGateProps): react_jsx_runtime.JSX.Element;
44
+ declare function AuthGate({ children, loading, signInComponent, useEmailOtp }: AuthGateProps): react_jsx_runtime.JSX.Element;
39
45
 
40
46
  /** Returns the current auth state and sign-in/sign-out methods. */
41
47
  declare function useAuth(): {
42
48
  signIn: (redirectTo?: string) => Promise<_supabase_auth_js.OAuthResponse>;
49
+ sendOtp: (email: string) => Promise<_supabase_auth_js.AuthOtpResponse>;
50
+ verifyOtp: (email: string, token: string) => Promise<_supabase_auth_js.AuthResponse>;
43
51
  signOut: () => Promise<{
44
52
  error: _supabase_auth_js.AuthError | null;
45
53
  }>;
54
+ emailDomain: string | undefined;
46
55
  isAuthenticated: boolean;
47
56
  isLoading: boolean;
48
57
  user: {
@@ -86,6 +95,7 @@ declare function usePivotQuery(config: PivotConfig | null, options?: UseSemantic
86
95
  interface SemanticLayerContextValue {
87
96
  client: SemanticLayerClient;
88
97
  auth: AuthState;
98
+ emailDomain?: string;
89
99
  }
90
100
  declare const SemanticLayerContext: React.Context<SemanticLayerContextValue | null>;
91
101
 
package/dist/react.js CHANGED
@@ -1,12 +1,13 @@
1
- import { SemanticLayerClient } from './chunk-DHFL2XZB.js';
2
- import { SemanticLayerContext, useAuth } from './chunk-NJ4IJBV3.js';
3
- export { SemanticLayerContext, useAuth, useMetrics, usePivotQuery, useSemanticQuery } from './chunk-NJ4IJBV3.js';
4
- import { useMemo, useState, useEffect, useContext, useCallback } from 'react';
1
+ import { SemanticLayerClient } from './chunk-P72N6ISJ.js';
2
+ import { SemanticLayerContext, useAuth } from './chunk-RGVYFSW2.js';
3
+ export { SemanticLayerContext, useAuth, useMetrics, usePivotQuery, useSemanticQuery } from './chunk-RGVYFSW2.js';
4
+ import { useMemo, useState, useEffect, useCallback } from 'react';
5
5
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
6
6
 
7
7
  function SemanticLayerProvider({
8
8
  gatewayUrl,
9
9
  anonKey,
10
+ emailDomain,
10
11
  client: externalClient,
11
12
  children
12
13
  }) {
@@ -75,27 +76,27 @@ function SemanticLayerProvider({
75
76
  subscription.unsubscribe();
76
77
  };
77
78
  }, [client]);
78
- const value = useMemo(() => ({ client, auth }), [client, auth]);
79
+ const value = useMemo(() => ({ client, auth, emailDomain }), [client, auth, emailDomain]);
79
80
  return /* @__PURE__ */ jsx(SemanticLayerContext.Provider, { value, children });
80
81
  }
81
- var defaultLoadingStyle = {
82
+ var containerStyle = {
82
83
  display: "flex",
84
+ flexDirection: "column",
83
85
  alignItems: "center",
84
86
  justifyContent: "center",
85
87
  minHeight: "100vh",
86
88
  fontFamily: "system-ui, -apple-system, sans-serif",
87
- color: "#6b7280"
89
+ gap: "16px"
88
90
  };
89
- var defaultContainerStyle = {
91
+ var loadingStyle = {
90
92
  display: "flex",
91
- flexDirection: "column",
92
93
  alignItems: "center",
93
94
  justifyContent: "center",
94
95
  minHeight: "100vh",
95
96
  fontFamily: "system-ui, -apple-system, sans-serif",
96
- gap: "16px"
97
+ color: "#6b7280"
97
98
  };
98
- var defaultButtonStyle = {
99
+ var buttonStyle = {
99
100
  padding: "12px 24px",
100
101
  fontSize: "16px",
101
102
  fontWeight: 500,
@@ -108,6 +109,28 @@ var defaultButtonStyle = {
108
109
  alignItems: "center",
109
110
  gap: "8px"
110
111
  };
112
+ var inputStyle = {
113
+ padding: "10px 14px",
114
+ fontSize: "16px",
115
+ border: "1px solid #d1d5db",
116
+ borderRadius: "8px",
117
+ width: "280px",
118
+ fontFamily: "system-ui, -apple-system, sans-serif"
119
+ };
120
+ var errorStyle = {
121
+ margin: 0,
122
+ color: "#ef4444",
123
+ fontSize: "14px"
124
+ };
125
+ var linkStyle = {
126
+ background: "none",
127
+ border: "none",
128
+ color: "#4285f4",
129
+ cursor: "pointer",
130
+ fontSize: "14px",
131
+ padding: 0,
132
+ textDecoration: "underline"
133
+ };
111
134
  function isInIframe() {
112
135
  try {
113
136
  return typeof window !== "undefined" && window.self !== window.top;
@@ -115,47 +138,127 @@ function isInIframe() {
115
138
  return true;
116
139
  }
117
140
  }
118
- function AuthGate({ children, loading, signInComponent }) {
119
- const { isAuthenticated, isLoading, error, signIn } = useAuth();
120
- const ctx = useContext(SemanticLayerContext);
121
- const client = ctx?.client;
122
- const inIframe = isInIframe();
123
- useEffect(() => {
124
- if (!inIframe || !client) return;
125
- const handler = (event) => {
126
- if (event.data?.type === "semantic-layer-auth-callback" && event.data.access_token) {
127
- client.getSupabaseClient().auth.setSession({
128
- access_token: event.data.access_token,
129
- refresh_token: event.data.refresh_token
130
- });
141
+ function OtpSignIn() {
142
+ const { sendOtp, verifyOtp, emailDomain } = useAuth();
143
+ const [email, setEmail] = useState("");
144
+ const [code, setCode] = useState("");
145
+ const [step, setStep] = useState("email");
146
+ const [sending, setSending] = useState(false);
147
+ const [error, setError] = useState(null);
148
+ const handleSendCode = useCallback(async () => {
149
+ setError(null);
150
+ const trimmed = email.trim().toLowerCase();
151
+ if (!trimmed) {
152
+ setError("Please enter your email.");
153
+ return;
154
+ }
155
+ if (emailDomain && !trimmed.endsWith(`@${emailDomain}`)) {
156
+ setError(`Please use your @${emailDomain} email.`);
157
+ return;
158
+ }
159
+ setSending(true);
160
+ try {
161
+ const { error: otpError } = await sendOtp(trimmed);
162
+ if (otpError) {
163
+ setError(otpError.message);
164
+ } else {
165
+ setStep("code");
131
166
  }
132
- };
133
- window.addEventListener("message", handler);
134
- return () => window.removeEventListener("message", handler);
135
- }, [inIframe, client]);
136
- const handleSignIn = useCallback(async () => {
137
- if (inIframe && client) {
138
- const callbackUrl = `${client.gatewayUrl}/functions/v1/auth-callback`;
139
- const url = await client.getSignInUrl(callbackUrl);
140
- if (url) {
141
- window.open(url, "semantic-layer-auth", "popup,width=600,height=700");
167
+ } catch (err) {
168
+ setError(err instanceof Error ? err.message : "Failed to send code");
169
+ } finally {
170
+ setSending(false);
171
+ }
172
+ }, [email, emailDomain, sendOtp]);
173
+ const handleVerifyCode = useCallback(async () => {
174
+ setError(null);
175
+ const trimmedCode = code.trim();
176
+ if (!trimmedCode) {
177
+ setError("Please enter the code from your email.");
178
+ return;
179
+ }
180
+ setSending(true);
181
+ try {
182
+ const { error: verifyError } = await verifyOtp(email.trim().toLowerCase(), trimmedCode);
183
+ if (verifyError) {
184
+ setError(verifyError.message);
142
185
  }
143
- } else {
144
- signIn(window.location.origin);
186
+ } catch (err) {
187
+ setError(err instanceof Error ? err.message : "Verification failed");
188
+ } finally {
189
+ setSending(false);
145
190
  }
146
- }, [inIframe, client, signIn]);
191
+ }, [email, code, verifyOtp]);
192
+ if (step === "code") {
193
+ return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
194
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Check your email" }),
195
+ /* @__PURE__ */ jsxs("p", { style: { margin: 0, color: "#6b7280", textAlign: "center", maxWidth: "320px" }, children: [
196
+ "We sent a sign-in code to ",
197
+ /* @__PURE__ */ jsx("strong", { children: email.trim() })
198
+ ] }),
199
+ /* @__PURE__ */ jsx(
200
+ "input",
201
+ {
202
+ style: inputStyle,
203
+ type: "text",
204
+ inputMode: "numeric",
205
+ autoComplete: "one-time-code",
206
+ placeholder: "Enter 6-digit code",
207
+ value: code,
208
+ onChange: (e) => setCode(e.target.value),
209
+ onKeyDown: (e) => e.key === "Enter" && handleVerifyCode()
210
+ }
211
+ ),
212
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle, children: error }),
213
+ /* @__PURE__ */ jsx("button", { style: buttonStyle, onClick: handleVerifyCode, disabled: sending, children: sending ? "Verifying..." : "Verify code" }),
214
+ /* @__PURE__ */ jsx("button", { style: linkStyle, onClick: () => {
215
+ setStep("email");
216
+ setCode("");
217
+ setError(null);
218
+ }, children: "Use a different email" })
219
+ ] });
220
+ }
221
+ return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
222
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Sign in to continue" }),
223
+ /* @__PURE__ */ jsxs("p", { style: { margin: 0, color: "#6b7280" }, children: [
224
+ "Enter your ",
225
+ emailDomain ? `@${emailDomain} ` : "",
226
+ "email to receive a sign-in code."
227
+ ] }),
228
+ /* @__PURE__ */ jsx(
229
+ "input",
230
+ {
231
+ style: inputStyle,
232
+ type: "email",
233
+ placeholder: emailDomain ? `you@${emailDomain}` : "you@company.com",
234
+ value: email,
235
+ onChange: (e) => setEmail(e.target.value),
236
+ onKeyDown: (e) => e.key === "Enter" && handleSendCode()
237
+ }
238
+ ),
239
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle, children: error }),
240
+ /* @__PURE__ */ jsx("button", { style: buttonStyle, onClick: handleSendCode, disabled: sending, children: sending ? "Sending..." : "Send sign-in code" })
241
+ ] });
242
+ }
243
+ function AuthGate({ children, loading, signInComponent, useEmailOtp }) {
244
+ const { isAuthenticated, isLoading, error, signIn } = useAuth();
245
+ const inIframe = isInIframe();
246
+ const shouldUseOtp = useEmailOtp || inIframe;
147
247
  if (isLoading) {
148
- return /* @__PURE__ */ jsx(Fragment, { children: loading || /* @__PURE__ */ jsx("div", { style: defaultLoadingStyle, children: "Loading..." }) });
248
+ return /* @__PURE__ */ jsx(Fragment, { children: loading || /* @__PURE__ */ jsx("div", { style: loadingStyle, children: "Loading..." }) });
149
249
  }
150
250
  if (!isAuthenticated) {
251
+ if (shouldUseOtp) {
252
+ return /* @__PURE__ */ jsx(OtpSignIn, {});
253
+ }
151
254
  if (signInComponent) {
152
- return /* @__PURE__ */ jsx(Fragment, { children: signInComponent({ signIn: handleSignIn }) });
255
+ return /* @__PURE__ */ jsx(Fragment, { children: signInComponent({ signIn: () => signIn(window.location.origin) }) });
153
256
  }
154
- return /* @__PURE__ */ jsxs("div", { style: defaultContainerStyle, children: [
257
+ return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
155
258
  /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "24px", color: "#111827" }, children: "Sign in to continue" }),
156
- /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "#6b7280" }, children: "Use your inKind Google account to access data." }),
157
- error && /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "#ef4444", fontSize: "14px" }, children: error }),
158
- /* @__PURE__ */ jsx("button", { style: defaultButtonStyle, onClick: handleSignIn, children: "Sign in with Google" })
259
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "#6b7280" }, children: "Use your Google account to access data." }),
260
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle, children: error }),
261
+ /* @__PURE__ */ jsx("button", { style: buttonStyle, onClick: () => signIn(window.location.origin), children: "Sign in with Google" })
159
262
  ] });
160
263
  }
161
264
  return /* @__PURE__ */ jsx(Fragment, { children });
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/provider.tsx","../src/react/auth-gate.tsx"],"names":["useEffect","jsx"],"mappings":"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","file":"react.js","sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { SemanticLayerClient } from \"../client\";\nimport type { SemanticLayerConfig, AuthState } from \"../types\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface SemanticLayerProviderProps {\n /** The Supabase URL of the gateway project. */\n gatewayUrl: string;\n /** The Supabase anon/publishable key of the gateway project. */\n anonKey: string;\n /**\n * Optional: a pre-constructed client instance.\n * If provided, gatewayUrl and anonKey are ignored.\n */\n client?: SemanticLayerClient;\n children: React.ReactNode;\n}\n\nexport function SemanticLayerProvider({\n gatewayUrl,\n anonKey,\n client: externalClient,\n children,\n}: SemanticLayerProviderProps) {\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n return new SemanticLayerClient({ gatewayUrl, anonKey });\n }, [gatewayUrl, anonKey, externalClient]);\n\n const [auth, setAuth] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n error: null,\n });\n\n useEffect(() => {\n let mounted = true;\n\n async function initAuth() {\n try {\n const session = await client.getSession();\n if (!mounted) return;\n\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n } catch (err) {\n if (!mounted) return;\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: err instanceof Error ? err.message : \"Auth initialization failed\",\n });\n }\n }\n\n initAuth();\n\n const { data: { subscription } } = client.onAuthStateChange((_event, session) => {\n if (!mounted) return;\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n });\n\n return () => {\n mounted = false;\n subscription.unsubscribe();\n };\n }, [client]);\n\n const value = useMemo(() => ({ client, auth }), [client, auth]);\n\n return (\n <SemanticLayerContext.Provider value={value}>\n {children}\n </SemanticLayerContext.Provider>\n );\n}\n","import React, { useCallback, useContext, useEffect } from \"react\";\nimport { useAuth } from \"./hooks\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface AuthGateProps {\n children: React.ReactNode;\n /** Custom loading component. */\n loading?: React.ReactNode;\n /** Custom sign-in component. Receives a signIn callback. */\n signInComponent?: (props: { signIn: () => void }) => React.ReactNode;\n}\n\nconst defaultLoadingStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n color: \"#6b7280\",\n};\n\nconst defaultContainerStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n gap: \"16px\",\n};\n\nconst defaultButtonStyle: React.CSSProperties = {\n padding: \"12px 24px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#4285f4\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n};\n\nfunction isInIframe(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top;\n } catch {\n return true;\n }\n}\n\n/**\n * Wraps children and only renders them when the user is authenticated.\n * Shows a sign-in screen when unauthenticated.\n * When running inside an iframe (e.g. Lovable preview), uses a popup\n * for OAuth so the editor isn't navigated away.\n */\nexport function AuthGate({ children, loading, signInComponent }: AuthGateProps) {\n const { isAuthenticated, isLoading, error, signIn } = useAuth();\n const ctx = useContext(SemanticLayerContext);\n const client = ctx?.client;\n const inIframe = isInIframe();\n\n // Listen for auth tokens relayed from the popup via postMessage\n useEffect(() => {\n if (!inIframe || !client) return;\n\n const handler = (event: MessageEvent) => {\n if (event.data?.type === \"semantic-layer-auth-callback\" && event.data.access_token) {\n client.getSupabaseClient().auth.setSession({\n access_token: event.data.access_token,\n refresh_token: event.data.refresh_token,\n });\n }\n };\n\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [inIframe, client]);\n\n const handleSignIn = useCallback(async () => {\n if (inIframe && client) {\n const callbackUrl = `${client.gatewayUrl}/functions/v1/auth-callback`;\n const url = await client.getSignInUrl(callbackUrl);\n if (url) {\n window.open(url, \"semantic-layer-auth\", \"popup,width=600,height=700\");\n }\n } else {\n signIn(window.location.origin);\n }\n }, [inIframe, client, signIn]);\n\n if (isLoading) {\n return <>{loading || <div style={defaultLoadingStyle}>Loading...</div>}</>;\n }\n\n if (!isAuthenticated) {\n if (signInComponent) {\n return <>{signInComponent({ signIn: handleSignIn })}</>;\n }\n\n return (\n <div style={defaultContainerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Use your inKind Google account to access data.\n </p>\n {error && (\n <p style={{ margin: 0, color: \"#ef4444\", fontSize: \"14px\" }}>{error}</p>\n )}\n <button style={defaultButtonStyle} onClick={handleSignIn}>\n Sign in with Google\n </button>\n </div>\n );\n }\n\n return <>{children}</>;\n}\n"]}
1
+ {"version":3,"sources":["../src/react/provider.tsx","../src/react/auth-gate.tsx"],"names":["useState","jsx"],"mappings":"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","file":"react.js","sourcesContent":["import React, { useEffect, useMemo, useState } from \"react\";\nimport { SemanticLayerClient } from \"../client\";\nimport type { SemanticLayerConfig, AuthState } from \"../types\";\nimport { SemanticLayerContext } from \"./context\";\n\nexport interface SemanticLayerProviderProps {\n /** The Supabase URL of the gateway project. */\n gatewayUrl: string;\n /** The Supabase anon/publishable key of the gateway project. */\n anonKey: string;\n /**\n * Optional: restrict sign-in to emails matching this domain (e.g. \"inkind.com\").\n * Used for client-side validation in the OTP sign-in form.\n */\n emailDomain?: string;\n /**\n * Optional: a pre-constructed client instance.\n * If provided, gatewayUrl and anonKey are ignored.\n */\n client?: SemanticLayerClient;\n children: React.ReactNode;\n}\n\nexport function SemanticLayerProvider({\n gatewayUrl,\n anonKey,\n emailDomain,\n client: externalClient,\n children,\n}: SemanticLayerProviderProps) {\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n return new SemanticLayerClient({ gatewayUrl, anonKey });\n }, [gatewayUrl, anonKey, externalClient]);\n\n const [auth, setAuth] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n error: null,\n });\n\n useEffect(() => {\n let mounted = true;\n\n async function initAuth() {\n try {\n const session = await client.getSession();\n if (!mounted) return;\n\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n } catch (err) {\n if (!mounted) return;\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: err instanceof Error ? err.message : \"Auth initialization failed\",\n });\n }\n }\n\n initAuth();\n\n const { data: { subscription } } = client.onAuthStateChange((_event, session) => {\n if (!mounted) return;\n if (session?.user) {\n setAuth({\n isAuthenticated: true,\n isLoading: false,\n user: { id: session.user.id, email: session.user.email || \"\" },\n error: null,\n });\n } else {\n setAuth({\n isAuthenticated: false,\n isLoading: false,\n user: null,\n error: null,\n });\n }\n });\n\n return () => {\n mounted = false;\n subscription.unsubscribe();\n };\n }, [client]);\n\n const value = useMemo(() => ({ client, auth, emailDomain }), [client, auth, emailDomain]);\n\n return (\n <SemanticLayerContext.Provider value={value}>\n {children}\n </SemanticLayerContext.Provider>\n );\n}\n","import React, { useCallback, useState } from \"react\";\nimport { useAuth } from \"./hooks\";\n\nexport interface AuthGateProps {\n children: React.ReactNode;\n /** Custom loading component. */\n loading?: React.ReactNode;\n /** Custom sign-in component. Receives a signIn callback. */\n signInComponent?: (props: { signIn: () => void }) => React.ReactNode;\n /** Force email OTP sign-in instead of Google OAuth (recommended for Lovable editor). */\n useEmailOtp?: boolean;\n}\n\nconst containerStyle: React.CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n gap: \"16px\",\n};\n\nconst loadingStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n color: \"#6b7280\",\n};\n\nconst buttonStyle: React.CSSProperties = {\n padding: \"12px 24px\",\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#ffffff\",\n backgroundColor: \"#4285f4\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n};\n\nconst inputStyle: React.CSSProperties = {\n padding: \"10px 14px\",\n fontSize: \"16px\",\n border: \"1px solid #d1d5db\",\n borderRadius: \"8px\",\n width: \"280px\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n};\n\nconst errorStyle: React.CSSProperties = {\n margin: 0,\n color: \"#ef4444\",\n fontSize: \"14px\",\n};\n\nconst linkStyle: React.CSSProperties = {\n background: \"none\",\n border: \"none\",\n color: \"#4285f4\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n padding: 0,\n textDecoration: \"underline\",\n};\n\nfunction isInIframe(): boolean {\n try {\n return typeof window !== \"undefined\" && window.self !== window.top;\n } catch {\n return true;\n }\n}\n\n/**\n * Email OTP sign-in form for use inside iframes (Lovable editor preview).\n * Two-step: enter email → enter code from inbox.\n */\nfunction OtpSignIn() {\n const { sendOtp, verifyOtp, emailDomain } = useAuth();\n const [email, setEmail] = useState(\"\");\n const [code, setCode] = useState(\"\");\n const [step, setStep] = useState<\"email\" | \"code\">(\"email\");\n const [sending, setSending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleSendCode = useCallback(async () => {\n setError(null);\n const trimmed = email.trim().toLowerCase();\n if (!trimmed) {\n setError(\"Please enter your email.\");\n return;\n }\n if (emailDomain && !trimmed.endsWith(`@${emailDomain}`)) {\n setError(`Please use your @${emailDomain} email.`);\n return;\n }\n setSending(true);\n try {\n const { error: otpError } = await sendOtp(trimmed);\n if (otpError) {\n setError(otpError.message);\n } else {\n setStep(\"code\");\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to send code\");\n } finally {\n setSending(false);\n }\n }, [email, emailDomain, sendOtp]);\n\n const handleVerifyCode = useCallback(async () => {\n setError(null);\n const trimmedCode = code.trim();\n if (!trimmedCode) {\n setError(\"Please enter the code from your email.\");\n return;\n }\n setSending(true);\n try {\n const { error: verifyError } = await verifyOtp(email.trim().toLowerCase(), trimmedCode);\n if (verifyError) {\n setError(verifyError.message);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Verification failed\");\n } finally {\n setSending(false);\n }\n }, [email, code, verifyOtp]);\n\n if (step === \"code\") {\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Check your email</h2>\n <p style={{ margin: 0, color: \"#6b7280\", textAlign: \"center\", maxWidth: \"320px\" }}>\n We sent a sign-in code to <strong>{email.trim()}</strong>\n </p>\n <input\n style={inputStyle}\n type=\"text\"\n inputMode=\"numeric\"\n autoComplete=\"one-time-code\"\n placeholder=\"Enter 6-digit code\"\n value={code}\n onChange={(e) => setCode(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleVerifyCode()}\n />\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={handleVerifyCode} disabled={sending}>\n {sending ? \"Verifying...\" : \"Verify code\"}\n </button>\n <button style={linkStyle} onClick={() => { setStep(\"email\"); setCode(\"\"); setError(null); }}>\n Use a different email\n </button>\n </div>\n );\n }\n\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Enter your {emailDomain ? `@${emailDomain} ` : \"\"}email to receive a sign-in code.\n </p>\n <input\n style={inputStyle}\n type=\"email\"\n placeholder={emailDomain ? `you@${emailDomain}` : \"you@company.com\"}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleSendCode()}\n />\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={handleSendCode} disabled={sending}>\n {sending ? \"Sending...\" : \"Send sign-in code\"}\n </button>\n </div>\n );\n}\n\n/**\n * Wraps children and only renders them when the user is authenticated.\n * In iframes (e.g. Lovable editor preview), shows an email OTP form.\n * In standalone tabs, shows the Google OAuth sign-in button.\n */\nexport function AuthGate({ children, loading, signInComponent, useEmailOtp }: AuthGateProps) {\n const { isAuthenticated, isLoading, error, signIn } = useAuth();\n const inIframe = isInIframe();\n const shouldUseOtp = useEmailOtp || inIframe;\n\n if (isLoading) {\n return <>{loading || <div style={loadingStyle}>Loading...</div>}</>;\n }\n\n if (!isAuthenticated) {\n if (shouldUseOtp) {\n return <OtpSignIn />;\n }\n\n if (signInComponent) {\n return <>{signInComponent({ signIn: () => signIn(window.location.origin) })}</>;\n }\n\n return (\n <div style={containerStyle}>\n <h2 style={{ margin: 0, fontSize: \"24px\", color: \"#111827\" }}>Sign in to continue</h2>\n <p style={{ margin: 0, color: \"#6b7280\" }}>\n Use your Google account to access data.\n </p>\n {error && <p style={errorStyle}>{error}</p>}\n <button style={buttonStyle} onClick={() => signIn(window.location.origin)}>\n Sign in with Google\n </button>\n </div>\n );\n }\n\n return <>{children}</>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkindcards/semantic-layer",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "SDK for connecting Lovable apps to the dbt Semantic Layer via a shared gateway",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":["createClient"],"mappings":"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","file":"chunk-B4AB5ZWB.cjs","sourcesContent":["import { createClient, SupabaseClient, Session } from \"@supabase/supabase-js\";\nimport type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n} from \"./types\";\n\nexport class SemanticLayerClient {\n private supabase: SupabaseClient;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n readonly gatewayUrl: string;\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n this.supabase = createClient(config.gatewayUrl, config.anonKey, {\n auth: {\n persistSession: true,\n autoRefreshToken: true,\n storageKey: \"semantic-layer-auth\",\n },\n });\n }\n\n /** Access the underlying Supabase client (for auth operations). */\n getSupabaseClient(): SupabaseClient {\n return this.supabase;\n }\n\n // ─── Auth ────────────────────────────────────────────────────────────────────\n\n async signInWithGoogle(redirectTo?: string) {\n return this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: { redirectTo },\n });\n }\n\n /** Get the Google sign-in URL without triggering a redirect (for popup flows). */\n async getSignInUrl(redirectTo?: string): Promise<string | null> {\n const { data, error } = await this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: {\n redirectTo,\n skipBrowserRedirect: true,\n },\n });\n if (error || !data.url) return null;\n return data.url;\n }\n\n async signOut() {\n return this.supabase.auth.signOut();\n }\n\n async getSession(): Promise<Session | null> {\n const { data } = await this.supabase.auth.getSession();\n return data.session;\n }\n\n onAuthStateChange(callback: (event: string, session: Session | null) => void) {\n return this.supabase.auth.onAuthStateChange(callback);\n }\n\n // ─── Metadata ────────────────────────────────────────────────────────────────\n\n /**\n * Fetch the curated catalog of metrics and dimensions from the gateway.\n * Results are cached for 5 minutes.\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, error } = await this.supabase.functions.invoke(\"dbt-metadata\");\n\n if (error) {\n throw new SemanticLayerError(`Failed to fetch metadata: ${error.message}`, \"METADATA_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"METADATA_ERROR\");\n }\n\n this.metadataCache = data as MetadataResponse;\n this.metadataCacheTime = now;\n return this.metadataCache;\n }\n\n /** Get only metrics from the catalog. */\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n /** Get only dimensions (including time dimensions) from the catalog. */\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 /** Find a field by name or id. */\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 /** Execute a query using the full PivotConfig format. */\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n\n const { data, error } = await this.supabase.functions.invoke(\"dbt-query\", {\n body: { config },\n });\n\n if (error) {\n throw new SemanticLayerError(`Query failed: ${error.message}`, \"QUERY_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"QUERY_ERROR\");\n }\n\n return data as QueryResult;\n }\n\n /**\n * Execute a query using the simplified input format.\n * Automatically resolves metric/dimension names to full field objects.\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\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"chunk-DHFL2XZB.js","sourcesContent":["import { createClient, SupabaseClient, Session } from \"@supabase/supabase-js\";\nimport type {\n SemanticLayerConfig,\n MetadataResponse,\n PivotConfig,\n QueryResult,\n SimpleQueryInput,\n SemanticField,\n} from \"./types\";\n\nexport class SemanticLayerClient {\n private supabase: SupabaseClient;\n private metadataCache: MetadataResponse | null = null;\n private metadataCacheTime = 0;\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n readonly gatewayUrl: string;\n\n constructor(config: SemanticLayerConfig) {\n this.gatewayUrl = config.gatewayUrl;\n this.supabase = createClient(config.gatewayUrl, config.anonKey, {\n auth: {\n persistSession: true,\n autoRefreshToken: true,\n storageKey: \"semantic-layer-auth\",\n },\n });\n }\n\n /** Access the underlying Supabase client (for auth operations). */\n getSupabaseClient(): SupabaseClient {\n return this.supabase;\n }\n\n // ─── Auth ────────────────────────────────────────────────────────────────────\n\n async signInWithGoogle(redirectTo?: string) {\n return this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: { redirectTo },\n });\n }\n\n /** Get the Google sign-in URL without triggering a redirect (for popup flows). */\n async getSignInUrl(redirectTo?: string): Promise<string | null> {\n const { data, error } = await this.supabase.auth.signInWithOAuth({\n provider: \"google\",\n options: {\n redirectTo,\n skipBrowserRedirect: true,\n },\n });\n if (error || !data.url) return null;\n return data.url;\n }\n\n async signOut() {\n return this.supabase.auth.signOut();\n }\n\n async getSession(): Promise<Session | null> {\n const { data } = await this.supabase.auth.getSession();\n return data.session;\n }\n\n onAuthStateChange(callback: (event: string, session: Session | null) => void) {\n return this.supabase.auth.onAuthStateChange(callback);\n }\n\n // ─── Metadata ────────────────────────────────────────────────────────────────\n\n /**\n * Fetch the curated catalog of metrics and dimensions from the gateway.\n * Results are cached for 5 minutes.\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, error } = await this.supabase.functions.invoke(\"dbt-metadata\");\n\n if (error) {\n throw new SemanticLayerError(`Failed to fetch metadata: ${error.message}`, \"METADATA_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"METADATA_ERROR\");\n }\n\n this.metadataCache = data as MetadataResponse;\n this.metadataCacheTime = now;\n return this.metadataCache;\n }\n\n /** Get only metrics from the catalog. */\n async getMetrics(): Promise<SemanticField[]> {\n const { fields } = await this.getMetadata();\n return fields.filter((f) => f.type === \"metric\");\n }\n\n /** Get only dimensions (including time dimensions) from the catalog. */\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 /** Find a field by name or id. */\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 /** Execute a query using the full PivotConfig format. */\n async query(config: PivotConfig): Promise<QueryResult> {\n if (config.values.length === 0) {\n return { columns: [], rows: [], totalRows: 0, executionTimeMs: 0 };\n }\n\n const { data, error } = await this.supabase.functions.invoke(\"dbt-query\", {\n body: { config },\n });\n\n if (error) {\n throw new SemanticLayerError(`Query failed: ${error.message}`, \"QUERY_ERROR\");\n }\n if (data?.error) {\n throw new SemanticLayerError(data.error, \"QUERY_ERROR\");\n }\n\n return data as QueryResult;\n }\n\n /**\n * Execute a query using the simplified input format.\n * Automatically resolves metric/dimension names to full field objects.\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\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/react/context.ts","../src/react/hooks.ts"],"names":[],"mappings":"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","file":"chunk-NJ4IJBV3.js","sourcesContent":["import { createContext } from \"react\";\nimport type { SemanticLayerClient } from \"../client\";\nimport type { AuthState } from \"../types\";\n\nexport interface SemanticLayerContextValue {\n client: SemanticLayerClient;\n auth: AuthState;\n}\n\nexport const SemanticLayerContext = createContext<SemanticLayerContextValue | null>(null);\n","import { useContext, useCallback, useEffect, useState, useRef } from \"react\";\nimport { SemanticLayerContext } from \"./context\";\nimport type {\n SemanticField,\n FieldCategory,\n QueryResult,\n SimpleQueryInput,\n PivotConfig,\n AuthState,\n} from \"../types\";\n\nfunction useSemanticLayer() {\n const ctx = useContext(SemanticLayerContext);\n if (!ctx) {\n throw new Error(\"useSemanticLayer hooks must be used within a <SemanticLayerProvider>\");\n }\n return ctx;\n}\n\n/** Returns the current auth state and sign-in/sign-out methods. */\nexport function useAuth() {\n const { client, auth } = useSemanticLayer();\n\n const signIn = useCallback(\n (redirectTo?: string) => client.signInWithGoogle(redirectTo),\n [client],\n );\n\n const signOut = useCallback(() => client.signOut(), [client]);\n\n return { ...auth, signIn, signOut };\n}\n\ninterface UseMetricsResult {\n fields: SemanticField[];\n metrics: SemanticField[];\n dimensions: SemanticField[];\n categories: FieldCategory[];\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/** Fetch the full curated catalog of metrics and dimensions. */\nexport function useMetrics(): UseMetricsResult {\n const { client, auth } = useSemanticLayer();\n const [fields, setFields] = useState<SemanticField[]>([]);\n const [categories, setCategories] = useState<FieldCategory[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n\n const fetch = useCallback(\n async (force = false) => {\n if (!auth.isAuthenticated) return;\n setIsLoading(true);\n setError(null);\n try {\n const data = await client.getMetadata(force);\n setFields(data.fields);\n setCategories(data.categories);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load metadata\");\n } finally {\n setIsLoading(false);\n }\n },\n [client, auth.isAuthenticated],\n );\n\n useEffect(() => {\n if (auth.isAuthenticated && !fetchedRef.current) {\n fetchedRef.current = true;\n fetch();\n }\n }, [auth.isAuthenticated, fetch]);\n\n const refetch = useCallback(() => fetch(true), [fetch]);\n\n return {\n fields,\n metrics: fields.filter((f) => f.type === \"metric\"),\n dimensions: fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\"),\n categories,\n isLoading,\n error,\n refetch,\n };\n}\n\ninterface UseSemanticQueryOptions {\n /** Set to false to prevent the query from running automatically. */\n enabled?: boolean;\n}\n\ninterface UseSemanticQueryResult {\n data: QueryResult | null;\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/**\n * Execute a query against the dbt Semantic Layer using the simple input format.\n * The query runs automatically when the input changes (unless enabled=false).\n */\nexport function useSemanticQuery(\n input: SimpleQueryInput | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const inputKey = JSON.stringify(input);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !input || !enabled) return;\n if (input.metrics.length === 0) {\n setData({ columns: [], rows: [], totalRows: 0, executionTimeMs: 0 });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.simpleQuery(input);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, inputKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n\n/**\n * Execute a query using the full PivotConfig format.\n * Use this for advanced use cases (column pivoting, custom aggregations).\n */\nexport function usePivotQuery(\n config: PivotConfig | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const configKey = JSON.stringify(config);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !config || !enabled) return;\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.query(config);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, configKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/react/context.ts","../src/react/hooks.ts"],"names":["createContext","useContext","useCallback","useState","useRef","useEffect"],"mappings":"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","file":"chunk-Y3A3T45C.cjs","sourcesContent":["import { createContext } from \"react\";\nimport type { SemanticLayerClient } from \"../client\";\nimport type { AuthState } from \"../types\";\n\nexport interface SemanticLayerContextValue {\n client: SemanticLayerClient;\n auth: AuthState;\n}\n\nexport const SemanticLayerContext = createContext<SemanticLayerContextValue | null>(null);\n","import { useContext, useCallback, useEffect, useState, useRef } from \"react\";\nimport { SemanticLayerContext } from \"./context\";\nimport type {\n SemanticField,\n FieldCategory,\n QueryResult,\n SimpleQueryInput,\n PivotConfig,\n AuthState,\n} from \"../types\";\n\nfunction useSemanticLayer() {\n const ctx = useContext(SemanticLayerContext);\n if (!ctx) {\n throw new Error(\"useSemanticLayer hooks must be used within a <SemanticLayerProvider>\");\n }\n return ctx;\n}\n\n/** Returns the current auth state and sign-in/sign-out methods. */\nexport function useAuth() {\n const { client, auth } = useSemanticLayer();\n\n const signIn = useCallback(\n (redirectTo?: string) => client.signInWithGoogle(redirectTo),\n [client],\n );\n\n const signOut = useCallback(() => client.signOut(), [client]);\n\n return { ...auth, signIn, signOut };\n}\n\ninterface UseMetricsResult {\n fields: SemanticField[];\n metrics: SemanticField[];\n dimensions: SemanticField[];\n categories: FieldCategory[];\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/** Fetch the full curated catalog of metrics and dimensions. */\nexport function useMetrics(): UseMetricsResult {\n const { client, auth } = useSemanticLayer();\n const [fields, setFields] = useState<SemanticField[]>([]);\n const [categories, setCategories] = useState<FieldCategory[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n\n const fetch = useCallback(\n async (force = false) => {\n if (!auth.isAuthenticated) return;\n setIsLoading(true);\n setError(null);\n try {\n const data = await client.getMetadata(force);\n setFields(data.fields);\n setCategories(data.categories);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load metadata\");\n } finally {\n setIsLoading(false);\n }\n },\n [client, auth.isAuthenticated],\n );\n\n useEffect(() => {\n if (auth.isAuthenticated && !fetchedRef.current) {\n fetchedRef.current = true;\n fetch();\n }\n }, [auth.isAuthenticated, fetch]);\n\n const refetch = useCallback(() => fetch(true), [fetch]);\n\n return {\n fields,\n metrics: fields.filter((f) => f.type === \"metric\"),\n dimensions: fields.filter((f) => f.type === \"dimension\" || f.type === \"time_dimension\"),\n categories,\n isLoading,\n error,\n refetch,\n };\n}\n\ninterface UseSemanticQueryOptions {\n /** Set to false to prevent the query from running automatically. */\n enabled?: boolean;\n}\n\ninterface UseSemanticQueryResult {\n data: QueryResult | null;\n isLoading: boolean;\n error: string | null;\n refetch: () => void;\n}\n\n/**\n * Execute a query against the dbt Semantic Layer using the simple input format.\n * The query runs automatically when the input changes (unless enabled=false).\n */\nexport function useSemanticQuery(\n input: SimpleQueryInput | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const inputKey = JSON.stringify(input);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !input || !enabled) return;\n if (input.metrics.length === 0) {\n setData({ columns: [], rows: [], totalRows: 0, executionTimeMs: 0 });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.simpleQuery(input);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, inputKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n\n/**\n * Execute a query using the full PivotConfig format.\n * Use this for advanced use cases (column pivoting, custom aggregations).\n */\nexport function usePivotQuery(\n config: PivotConfig | null,\n options: UseSemanticQueryOptions = {},\n): UseSemanticQueryResult {\n const { client, auth } = useSemanticLayer();\n const { enabled = true } = options;\n const [data, setData] = useState<QueryResult | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const configKey = JSON.stringify(config);\n\n const execute = useCallback(async () => {\n if (!auth.isAuthenticated || !config || !enabled) return;\n\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.query(config);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Query failed\");\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, auth.isAuthenticated, configKey, enabled]);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return { data, isLoading, error, refetch: execute };\n}\n"]}