@staticbot/base44-supabase-shim 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,17 +1,34 @@
1
- import {
2
- makeIntegrations
3
- } from "./chunk-PUROQAXO.js";
4
1
  import {
5
2
  defaultEntityToTable,
6
3
  makeEntitiesProxy,
4
+ makeFunctions,
7
5
  parseOrderBy,
8
6
  resolveEntityMapping
9
- } from "./chunk-SWURHLDN.js";
7
+ } from "./chunk-YQ3BDCIS.js";
8
+ import {
9
+ makeIntegrations
10
+ } from "./chunk-E2KG6ZL4.js";
10
11
 
11
12
  // src/index.ts
12
13
  import { createClient as createSupabase } from "@supabase/supabase-js";
13
14
 
15
+ // src/agents.ts
16
+ function makeAgents(opts = {}) {
17
+ return {
18
+ /**
19
+ * Returns a WhatsApp connect URL for the given agent, or null when not
20
+ * configured. Meant to be dropped straight into `<a href={...}>` — React
21
+ * omits the attribute when null so the anchor becomes inert instead of
22
+ * navigating to "null".
23
+ */
24
+ getWhatsAppConnectURL(agentName) {
25
+ return opts.whatsappUrls?.[agentName] ?? null;
26
+ }
27
+ };
28
+ }
29
+
14
30
  // src/auth.ts
31
+ var setTokenWarned = false;
15
32
  function makeAuth(client, opts = {}) {
16
33
  const loginPath = opts.loginPath ?? "/login";
17
34
  return {
@@ -20,6 +37,12 @@ function makeAuth(client, opts = {}) {
20
37
  if (error) throw error;
21
38
  return data;
22
39
  },
40
+ /** Base44 alias for signIn. */
41
+ async loginViaEmailPassword(email, password) {
42
+ const { data, error } = await client.auth.signInWithPassword({ email, password });
43
+ if (error) throw error;
44
+ return data;
45
+ },
23
46
  async signUp({ email, password, metadata }) {
24
47
  const { data, error } = await client.auth.signUp({
25
48
  email,
@@ -29,14 +52,99 @@ function makeAuth(client, opts = {}) {
29
52
  if (error) throw error;
30
53
  return data;
31
54
  },
55
+ /** Base44 alias for signUp. */
56
+ async register({ email, password, metadata }) {
57
+ const { data, error } = await client.auth.signUp({
58
+ email,
59
+ password,
60
+ options: { data: metadata ?? {} }
61
+ });
62
+ if (error) throw error;
63
+ return data;
64
+ },
65
+ /**
66
+ * Base44 OAuth flow: redirects the browser to the provider's consent screen
67
+ * and back to `returnPath` (relative to window.location.origin) on success.
68
+ * Supabase equivalent: signInWithOAuth with an absolute redirectTo.
69
+ */
70
+ async loginWithProvider(provider, returnPath) {
71
+ const redirectTo = typeof window !== "undefined" ? window.location.origin + (returnPath ?? "/") : returnPath;
72
+ const { data, error } = await client.auth.signInWithOAuth({
73
+ provider,
74
+ options: redirectTo ? { redirectTo } : void 0
75
+ });
76
+ if (error) throw error;
77
+ return data;
78
+ },
79
+ /**
80
+ * Base44 email OTP verification after register(). Supabase's verifyOtp
81
+ * already sets the session on success, so setToken() is redundant afterward
82
+ * (kept as a soft no-op for source-compat).
83
+ */
84
+ async verifyOtp({ email, otpCode }) {
85
+ const { data, error } = await client.auth.verifyOtp({
86
+ email,
87
+ token: otpCode,
88
+ type: "signup"
89
+ });
90
+ if (error) throw error;
91
+ return {
92
+ access_token: data.session?.access_token,
93
+ session: data.session,
94
+ user: data.user
95
+ };
96
+ },
97
+ async resendOtp(email) {
98
+ const { error } = await client.auth.resend({ email, type: "signup" });
99
+ if (error) throw error;
100
+ },
101
+ /**
102
+ * No-op alias kept so migrated code doesn't TypeError. Supabase's
103
+ * verifyOtp() already installed the session — pushing the access_token in
104
+ * again would do nothing productive (Supabase requires access + refresh to
105
+ * setSession, and Base44 returns only access). Warns once per process.
106
+ */
107
+ setToken(_accessToken) {
108
+ if (!setTokenWarned) {
109
+ setTokenWarned = true;
110
+ if (typeof console !== "undefined") {
111
+ console.warn(
112
+ "[base44-shim] auth.setToken() is a no-op \u2014 verifyOtp()/signInWithPassword() already installed the Supabase session. Safe to remove the call."
113
+ );
114
+ }
115
+ }
116
+ },
117
+ async resetPasswordRequest(email, options) {
118
+ const redirectTo = options?.redirectTo ?? opts.resetPasswordRedirect;
119
+ const { error } = await client.auth.resetPasswordForEmail(
120
+ email,
121
+ redirectTo ? { redirectTo } : void 0
122
+ );
123
+ if (error) throw error;
124
+ },
125
+ async resetPassword({ newPassword }) {
126
+ const { data, error } = await client.auth.updateUser({ password: newPassword });
127
+ if (error) throw error;
128
+ return data;
129
+ },
32
130
  async signOut() {
33
131
  const { error } = await client.auth.signOut();
34
132
  if (error) throw error;
35
133
  },
36
- /** Base44 alias for signOut. */
37
- async logout() {
134
+ /**
135
+ * Base44 alias for signOut. If `returnUrl` is provided, navigates there
136
+ * after signOut resolves so SPAs can drop users on a public route.
137
+ */
138
+ async logout(returnUrl) {
38
139
  const { error } = await client.auth.signOut();
39
140
  if (error) throw error;
141
+ if (returnUrl && typeof window !== "undefined") {
142
+ window.location.assign(returnUrl);
143
+ }
144
+ },
145
+ async isAuthenticated() {
146
+ const { data } = await client.auth.getSession();
147
+ return !!data.session;
40
148
  },
41
149
  async getUser() {
42
150
  const { data, error } = await client.auth.getUser();
@@ -86,30 +194,6 @@ function makeAuth(client, opts = {}) {
86
194
  };
87
195
  }
88
196
 
89
- // src/functions.ts
90
- function makeFunctions(client) {
91
- return {
92
- /** Invoke an edge function by name, passing JSON body. Returns parsed JSON. */
93
- async invoke(name, payload) {
94
- const { data, error } = await client.functions.invoke(name, {
95
- body: payload
96
- });
97
- if (error) throw error;
98
- return data;
99
- },
100
- /** Lower-level: invoke and return Response so caller can handle non-JSON. */
101
- async fetch(name, init) {
102
- const url = `${client.supabaseUrl}/functions/v1/${name}`;
103
- const headers = new Headers(init?.headers);
104
- const session = await client.auth.getSession();
105
- const token = session.data.session?.access_token;
106
- if (token) headers.set("Authorization", `Bearer ${token}`);
107
- headers.set("apikey", client.supabaseKey);
108
- return fetch(url, { ...init, headers });
109
- }
110
- };
111
- }
112
-
113
197
  // src/misc.ts
114
198
  function makeAppLogs(client, app2) {
115
199
  return {
@@ -237,6 +321,7 @@ function createClient(options) {
237
321
  appLogs: makeAppLogs(supabase, options.schemaPrefix),
238
322
  users: makeUsers(),
239
323
  app,
324
+ agents: makeAgents(options.agents),
240
325
  asServiceRole
241
326
  };
242
327
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/auth.ts","../src/functions.ts","../src/misc.ts","../src/storage.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeAuth, type AuthOptions } from './auth.js';\nimport { makeEntitiesProxy } from './entities.js';\nimport { makeFunctions } from './functions.js';\nimport { makeIntegrations, type IntegrationsOptions } from './integrations.js';\nimport { app, makeAppLogs, makeUsers } from './misc.js';\nimport { makeStorage } from './storage.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\nexport { defaultEntityToTable, resolveEntityMapping, parseOrderBy } from './entities.js';\n\nexport interface ExtendedClientOptions extends ClientOptions {\n /** Auth-related options (login redirect path, etc). */\n authOptions?: AuthOptions;\n /** Integration stub configuration (storage default bucket, edge function names). */\n integrations?: Partial<IntegrationsOptions>;\n}\n\nexport interface Base44Client {\n /** Underlying Supabase client (anon key). */\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n auth: ReturnType<typeof makeAuth>;\n functions: ReturnType<typeof makeFunctions>;\n storage: ReturnType<typeof makeStorage>;\n integrations: ReturnType<typeof makeIntegrations>;\n /** Per-page activity logger. Writes to core.audit_log; errors are swallowed. */\n appLogs: ReturnType<typeof makeAppLogs>;\n /** Admin user management; browser-side calls throw (use Studio instead). */\n users: ReturnType<typeof makeUsers>;\n /** Empty placeholder for base44.app property access. */\n app: Record<string, unknown>;\n /** Service-role-scoped namespace for trusted server contexts. Throws if no service key supplied. */\n asServiceRole: { entities: EntitiesProxy };\n}\n\n/** Create a Base44-compatible client backed by Supabase. */\nexport function createClient(options: ExtendedClientOptions): Base44Client {\n if (!options.supabaseUrl) throw new Error('createClient: supabaseUrl is required');\n if (!options.supabaseAnonKey) throw new Error('createClient: supabaseAnonKey is required');\n if (!options.schemaPrefix) throw new Error('createClient: schemaPrefix is required');\n\n const supabase =\n options.client ?? createSupabase(options.supabaseUrl, options.supabaseAnonKey);\n\n const entities = makeEntitiesProxy(supabase, {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n });\n\n const asServiceRole = (() => {\n let serviceClient: SupabaseClient | null = null;\n let serviceEntities: EntitiesProxy | null = null;\n return {\n get entities(): EntitiesProxy {\n if (!options.supabaseServiceRoleKey) {\n throw new Error(\n 'asServiceRole.entities accessed but supabaseServiceRoleKey was not provided. ' +\n 'Only set this in trusted server contexts (edge functions, scripts).',\n );\n }\n if (!serviceClient) {\n serviceClient = createSupabase(options.supabaseUrl, options.supabaseServiceRoleKey);\n }\n if (!serviceEntities) {\n serviceEntities = makeEntitiesProxy(serviceClient, {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n });\n }\n return serviceEntities;\n },\n };\n })();\n\n return {\n supabase,\n entities,\n auth: makeAuth(supabase, options.authOptions),\n functions: makeFunctions(supabase),\n storage: makeStorage(supabase, options.schemaPrefix),\n integrations: makeIntegrations(supabase, {\n defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,\n sendEmailFunction: options.integrations?.sendEmailFunction,\n invokeLlmFunction: options.integrations?.invokeLlmFunction,\n }),\n appLogs: makeAppLogs(supabase, options.schemaPrefix),\n users: makeUsers(),\n app,\n asServiceRole,\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\nexport interface SignInArgs {\n email: string;\n password: string;\n}\n\nexport interface SignUpArgs {\n email: string;\n password: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AuthOptions {\n /**\n * Browser path the redirectToLogin() shim should send users to.\n * Default: '/login'.\n */\n loginPath?: string;\n}\n\nexport function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {\n const loginPath = opts.loginPath ?? '/login';\n\n return {\n async signIn({ email, password }: SignInArgs) {\n const { data, error } = await client.auth.signInWithPassword({ email, password });\n if (error) throw error;\n return data;\n },\n async signUp({ email, password, metadata }: SignUpArgs) {\n const { data, error } = await client.auth.signUp({\n email,\n password,\n options: { data: metadata ?? {} },\n });\n if (error) throw error;\n return data;\n },\n async signOut() {\n const { error } = await client.auth.signOut();\n if (error) throw error;\n },\n /** Base44 alias for signOut. */\n async logout() {\n const { error } = await client.auth.signOut();\n if (error) throw error;\n },\n async getUser() {\n const { data, error } = await client.auth.getUser();\n if (error) throw error;\n return data.user;\n },\n /** Base44 alias for getUser. Returns the current user object or throws if not signed in. */\n async me() {\n const { data, error } = await client.auth.getUser();\n if (error) throw error;\n if (!data.user) throw new Error('Not authenticated');\n return data.user;\n },\n /**\n * Base44 alias for updating the current user's metadata. Accepts arbitrary\n * key/value pairs that get stored in `user_metadata`.\n */\n async updateMe(metadata: Record<string, unknown>) {\n const { data, error } = await client.auth.updateUser({ data: metadata });\n if (error) throw error;\n return data.user;\n },\n async getSession() {\n const { data, error } = await client.auth.getSession();\n if (error) throw error;\n return data.session;\n },\n /**\n * Base44 used to redirect SPA users to its hosted login page. Self-host\n * has no hosted login, so this just navigates to the configured local\n * loginPath. Override the path via createClient({ ..., authLoginPath: '/x' }).\n */\n redirectToLogin(returnUrl?: string) {\n if (typeof window === 'undefined') return;\n // Already on the login route → no-op. Prevents redirect loops when an\n // unauthenticated check on /login itself fires another redirectToLogin.\n if (window.location.pathname === loginPath) return;\n // Defensive: if the returnUrl already points back to a login page (cyclic\n // chain from old buggy state), drop it. Also drop if it's absurdly long.\n let safeReturn: string | undefined = returnUrl;\n if (safeReturn) {\n const looksCyclic = safeReturn.includes(`${loginPath}?next=`) || safeReturn.includes(`${loginPath}%3F`);\n if (looksCyclic || safeReturn.length > 1024) safeReturn = undefined;\n }\n const url = safeReturn\n ? `${loginPath}?next=${encodeURIComponent(safeReturn)}`\n : loginPath;\n window.location.assign(url);\n },\n onAuthStateChange(cb: Parameters<SupabaseClient['auth']['onAuthStateChange']>[0]) {\n return client.auth.onAuthStateChange(cb);\n },\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\n/** Mirror of base44.functions — Supabase Edge Functions invoke wrapper.\n *\n * Returns the raw body. On HTTP error, throws an Error with the response body attached.\n */\nexport function makeFunctions(client: SupabaseClient) {\n return {\n /** Invoke an edge function by name, passing JSON body. Returns parsed JSON. */\n async invoke<T = unknown>(name: string, payload?: Record<string, unknown>): Promise<T> {\n const { data, error } = await client.functions.invoke<T>(name, {\n body: payload,\n });\n if (error) throw error;\n return data as T;\n },\n /** Lower-level: invoke and return Response so caller can handle non-JSON. */\n async fetch(name: string, init?: RequestInit): Promise<Response> {\n const url = `${(client as unknown as { supabaseUrl: string }).supabaseUrl}/functions/v1/${name}`;\n const headers = new Headers(init?.headers);\n const session = await client.auth.getSession();\n const token = session.data.session?.access_token;\n if (token) headers.set('Authorization', `Bearer ${token}`);\n headers.set('apikey', (client as unknown as { supabaseKey: string }).supabaseKey);\n return fetch(url, { ...init, headers });\n },\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\n/**\n * Stub for `base44.appLogs` — Base44 cloud's per-page activity tracker.\n * Writes a row to core.audit_log if the table exists, otherwise silently\n * succeeds. App code wraps this in .catch(() => {}) anyway, so any failure\n * is non-fatal.\n */\nexport function makeAppLogs(client: SupabaseClient, app: string) {\n return {\n async logUserInApp(pageName: string): Promise<void> {\n try {\n await client.schema('core' as never).from('audit_logs').insert({\n app,\n action: 'page_view',\n module: pageName,\n });\n } catch {\n // best-effort; analytics errors must never break the app\n }\n },\n };\n}\n\n/**\n * Stub for `base44.users` — admin-only user management. Self-host equivalent\n * uses Supabase Auth admin API but requires a service_role key, which the\n * browser client doesn't have. So inviteUser here logs a warning and returns\n * a benign error so callers can show a \"not supported\" message.\n */\nexport function makeUsers() {\n return {\n async inviteUser(_args: { email: string; [key: string]: unknown }): Promise<never> {\n throw new Error(\n 'inviteUser is admin-only and not exposed to the browser shim. ' +\n 'Use the Studio dashboard or an edge function with service_role to invite users.',\n );\n },\n };\n}\n\n/** Empty placeholder for `base44.app` — kept defined so property access doesn't crash. */\nexport const app: Record<string, unknown> = {};\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\nexport interface UploadFileArgs {\n /** Supabase Storage bucket name. Defaults to schemaPrefix from client options. */\n bucket?: string;\n /** Object path within the bucket (e.g. 'invoices/2026/inv-001.pdf'). */\n path: string;\n /** File contents. */\n file: Blob | File | ArrayBuffer | Uint8Array;\n /** Content-Type. Inferred from File if omitted. */\n contentType?: string;\n /** Overwrite existing object at path. Default false. */\n upsert?: boolean;\n}\n\nexport function makeStorage(client: SupabaseClient, defaultBucket: string) {\n return {\n /** Upload a file to a bucket. Returns the public URL. */\n async uploadFile({\n bucket,\n path,\n file,\n contentType,\n upsert = false,\n }: UploadFileArgs): Promise<{ path: string; url: string }> {\n const b = bucket ?? defaultBucket;\n const { error } = await client.storage.from(b).upload(path, file, {\n contentType,\n upsert,\n });\n if (error) throw error;\n const { data } = client.storage.from(b).getPublicUrl(path);\n return { path, url: data.publicUrl };\n },\n /** Get a public URL for a stored object. */\n getPublicUrl(path: string, bucket?: string): string {\n const b = bucket ?? defaultBucket;\n const { data } = client.storage.from(b).getPublicUrl(path);\n return data.publicUrl;\n },\n /** Generate a time-limited signed URL for private buckets. */\n async createSignedUrl(path: string, expiresInSec = 3600, bucket?: string): Promise<string> {\n const b = bucket ?? defaultBucket;\n const { data, error } = await client.storage.from(b).createSignedUrl(path, expiresInSec);\n if (error) throw error;\n return data.signedUrl;\n },\n /** Delete one or more objects. */\n async remove(paths: string | string[], bucket?: string): Promise<void> {\n const b = bucket ?? defaultBucket;\n const list = Array.isArray(paths) ? paths : [paths];\n const { error } = await client.storage.from(b).remove(list);\n if (error) throw error;\n },\n /** List objects in a bucket prefix. */\n async list(prefix?: string, bucket?: string) {\n const b = bucket ?? defaultBucket;\n const { data, error } = await client.storage.from(b).list(prefix);\n if (error) throw error;\n return data ?? [];\n },\n };\n}\n"],"mappings":"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","names":["app"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/agents.ts","../src/auth.ts","../src/misc.ts","../src/storage.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeAgents, type AgentsOptions } from './agents.js';\nimport { makeAuth, type AuthOptions } from './auth.js';\nimport { makeEntitiesProxy } from './entities.js';\nimport { makeFunctions } from './functions.js';\nimport { makeIntegrations, type IntegrationsOptions } from './integrations.js';\nimport { app, makeAppLogs, makeUsers } from './misc.js';\nimport { makeStorage } from './storage.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\nexport type { AgentsOptions } from './agents.js';\nexport { defaultEntityToTable, resolveEntityMapping, parseOrderBy } from './entities.js';\n\nexport interface ExtendedClientOptions extends ClientOptions {\n /** Auth-related options (login redirect path, etc). */\n authOptions?: AuthOptions;\n /** Integration stub configuration (storage default bucket, edge function names). */\n integrations?: Partial<IntegrationsOptions>;\n /** Agents stub configuration (per-agent WhatsApp connect URLs, etc.). */\n agents?: AgentsOptions;\n}\n\nexport interface Base44Client {\n /** Underlying Supabase client (anon key). */\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n auth: ReturnType<typeof makeAuth>;\n functions: ReturnType<typeof makeFunctions>;\n storage: ReturnType<typeof makeStorage>;\n integrations: ReturnType<typeof makeIntegrations>;\n /** Per-page activity logger. Writes to core.audit_log; errors are swallowed. */\n appLogs: ReturnType<typeof makeAppLogs>;\n /** Admin user management; browser-side calls throw (use Studio instead). */\n users: ReturnType<typeof makeUsers>;\n /** Empty placeholder for base44.app property access. */\n app: Record<string, unknown>;\n /** Base44 agents stub — WhatsApp/Telegram bridges disabled by default. */\n agents: ReturnType<typeof makeAgents>;\n /** Service-role-scoped namespace for trusted server contexts. Throws if no service key supplied. */\n asServiceRole: { entities: EntitiesProxy };\n}\n\n/** Create a Base44-compatible client backed by Supabase. */\nexport function createClient(options: ExtendedClientOptions): Base44Client {\n if (!options.supabaseUrl) throw new Error('createClient: supabaseUrl is required');\n if (!options.supabaseAnonKey) throw new Error('createClient: supabaseAnonKey is required');\n if (!options.schemaPrefix) throw new Error('createClient: schemaPrefix is required');\n\n const supabase =\n options.client ?? createSupabase(options.supabaseUrl, options.supabaseAnonKey);\n\n const entities = makeEntitiesProxy(supabase, {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n });\n\n const asServiceRole = (() => {\n let serviceClient: SupabaseClient | null = null;\n let serviceEntities: EntitiesProxy | null = null;\n return {\n get entities(): EntitiesProxy {\n if (!options.supabaseServiceRoleKey) {\n throw new Error(\n 'asServiceRole.entities accessed but supabaseServiceRoleKey was not provided. ' +\n 'Only set this in trusted server contexts (edge functions, scripts).',\n );\n }\n if (!serviceClient) {\n serviceClient = createSupabase(options.supabaseUrl, options.supabaseServiceRoleKey);\n }\n if (!serviceEntities) {\n serviceEntities = makeEntitiesProxy(serviceClient, {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n });\n }\n return serviceEntities;\n },\n };\n })();\n\n return {\n supabase,\n entities,\n auth: makeAuth(supabase, options.authOptions),\n functions: makeFunctions(supabase),\n storage: makeStorage(supabase, options.schemaPrefix),\n integrations: makeIntegrations(supabase, {\n defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,\n sendEmailFunction: options.integrations?.sendEmailFunction,\n invokeLlmFunction: options.integrations?.invokeLlmFunction,\n }),\n appLogs: makeAppLogs(supabase, options.schemaPrefix),\n users: makeUsers(),\n app,\n agents: makeAgents(options.agents),\n asServiceRole,\n };\n}\n","/**\n * Stub of `base44.agents.*`. Base44 hosts an \"agents\" concept with WhatsApp/\n * Telegram bridges that don't exist in self-host by default — this module\n * exists so migrated apps referencing `base44.agents.getWhatsAppConnectURL(...)`\n * don't `TypeError` at runtime. Default behavior returns null so <a href={...}>\n * usages render as an unclickable button (feature visibly disabled).\n *\n * If a customer wires their own WhatsApp gateway, pass per-agent URLs via\n * createClient({ agents: { whatsappUrls: { SubdomainReviewer: 'https://…' } } }).\n */\nexport interface AgentsOptions {\n /** Per-agent WhatsApp connect URLs. Absent entries return null. */\n whatsappUrls?: Record<string, string>;\n}\n\nexport function makeAgents(opts: AgentsOptions = {}) {\n return {\n /**\n * Returns a WhatsApp connect URL for the given agent, or null when not\n * configured. Meant to be dropped straight into `<a href={...}>` — React\n * omits the attribute when null so the anchor becomes inert instead of\n * navigating to \"null\".\n */\n getWhatsAppConnectURL(agentName: string): string | null {\n return opts.whatsappUrls?.[agentName] ?? null;\n },\n };\n}\n","import type { Provider, SupabaseClient } from '@supabase/supabase-js';\n\nexport interface SignInArgs {\n email: string;\n password: string;\n}\n\nexport interface SignUpArgs {\n email: string;\n password: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface VerifyOtpArgs {\n email: string;\n otpCode: string;\n}\n\nexport interface ResetPasswordArgs {\n /**\n * Reset token from the email link. Ignored by this shim — Supabase already\n * exchanged the link fragment for a session before the app got here, so\n * `updateUser({password})` operates on that session. Kept in the signature\n * for source-compat with @base44/sdk callers.\n */\n resetToken?: string;\n newPassword: string;\n}\n\nexport interface ResetPasswordRequestOptions {\n /** URL Supabase redirects to after the user clicks the reset link. */\n redirectTo?: string;\n}\n\nexport interface AuthOptions {\n /**\n * Browser path the redirectToLogin() shim should send users to.\n * Default: '/login'.\n */\n loginPath?: string;\n /**\n * Default redirect URL for password-reset emails. Callers can still override\n * per-call via resetPasswordRequest(email, { redirectTo }).\n */\n resetPasswordRedirect?: string;\n}\n\nlet setTokenWarned = false;\n\nexport function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {\n const loginPath = opts.loginPath ?? '/login';\n\n return {\n async signIn({ email, password }: SignInArgs) {\n const { data, error } = await client.auth.signInWithPassword({ email, password });\n if (error) throw error;\n return data;\n },\n /** Base44 alias for signIn. */\n async loginViaEmailPassword(email: string, password: string) {\n const { data, error } = await client.auth.signInWithPassword({ email, password });\n if (error) throw error;\n return data;\n },\n async signUp({ email, password, metadata }: SignUpArgs) {\n const { data, error } = await client.auth.signUp({\n email,\n password,\n options: { data: metadata ?? {} },\n });\n if (error) throw error;\n return data;\n },\n /** Base44 alias for signUp. */\n async register({ email, password, metadata }: SignUpArgs) {\n const { data, error } = await client.auth.signUp({\n email,\n password,\n options: { data: metadata ?? {} },\n });\n if (error) throw error;\n return data;\n },\n /**\n * Base44 OAuth flow: redirects the browser to the provider's consent screen\n * and back to `returnPath` (relative to window.location.origin) on success.\n * Supabase equivalent: signInWithOAuth with an absolute redirectTo.\n */\n async loginWithProvider(provider: Provider, returnPath?: string) {\n const redirectTo =\n typeof window !== 'undefined'\n ? window.location.origin + (returnPath ?? '/')\n : returnPath;\n const { data, error } = await client.auth.signInWithOAuth({\n provider,\n options: redirectTo ? { redirectTo } : undefined,\n });\n if (error) throw error;\n return data;\n },\n /**\n * Base44 email OTP verification after register(). Supabase's verifyOtp\n * already sets the session on success, so setToken() is redundant afterward\n * (kept as a soft no-op for source-compat).\n */\n async verifyOtp({ email, otpCode }: VerifyOtpArgs) {\n const { data, error } = await client.auth.verifyOtp({\n email,\n token: otpCode,\n type: 'signup',\n });\n if (error) throw error;\n // Base44's return shape included `access_token` at the top level; expose\n // both that and the session/user so callers can pick either style.\n return {\n access_token: data.session?.access_token,\n session: data.session,\n user: data.user,\n };\n },\n async resendOtp(email: string) {\n const { error } = await client.auth.resend({ email, type: 'signup' });\n if (error) throw error;\n },\n /**\n * No-op alias kept so migrated code doesn't TypeError. Supabase's\n * verifyOtp() already installed the session — pushing the access_token in\n * again would do nothing productive (Supabase requires access + refresh to\n * setSession, and Base44 returns only access). Warns once per process.\n */\n setToken(_accessToken: string) {\n if (!setTokenWarned) {\n setTokenWarned = true;\n if (typeof console !== 'undefined') {\n console.warn(\n '[base44-shim] auth.setToken() is a no-op — verifyOtp()/signInWithPassword() ' +\n 'already installed the Supabase session. Safe to remove the call.',\n );\n }\n }\n },\n async resetPasswordRequest(email: string, options?: ResetPasswordRequestOptions) {\n const redirectTo = options?.redirectTo ?? opts.resetPasswordRedirect;\n const { error } = await client.auth.resetPasswordForEmail(\n email,\n redirectTo ? { redirectTo } : undefined,\n );\n if (error) throw error;\n },\n async resetPassword({ newPassword }: ResetPasswordArgs) {\n const { data, error } = await client.auth.updateUser({ password: newPassword });\n if (error) throw error;\n return data;\n },\n async signOut() {\n const { error } = await client.auth.signOut();\n if (error) throw error;\n },\n /**\n * Base44 alias for signOut. If `returnUrl` is provided, navigates there\n * after signOut resolves so SPAs can drop users on a public route.\n */\n async logout(returnUrl?: string) {\n const { error } = await client.auth.signOut();\n if (error) throw error;\n if (returnUrl && typeof window !== 'undefined') {\n window.location.assign(returnUrl);\n }\n },\n async isAuthenticated(): Promise<boolean> {\n const { data } = await client.auth.getSession();\n return !!data.session;\n },\n async getUser() {\n const { data, error } = await client.auth.getUser();\n if (error) throw error;\n return data.user;\n },\n /** Base44 alias for getUser. Returns the current user object or throws if not signed in. */\n async me() {\n const { data, error } = await client.auth.getUser();\n if (error) throw error;\n if (!data.user) throw new Error('Not authenticated');\n return data.user;\n },\n /**\n * Base44 alias for updating the current user's metadata. Accepts arbitrary\n * key/value pairs that get stored in `user_metadata`.\n */\n async updateMe(metadata: Record<string, unknown>) {\n const { data, error } = await client.auth.updateUser({ data: metadata });\n if (error) throw error;\n return data.user;\n },\n async getSession() {\n const { data, error } = await client.auth.getSession();\n if (error) throw error;\n return data.session;\n },\n /**\n * Base44 used to redirect SPA users to its hosted login page. Self-host\n * has no hosted login, so this just navigates to the configured local\n * loginPath. Override the path via createClient({ ..., authLoginPath: '/x' }).\n */\n redirectToLogin(returnUrl?: string) {\n if (typeof window === 'undefined') return;\n // Already on the login route → no-op. Prevents redirect loops when an\n // unauthenticated check on /login itself fires another redirectToLogin.\n if (window.location.pathname === loginPath) return;\n // Defensive: if the returnUrl already points back to a login page (cyclic\n // chain from old buggy state), drop it. Also drop if it's absurdly long.\n let safeReturn: string | undefined = returnUrl;\n if (safeReturn) {\n const looksCyclic = safeReturn.includes(`${loginPath}?next=`) || safeReturn.includes(`${loginPath}%3F`);\n if (looksCyclic || safeReturn.length > 1024) safeReturn = undefined;\n }\n const url = safeReturn\n ? `${loginPath}?next=${encodeURIComponent(safeReturn)}`\n : loginPath;\n window.location.assign(url);\n },\n onAuthStateChange(cb: Parameters<SupabaseClient['auth']['onAuthStateChange']>[0]) {\n return client.auth.onAuthStateChange(cb);\n },\n };\n}\n\n/** Test-only: reset the process-global warn-once state so multiple tests can assert it. */\nexport function __resetSetTokenWarnedForTests() {\n setTokenWarned = false;\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\n/**\n * Stub for `base44.appLogs` — Base44 cloud's per-page activity tracker.\n * Writes a row to core.audit_log if the table exists, otherwise silently\n * succeeds. App code wraps this in .catch(() => {}) anyway, so any failure\n * is non-fatal.\n */\nexport function makeAppLogs(client: SupabaseClient, app: string) {\n return {\n async logUserInApp(pageName: string): Promise<void> {\n try {\n await client.schema('core' as never).from('audit_logs').insert({\n app,\n action: 'page_view',\n module: pageName,\n });\n } catch {\n // best-effort; analytics errors must never break the app\n }\n },\n };\n}\n\n/**\n * Stub for `base44.users` — admin-only user management. Self-host equivalent\n * uses Supabase Auth admin API but requires a service_role key, which the\n * browser client doesn't have. So inviteUser here logs a warning and returns\n * a benign error so callers can show a \"not supported\" message.\n */\nexport function makeUsers() {\n return {\n async inviteUser(_args: { email: string; [key: string]: unknown }): Promise<never> {\n throw new Error(\n 'inviteUser is admin-only and not exposed to the browser shim. ' +\n 'Use the Studio dashboard or an edge function with service_role to invite users.',\n );\n },\n };\n}\n\n/** Empty placeholder for `base44.app` — kept defined so property access doesn't crash. */\nexport const app: Record<string, unknown> = {};\n","import type { SupabaseClient } from '@supabase/supabase-js';\n\nexport interface UploadFileArgs {\n /** Supabase Storage bucket name. Defaults to schemaPrefix from client options. */\n bucket?: string;\n /** Object path within the bucket (e.g. 'invoices/2026/inv-001.pdf'). */\n path: string;\n /** File contents. */\n file: Blob | File | ArrayBuffer | Uint8Array;\n /** Content-Type. Inferred from File if omitted. */\n contentType?: string;\n /** Overwrite existing object at path. Default false. */\n upsert?: boolean;\n}\n\nexport function makeStorage(client: SupabaseClient, defaultBucket: string) {\n return {\n /** Upload a file to a bucket. Returns the public URL. */\n async uploadFile({\n bucket,\n path,\n file,\n contentType,\n upsert = false,\n }: UploadFileArgs): Promise<{ path: string; url: string }> {\n const b = bucket ?? defaultBucket;\n const { error } = await client.storage.from(b).upload(path, file, {\n contentType,\n upsert,\n });\n if (error) throw error;\n const { data } = client.storage.from(b).getPublicUrl(path);\n return { path, url: data.publicUrl };\n },\n /** Get a public URL for a stored object. */\n getPublicUrl(path: string, bucket?: string): string {\n const b = bucket ?? defaultBucket;\n const { data } = client.storage.from(b).getPublicUrl(path);\n return data.publicUrl;\n },\n /** Generate a time-limited signed URL for private buckets. */\n async createSignedUrl(path: string, expiresInSec = 3600, bucket?: string): Promise<string> {\n const b = bucket ?? defaultBucket;\n const { data, error } = await client.storage.from(b).createSignedUrl(path, expiresInSec);\n if (error) throw error;\n return data.signedUrl;\n },\n /** Delete one or more objects. */\n async remove(paths: string | string[], bucket?: string): Promise<void> {\n const b = bucket ?? defaultBucket;\n const list = Array.isArray(paths) ? paths : [paths];\n const { error } = await client.storage.from(b).remove(list);\n if (error) throw error;\n },\n /** List objects in a bucket prefix. */\n async list(prefix?: string, bucket?: string) {\n const b = bucket ?? defaultBucket;\n const { data, error } = await client.storage.from(b).list(prefix);\n if (error) throw error;\n return data ?? [];\n },\n };\n}\n"],"mappings":"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","names":["app"]}
@@ -62,6 +62,18 @@ function makeIntegrations(client, opts) {
62
62
  });
63
63
  if (error) throw error;
64
64
  return data;
65
+ },
66
+ async GenerateImage(payload) {
67
+ if (!opts.generateImageFunction) {
68
+ throw new Error(
69
+ "GenerateImage not configured. Image-gen features are disabled in this self-host build. Set integrations.generateImageFunction in createClient() and deploy an edge function that proxies to your image endpoint (SDXL / DALL\xB7E gateway)."
70
+ );
71
+ }
72
+ const { data, error } = await client.functions.invoke(opts.generateImageFunction, {
73
+ body: payload
74
+ });
75
+ if (error) throw error;
76
+ return data;
65
77
  }
66
78
  };
67
79
  return { Core };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/integrations.ts"],"sourcesContent":["import type { SupabaseClient } from '@supabase/supabase-js';\n\nexport interface IntegrationsOptions {\n /** Default storage bucket for UploadFile. Falls back to schemaPrefix from createClient. */\n defaultBucket: string;\n /**\n * Edge function name to invoke for SendEmail. If unset, calls fail loudly.\n * Implement this function in supabase/volumes/functions/send-email/.\n */\n sendEmailFunction?: string;\n /**\n * Edge function name to invoke for InvokeLLM. If unset, calls fail loudly\n * (AI features are out of scope for the air-gapped self-host stack).\n */\n invokeLlmFunction?: string;\n}\n\n/**\n * Stub of `base44.integrations.Core.*`. Three methods are implemented:\n *\n * UploadFile → delegates to Supabase Storage upload + returns {url, path}.\n * SendEmail → invokes a configured edge function (or throws if none).\n * InvokeLLM → invokes a configured edge function (or throws if none).\n *\n * Air-gapped LAN cannot call OpenAI directly; wire your own LLM endpoint\n * (Ollama, internal API gateway, etc.) inside an edge function and pass the\n * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay' } }).\n */\nexport function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptions) {\n const Core = {\n async UploadFile({\n file,\n bucket,\n path,\n contentType,\n }: {\n file: Blob | File | ArrayBuffer | Uint8Array;\n bucket?: string;\n path?: string;\n contentType?: string;\n }): Promise<{ url: string; path: string }> {\n const b = bucket ?? opts.defaultBucket;\n const p =\n path ??\n `uploads/${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${(file as File)?.name ?? 'file'}`;\n const { error } = await client.storage.from(b).upload(p, file, {\n contentType: contentType ?? (file as File)?.type,\n upsert: false,\n });\n if (error) throw error;\n const { data } = client.storage.from(b).getPublicUrl(p);\n return { url: data.publicUrl, path: p };\n },\n\n async SendEmail(payload: {\n to: string | string[];\n subject: string;\n body?: string;\n html?: string;\n from?: string;\n }): Promise<{ ok: boolean }> {\n if (!opts.sendEmailFunction) {\n throw new Error(\n 'SendEmail not configured. Set integrations.sendEmailFunction in createClient() ' +\n 'and deploy a corresponding Supabase Edge Function (e.g. send-email).',\n );\n }\n const { error } = await client.functions.invoke(opts.sendEmailFunction, { body: payload });\n if (error) throw error;\n return { ok: true };\n },\n\n async InvokeLLM(payload: {\n prompt: string;\n model?: string;\n [key: string]: unknown;\n }): Promise<unknown> {\n if (!opts.invokeLlmFunction) {\n throw new Error(\n 'InvokeLLM not configured. AI features are disabled in this self-host build. ' +\n 'Set integrations.invokeLlmFunction in createClient() and deploy an edge function ' +\n 'that proxies to your LLM endpoint (Ollama / internal gateway).',\n );\n }\n const { data, error } = await client.functions.invoke(opts.invokeLlmFunction, {\n body: payload,\n });\n if (error) throw error;\n return data;\n },\n };\n\n return { Core };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BO,SAAS,iBAAiB,QAAwB,MAA2B;AAClF,QAAM,OAAO;AAAA,IACX,MAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAK2C;AACzC,YAAM,IAAI,UAAU,KAAK;AACzB,YAAM,IACJ,QACA,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,IAAK,MAAe,QAAQ,MAAM;AACnG,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,QAAQ,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM;AAAA,QAC7D,aAAa,eAAgB,MAAe;AAAA,QAC5C,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,MAAO,OAAM;AACjB,YAAM,EAAE,KAAK,IAAI,OAAO,QAAQ,KAAK,CAAC,EAAE,aAAa,CAAC;AACtD,aAAO,EAAE,KAAK,KAAK,WAAW,MAAM,EAAE;AAAA,IACxC;AAAA,IAEA,MAAM,UAAU,SAMa;AAC3B,UAAI,CAAC,KAAK,mBAAmB;AAC3B,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AACA,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,UAAU,OAAO,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AACzF,UAAI,MAAO,OAAM;AACjB,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IAEA,MAAM,UAAU,SAIK;AACnB,UAAI,CAAC,KAAK,mBAAmB;AAC3B,cAAM,IAAI;AAAA,UACR;AAAA,QAGF;AAAA,MACF;AACA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,UAAU,OAAO,KAAK,mBAAmB;AAAA,QAC5E,MAAM;AAAA,MACR,CAAC;AACD,UAAI,MAAO,OAAM;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,EAAE,KAAK;AAChB;","names":[]}
1
+ {"version":3,"sources":["../src/integrations.ts"],"sourcesContent":["import type { SupabaseClient } from '@supabase/supabase-js';\n\nexport interface IntegrationsOptions {\n /** Default storage bucket for UploadFile. Falls back to schemaPrefix from createClient. */\n defaultBucket: string;\n /**\n * Edge function name to invoke for SendEmail. If unset, calls fail loudly.\n * Implement this function in supabase/volumes/functions/send-email/.\n */\n sendEmailFunction?: string;\n /**\n * Edge function name to invoke for InvokeLLM. If unset, calls fail loudly\n * (AI features are out of scope for the air-gapped self-host stack).\n */\n invokeLlmFunction?: string;\n /**\n * Edge function name to invoke for GenerateImage. If unset, calls fail loudly.\n * Base44's default backing was DALL·E — for self-host, proxy your own image\n * endpoint through an edge function.\n */\n generateImageFunction?: string;\n}\n\n/**\n * Stub of `base44.integrations.Core.*`. Four methods are implemented:\n *\n * UploadFile → delegates to Supabase Storage upload + returns {url, path}.\n * SendEmail → invokes a configured edge function (or throws if none).\n * InvokeLLM → invokes a configured edge function (or throws if none).\n * GenerateImage → invokes a configured edge function (or throws if none).\n *\n * Air-gapped LAN cannot call OpenAI directly; wire your own LLM/image endpoint\n * (Ollama, internal API gateway, etc.) inside an edge function and pass the\n * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay',\n * generateImageFunction: 'image-relay' } }).\n */\nexport function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptions) {\n const Core = {\n async UploadFile({\n file,\n bucket,\n path,\n contentType,\n }: {\n file: Blob | File | ArrayBuffer | Uint8Array;\n bucket?: string;\n path?: string;\n contentType?: string;\n }): Promise<{ url: string; path: string }> {\n const b = bucket ?? opts.defaultBucket;\n const p =\n path ??\n `uploads/${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${(file as File)?.name ?? 'file'}`;\n const { error } = await client.storage.from(b).upload(p, file, {\n contentType: contentType ?? (file as File)?.type,\n upsert: false,\n });\n if (error) throw error;\n const { data } = client.storage.from(b).getPublicUrl(p);\n return { url: data.publicUrl, path: p };\n },\n\n async SendEmail(payload: {\n to: string | string[];\n subject: string;\n body?: string;\n html?: string;\n from?: string;\n }): Promise<{ ok: boolean }> {\n if (!opts.sendEmailFunction) {\n throw new Error(\n 'SendEmail not configured. Set integrations.sendEmailFunction in createClient() ' +\n 'and deploy a corresponding Supabase Edge Function (e.g. send-email).',\n );\n }\n const { error } = await client.functions.invoke(opts.sendEmailFunction, { body: payload });\n if (error) throw error;\n return { ok: true };\n },\n\n async InvokeLLM(payload: {\n prompt: string;\n model?: string;\n [key: string]: unknown;\n }): Promise<unknown> {\n if (!opts.invokeLlmFunction) {\n throw new Error(\n 'InvokeLLM not configured. AI features are disabled in this self-host build. ' +\n 'Set integrations.invokeLlmFunction in createClient() and deploy an edge function ' +\n 'that proxies to your LLM endpoint (Ollama / internal gateway).',\n );\n }\n const { data, error } = await client.functions.invoke(opts.invokeLlmFunction, {\n body: payload,\n });\n if (error) throw error;\n return data;\n },\n\n async GenerateImage(payload: {\n prompt: string;\n [key: string]: unknown;\n }): Promise<unknown> {\n if (!opts.generateImageFunction) {\n throw new Error(\n 'GenerateImage not configured. Image-gen features are disabled in this self-host ' +\n 'build. Set integrations.generateImageFunction in createClient() and deploy an ' +\n 'edge function that proxies to your image endpoint (SDXL / DALL·E gateway).',\n );\n }\n const { data, error } = await client.functions.invoke(opts.generateImageFunction, {\n body: payload,\n });\n if (error) throw error;\n return data;\n },\n };\n\n return { Core };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCO,SAAS,iBAAiB,QAAwB,MAA2B;AAClF,QAAM,OAAO;AAAA,IACX,MAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAK2C;AACzC,YAAM,IAAI,UAAU,KAAK;AACzB,YAAM,IACJ,QACA,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,IAAK,MAAe,QAAQ,MAAM;AACnG,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,QAAQ,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM;AAAA,QAC7D,aAAa,eAAgB,MAAe;AAAA,QAC5C,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,MAAO,OAAM;AACjB,YAAM,EAAE,KAAK,IAAI,OAAO,QAAQ,KAAK,CAAC,EAAE,aAAa,CAAC;AACtD,aAAO,EAAE,KAAK,KAAK,WAAW,MAAM,EAAE;AAAA,IACxC;AAAA,IAEA,MAAM,UAAU,SAMa;AAC3B,UAAI,CAAC,KAAK,mBAAmB;AAC3B,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AACA,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,UAAU,OAAO,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AACzF,UAAI,MAAO,OAAM;AACjB,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,IAEA,MAAM,UAAU,SAIK;AACnB,UAAI,CAAC,KAAK,mBAAmB;AAC3B,cAAM,IAAI;AAAA,UACR;AAAA,QAGF;AAAA,MACF;AACA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,UAAU,OAAO,KAAK,mBAAmB;AAAA,QAC5E,MAAM;AAAA,MACR,CAAC;AACD,UAAI,MAAO,OAAM;AACjB,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,cAAc,SAGC;AACnB,UAAI,CAAC,KAAK,uBAAuB;AAC/B,cAAM,IAAI;AAAA,UACR;AAAA,QAGF;AAAA,MACF;AACA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,UAAU,OAAO,KAAK,uBAAuB;AAAA,QAChF,MAAM;AAAA,MACR,CAAC;AACD,UAAI,MAAO,OAAM;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,EAAE,KAAK;AAChB;","names":[]}
@@ -13,17 +13,25 @@ interface IntegrationsOptions {
13
13
  * (AI features are out of scope for the air-gapped self-host stack).
14
14
  */
15
15
  invokeLlmFunction?: string;
16
+ /**
17
+ * Edge function name to invoke for GenerateImage. If unset, calls fail loudly.
18
+ * Base44's default backing was DALL·E — for self-host, proxy your own image
19
+ * endpoint through an edge function.
20
+ */
21
+ generateImageFunction?: string;
16
22
  }
17
23
  /**
18
- * Stub of `base44.integrations.Core.*`. Three methods are implemented:
24
+ * Stub of `base44.integrations.Core.*`. Four methods are implemented:
19
25
  *
20
- * UploadFile → delegates to Supabase Storage upload + returns {url, path}.
21
- * SendEmail → invokes a configured edge function (or throws if none).
22
- * InvokeLLM → invokes a configured edge function (or throws if none).
26
+ * UploadFile → delegates to Supabase Storage upload + returns {url, path}.
27
+ * SendEmail → invokes a configured edge function (or throws if none).
28
+ * InvokeLLM → invokes a configured edge function (or throws if none).
29
+ * GenerateImage → invokes a configured edge function (or throws if none).
23
30
  *
24
- * Air-gapped LAN cannot call OpenAI directly; wire your own LLM endpoint
31
+ * Air-gapped LAN cannot call OpenAI directly; wire your own LLM/image endpoint
25
32
  * (Ollama, internal API gateway, etc.) inside an edge function and pass the
26
- * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay' } }).
33
+ * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay',
34
+ * generateImageFunction: 'image-relay' } }).
27
35
  */
28
36
  declare function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptions): {
29
37
  Core: {
@@ -50,6 +58,10 @@ declare function makeIntegrations(client: SupabaseClient, opts: IntegrationsOpti
50
58
  model?: string;
51
59
  [key: string]: unknown;
52
60
  }): Promise<unknown>;
61
+ GenerateImage(payload: {
62
+ prompt: string;
63
+ [key: string]: unknown;
64
+ }): Promise<unknown>;
53
65
  };
54
66
  };
55
67
 
@@ -13,17 +13,25 @@ interface IntegrationsOptions {
13
13
  * (AI features are out of scope for the air-gapped self-host stack).
14
14
  */
15
15
  invokeLlmFunction?: string;
16
+ /**
17
+ * Edge function name to invoke for GenerateImage. If unset, calls fail loudly.
18
+ * Base44's default backing was DALL·E — for self-host, proxy your own image
19
+ * endpoint through an edge function.
20
+ */
21
+ generateImageFunction?: string;
16
22
  }
17
23
  /**
18
- * Stub of `base44.integrations.Core.*`. Three methods are implemented:
24
+ * Stub of `base44.integrations.Core.*`. Four methods are implemented:
19
25
  *
20
- * UploadFile → delegates to Supabase Storage upload + returns {url, path}.
21
- * SendEmail → invokes a configured edge function (or throws if none).
22
- * InvokeLLM → invokes a configured edge function (or throws if none).
26
+ * UploadFile → delegates to Supabase Storage upload + returns {url, path}.
27
+ * SendEmail → invokes a configured edge function (or throws if none).
28
+ * InvokeLLM → invokes a configured edge function (or throws if none).
29
+ * GenerateImage → invokes a configured edge function (or throws if none).
23
30
  *
24
- * Air-gapped LAN cannot call OpenAI directly; wire your own LLM endpoint
31
+ * Air-gapped LAN cannot call OpenAI directly; wire your own LLM/image endpoint
25
32
  * (Ollama, internal API gateway, etc.) inside an edge function and pass the
26
- * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay' } }).
33
+ * function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay',
34
+ * generateImageFunction: 'image-relay' } }).
27
35
  */
28
36
  declare function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptions): {
29
37
  Core: {
@@ -50,6 +58,10 @@ declare function makeIntegrations(client: SupabaseClient, opts: IntegrationsOpti
50
58
  model?: string;
51
59
  [key: string]: unknown;
52
60
  }): Promise<unknown>;
61
+ GenerateImage(payload: {
62
+ prompt: string;
63
+ [key: string]: unknown;
64
+ }): Promise<unknown>;
53
65
  };
54
66
  };
55
67
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeIntegrations
3
- } from "./chunk-PUROQAXO.js";
3
+ } from "./chunk-E2KG6ZL4.js";
4
4
  export {
5
5
  makeIntegrations
6
6
  };
package/dist/server.cjs CHANGED
@@ -285,6 +285,87 @@ function makeEntitiesProxy(client, opts) {
285
285
  });
286
286
  }
287
287
 
288
+ // src/functions.ts
289
+ function makeFunctions(client) {
290
+ return {
291
+ /** Invoke an edge function by name, passing JSON body. Returns parsed JSON. */
292
+ async invoke(name, payload) {
293
+ const { data, error } = await client.functions.invoke(name, {
294
+ body: payload
295
+ });
296
+ if (error) throw error;
297
+ return data;
298
+ },
299
+ /** Lower-level: invoke and return Response so caller can handle non-JSON. */
300
+ async fetch(name, init) {
301
+ const url = `${client.supabaseUrl}/functions/v1/${name}`;
302
+ const headers = new Headers(init?.headers);
303
+ const session = await client.auth.getSession();
304
+ const token = session.data.session?.access_token;
305
+ if (token) headers.set("Authorization", `Bearer ${token}`);
306
+ headers.set("apikey", client.supabaseKey);
307
+ return fetch(url, { ...init, headers });
308
+ }
309
+ };
310
+ }
311
+
312
+ // src/integrations.ts
313
+ function makeIntegrations(client, opts) {
314
+ const Core = {
315
+ async UploadFile({
316
+ file,
317
+ bucket,
318
+ path,
319
+ contentType
320
+ }) {
321
+ const b = bucket ?? opts.defaultBucket;
322
+ const p = path ?? `uploads/${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${file?.name ?? "file"}`;
323
+ const { error } = await client.storage.from(b).upload(p, file, {
324
+ contentType: contentType ?? file?.type,
325
+ upsert: false
326
+ });
327
+ if (error) throw error;
328
+ const { data } = client.storage.from(b).getPublicUrl(p);
329
+ return { url: data.publicUrl, path: p };
330
+ },
331
+ async SendEmail(payload) {
332
+ if (!opts.sendEmailFunction) {
333
+ throw new Error(
334
+ "SendEmail not configured. Set integrations.sendEmailFunction in createClient() and deploy a corresponding Supabase Edge Function (e.g. send-email)."
335
+ );
336
+ }
337
+ const { error } = await client.functions.invoke(opts.sendEmailFunction, { body: payload });
338
+ if (error) throw error;
339
+ return { ok: true };
340
+ },
341
+ async InvokeLLM(payload) {
342
+ if (!opts.invokeLlmFunction) {
343
+ throw new Error(
344
+ "InvokeLLM not configured. AI features are disabled in this self-host build. Set integrations.invokeLlmFunction in createClient() and deploy an edge function that proxies to your LLM endpoint (Ollama / internal gateway)."
345
+ );
346
+ }
347
+ const { data, error } = await client.functions.invoke(opts.invokeLlmFunction, {
348
+ body: payload
349
+ });
350
+ if (error) throw error;
351
+ return data;
352
+ },
353
+ async GenerateImage(payload) {
354
+ if (!opts.generateImageFunction) {
355
+ throw new Error(
356
+ "GenerateImage not configured. Image-gen features are disabled in this self-host build. Set integrations.generateImageFunction in createClient() and deploy an edge function that proxies to your image endpoint (SDXL / DALL\xB7E gateway)."
357
+ );
358
+ }
359
+ const { data, error } = await client.functions.invoke(opts.generateImageFunction, {
360
+ body: payload
361
+ });
362
+ if (error) throw error;
363
+ return data;
364
+ }
365
+ };
366
+ return { Core };
367
+ }
368
+
288
369
  // src/server.ts
289
370
  function createClientFromRequest(req, options) {
290
371
  if (!options.supabaseUrl) throw new Error("createClientFromRequest: supabaseUrl is required");
@@ -306,11 +387,21 @@ function createClientFromRequest(req, options) {
306
387
  sharedEntities: options.sharedEntities,
307
388
  entityMap: options.entityMap
308
389
  };
390
+ const integrationsOpts = {
391
+ defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,
392
+ sendEmailFunction: options.integrations?.sendEmailFunction,
393
+ invokeLlmFunction: options.integrations?.invokeLlmFunction,
394
+ generateImageFunction: options.integrations?.generateImageFunction
395
+ };
309
396
  return {
310
397
  supabase: userClient,
311
398
  entities: makeEntitiesProxy(userClient, mappingOpts),
399
+ functions: makeFunctions(userClient),
400
+ integrations: makeIntegrations(userClient, integrationsOpts),
312
401
  asServiceRole: {
313
- entities: makeEntitiesProxy(serviceClient, mappingOpts)
402
+ entities: makeEntitiesProxy(serviceClient, mappingOpts),
403
+ functions: makeFunctions(serviceClient),
404
+ integrations: makeIntegrations(serviceClient, integrationsOpts)
314
405
  }
315
406
  };
316
407
  }