@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/README.md +121 -5
- package/dist/{chunk-PUROQAXO.js → chunk-E2KG6ZL4.js} +13 -1
- package/dist/chunk-E2KG6ZL4.js.map +1 -0
- package/dist/{chunk-SWURHLDN.js → chunk-YQ3BDCIS.js} +27 -2
- package/dist/chunk-YQ3BDCIS.js.map +1 -0
- package/dist/index.cjs +122 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -17
- package/dist/index.d.ts +103 -17
- package/dist/index.js +115 -30
- package/dist/index.js.map +1 -1
- package/dist/integrations.cjs +12 -0
- package/dist/integrations.cjs.map +1 -1
- package/dist/integrations.d.cts +18 -6
- package/dist/integrations.d.ts +18 -6
- package/dist/integrations.js +1 -1
- package/dist/server.cjs +92 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +18 -6
- package/dist/server.d.ts +18 -6
- package/dist/server.js +17 -3
- package/dist/server.js.map +1 -1
- package/dist/{types-HIZDZaWa.d.cts → types-CnrxaSFp.d.cts} +12 -1
- package/dist/{types-HIZDZaWa.d.ts → types-CnrxaSFp.d.ts} +12 -1
- package/package.json +7 -3
- package/src/agents.ts +28 -0
- package/src/auth.ts +133 -3
- package/src/index.ts +7 -0
- package/src/integrations.ts +32 -6
- package/src/server.ts +32 -2
- package/dist/chunk-PUROQAXO.js.map +0 -1
- package/dist/chunk-SWURHLDN.js.map +0 -1
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/entities.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeEntitiesProxy } from './entities.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\n\nexport interface ServerClient {\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n asServiceRole: { entities: EntitiesProxy };\n}\n\n/**\n * Create a Base44-style client from an incoming HTTP Request, intended for\n * Supabase Edge Functions (Deno) or any server runtime that has fetch Request.\n *\n * Honors the caller's Authorization header so RLS applies as the end user.\n * `asServiceRole` uses the configured service_role key (bypasses RLS) for\n * privileged operations — analogous to base44.asServiceRole.\n */\nexport function createClientFromRequest(\n req: Request,\n options: Omit<ClientOptions, 'client'> & { supabaseServiceRoleKey: string },\n): ServerClient {\n if (!options.supabaseUrl) throw new Error('createClientFromRequest: supabaseUrl is required');\n if (!options.supabaseAnonKey)\n throw new Error('createClientFromRequest: supabaseAnonKey is required');\n if (!options.supabaseServiceRoleKey)\n throw new Error('createClientFromRequest: supabaseServiceRoleKey is required for server use');\n\n const authHeader = req.headers.get('Authorization') ?? '';\n const userClient = createSupabase(options.supabaseUrl, options.supabaseAnonKey, {\n global: { headers: { Authorization: authHeader } },\n auth: { persistSession: false, autoRefreshToken: false },\n });\n const serviceClient = createSupabase(options.supabaseUrl, options.supabaseServiceRoleKey, {\n auth: { persistSession: false, autoRefreshToken: false },\n });\n\n const mappingOpts = {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n };\n\n return {\n supabase: userClient,\n entities: makeEntitiesProxy(userClient, mappingOpts),\n asServiceRole: {\n entities: makeEntitiesProxy(serviceClient, mappingOpts),\n },\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n ClientOptions,\n EntitiesProxy,\n EntityApi,\n EntityMapping,\n FilterObject,\n FilterValue,\n OrderBy,\n} from './types.js';\n\nconst DEFAULT_SHARED_ENTITIES = [\n // Auth/identity (option C: shared)\n 'User',\n 'Role',\n 'UserRole', // 'finance.user_roles' was 404 — UserRole belongs in shared\n 'Department',\n // Org (option C: shared)\n 'Company',\n // Cross-app entities exposed by core schema\n 'AuditLog',\n // Note: Customer is intentionally NOT shared — each app's Customer schema\n // differs significantly (CRM vs Facility vs Construction).\n];\n\n/** PascalCase → snake_case + naive pluralization (s, ies, es). */\nexport function defaultEntityToTable(entityName: string): string {\n const snake = entityName.replace(/([A-Z])/g, (m, c, i) =>\n i === 0 ? c.toLowerCase() : '_' + c.toLowerCase(),\n );\n if (snake.endsWith('y') && !/[aeiou]y$/.test(snake)) return snake.slice(0, -1) + 'ies';\n if (/(s|x|z|ch|sh)$/.test(snake)) return snake + 'es';\n return snake + 's';\n}\n\nexport function resolveEntityMapping(\n entityName: string,\n opts: Required<Pick<ClientOptions, 'schemaPrefix'>> &\n Pick<ClientOptions, 'sharedSchema' | 'sharedEntities' | 'entityMap'>,\n): EntityMapping {\n if (opts.entityMap?.[entityName]) return opts.entityMap[entityName];\n const sharedEntities = opts.sharedEntities ?? DEFAULT_SHARED_ENTITIES;\n const sharedSchema = opts.sharedSchema ?? 'core';\n const schema = sharedEntities.includes(entityName) ? sharedSchema : opts.schemaPrefix;\n return { schema, table: defaultEntityToTable(entityName) };\n}\n\n/**\n * Parse Base44-style orderBy:\n * - string '-created_date' → { field: 'created_date', ascending: false }\n * - string 'name' → { field: 'name', ascending: true }\n * - object passes through.\n */\nexport function parseOrderBy(input: string | OrderBy | undefined): OrderBy | undefined {\n if (!input) return undefined;\n if (typeof input === 'object') return input;\n if (input.startsWith('-')) return { field: input.slice(1), ascending: false };\n return { field: input, ascending: true };\n}\n\nconst MONGO_OPS = [\n '$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin', '$like', '$ilike',\n] as const;\n\nfunction isMongoFilter(v: unknown): v is Record<string, unknown> {\n if (!v || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.keys(v as object).some((k) =>\n (MONGO_OPS as readonly string[]).includes(k),\n );\n}\n\nfunction applyMongoOps(query: any, field: string, ops: Record<string, unknown>): any {\n for (const [op, value] of Object.entries(ops)) {\n switch (op) {\n case '$eq': query = query.eq(field, value); break;\n case '$ne': query = query.neq(field, value); break;\n case '$gt': query = query.gt(field, value); break;\n case '$gte': query = query.gte(field, value); break;\n case '$lt': query = query.lt(field, value); break;\n case '$lte': query = query.lte(field, value); break;\n case '$in': query = query.in(field, value as unknown[]); break;\n case '$nin': query = query.not('in', `(${(value as unknown[]).map(v => JSON.stringify(v)).join(',')})`); break;\n case '$like': query = query.like(field, value as string); break;\n case '$ilike': query = query.ilike(field, value as string); break;\n // Unknown ops are ignored rather than throwing — keeps shim forward-\n // compatible if Base44 ships new operators we haven't seen yet.\n }\n }\n return query;\n}\n\nfunction applyFilter(query: any, where: FilterObject): any {\n for (const [field, raw] of Object.entries(where)) {\n const v = raw as FilterValue;\n if (v === null) {\n query = query.is(field, null);\n } else if (isMongoFilter(v)) {\n query = applyMongoOps(query, field, v as Record<string, unknown>);\n } else if (typeof v === 'object' && !Array.isArray(v) && 'op' in v) {\n // legacy {op, value} form — translate to the Mongo path so behaviour stays in sync\n const { op, value } = v as { op: string; value: unknown };\n query = applyMongoOps(query, field, { [`$${op}`]: value });\n } else if (Array.isArray(v)) {\n query = query.in(field, v);\n } else {\n query = query.eq(field, v);\n }\n }\n return query;\n}\n\nfunction applyRange(query: any, limit: number | undefined, skip: number | undefined): any {\n if (typeof skip === 'number' && typeof limit === 'number') {\n return query.range(skip, skip + limit - 1);\n }\n if (typeof limit === 'number') return query.limit(limit);\n return query;\n}\n\nexport function makeEntityApi(client: SupabaseClient, mapping: EntityMapping): EntityApi {\n const from = () => client.schema(mapping.schema as never).from(mapping.table);\n\n // Treat \"table not in schema cache\" (PGRST205) and 404 as empty result, not error.\n // Apps reference many entities that may not exist in self-host schema yet —\n // surfacing as empty lets the UI render skeletons instead of crashing.\n const isMissingTableError = (e: unknown): boolean => {\n if (!e || typeof e !== 'object') return false;\n const code = (e as { code?: string }).code;\n const status = (e as { status?: number }).status;\n return code === 'PGRST205' || code === '42P01' || status === 404;\n };\n const warnedTables = new Set<string>();\n const warnMissing = () => {\n const key = `${mapping.schema}.${mapping.table}`;\n if (warnedTables.has(key)) return;\n warnedTables.add(key);\n if (typeof console !== 'undefined') console.warn(`[base44-shim] table ${key} not found — returning empty result`);\n };\n\n return {\n async list(orderBy, limit, skip) {\n let q = from().select('*');\n const ob = parseOrderBy(orderBy);\n if (ob) q = q.order(ob.field, { ascending: ob.ascending ?? true });\n q = applyRange(q, limit, skip);\n const { data, error } = await q;\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return []; }\n throw error;\n }\n return data ?? [];\n },\n async filter(where, orderBy, limit, skip) {\n let q = from().select('*');\n q = applyFilter(q, where);\n const ob = parseOrderBy(orderBy);\n if (ob) q = q.order(ob.field, { ascending: ob.ascending ?? true });\n q = applyRange(q, limit, skip);\n const { data, error } = await q;\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return []; }\n throw error;\n }\n return data ?? [];\n },\n async get(id) {\n const { data, error } = await from().select('*').eq('id', id).maybeSingle();\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return null; }\n throw error;\n }\n return data ?? null;\n },\n async read(id) {\n const { data, error } = await from().select('*').eq('id', id).maybeSingle();\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return null; }\n throw error;\n }\n return data ?? null;\n },\n async create(body) {\n const { data, error } = await from().insert(body).select().single();\n if (error) throw error;\n return data;\n },\n async bulkCreate(rows) {\n if (!rows.length) return [];\n const { data, error } = await from().insert(rows).select();\n if (error) throw error;\n return data ?? [];\n },\n async update(id, body) {\n const { data, error } = await from().update(body).eq('id', id).select().single();\n if (error) throw error;\n return data;\n },\n async bulkUpdate(rows) {\n if (!rows.length) return [];\n // PostgREST has no native multi-patch with per-row payloads; do one\n // round-trip per row. Fine for hundreds — re-evaluate if a caller\n // starts pushing thousands and we need a CTE-based RPC.\n const results = await Promise.all(\n rows.map(({ id, ...patch }) =>\n from().update(patch).eq('id', id).select().single(),\n ),\n );\n const errors = results.map((r) => r.error).filter(Boolean);\n if (errors.length) throw errors[0];\n return results.map((r) => r.data) as any[];\n },\n async updateMany(where, update) {\n // Base44 SDK / Mongo style: `{ $set: { field: value } }` wraps the patch.\n // Unwrap so the same call works whether the caller used $set or a flat object.\n const patch = (update as { $set?: unknown })?.$set ?? update;\n let q = from().update(patch as Record<string, unknown>);\n q = applyFilter(q, where);\n const { data, error } = await q.select();\n if (error) throw error;\n return data ?? [];\n },\n async delete(id) {\n const { error } = await from().delete().eq('id', id);\n if (error) throw error;\n },\n async deleteMany(where) {\n let q = from().delete();\n q = applyFilter(q, where);\n const { error } = await q;\n if (error) throw error;\n },\n subscribe(callback) {\n const channel = client\n .channel(`${mapping.schema}.${mapping.table}.${Math.random().toString(36).slice(2, 8)}`)\n .on(\n 'postgres_changes' as never,\n { event: '*', schema: mapping.schema, table: mapping.table },\n (payload: { eventType: string; new?: unknown; old?: unknown }) => {\n const type = payload.eventType.toLowerCase() as 'insert' | 'update' | 'delete';\n callback({ type, new: payload.new as never, old: payload.old as never });\n },\n )\n .subscribe();\n return () => {\n void client.removeChannel(channel);\n };\n },\n };\n}\n\nexport function makeEntitiesProxy(\n client: SupabaseClient,\n opts: Required<Pick<ClientOptions, 'schemaPrefix'>> &\n Pick<ClientOptions, 'sharedSchema' | 'sharedEntities' | 'entityMap'>,\n): EntitiesProxy {\n const cache: Record<string, EntityApi> = {};\n return new Proxy({} as EntitiesProxy, {\n get(_target, prop: string) {\n if (typeof prop !== 'string') return undefined;\n if (!cache[prop]) {\n const mapping = resolveEntityMapping(prop, opts);\n cache[prop] = makeEntityApi(client, mapping);\n }\n return cache[prop];\n },\n });\n}\n"],"mappings":"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","names":["createSupabase"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/entities.ts","../src/functions.ts","../src/integrations.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeEntitiesProxy } from './entities.js';\nimport { makeFunctions } from './functions.js';\nimport { makeIntegrations, type IntegrationsOptions } from './integrations.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\n\nexport interface ServerClient {\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n functions: ReturnType<typeof makeFunctions>;\n integrations: ReturnType<typeof makeIntegrations>;\n asServiceRole: {\n entities: EntitiesProxy;\n functions: ReturnType<typeof makeFunctions>;\n integrations: ReturnType<typeof makeIntegrations>;\n };\n}\n\nexport interface CreateServerClientOptions\n extends Omit<ClientOptions, 'client'> {\n supabaseServiceRoleKey: string;\n /** Integration stub config (edge function names for SendEmail / InvokeLLM / GenerateImage). */\n integrations?: Partial<IntegrationsOptions>;\n}\n\n/**\n * Create a Base44-style client from an incoming HTTP Request, intended for\n * Supabase Edge Functions (Deno) or any server runtime that has fetch Request.\n *\n * Honors the caller's Authorization header so RLS applies as the end user.\n * `asServiceRole` uses the configured service_role key (bypasses RLS) for\n * privileged operations — analogous to base44.asServiceRole.\n *\n * Both the user and service-role sides expose `entities`, `functions`, and\n * `integrations.Core` so ported edge functions can call whichever surface they\n * used against Base44's managed backend.\n */\nexport function createClientFromRequest(\n req: Request,\n options: CreateServerClientOptions,\n): ServerClient {\n if (!options.supabaseUrl) throw new Error('createClientFromRequest: supabaseUrl is required');\n if (!options.supabaseAnonKey)\n throw new Error('createClientFromRequest: supabaseAnonKey is required');\n if (!options.supabaseServiceRoleKey)\n throw new Error('createClientFromRequest: supabaseServiceRoleKey is required for server use');\n\n const authHeader = req.headers.get('Authorization') ?? '';\n const userClient = createSupabase(options.supabaseUrl, options.supabaseAnonKey, {\n global: { headers: { Authorization: authHeader } },\n auth: { persistSession: false, autoRefreshToken: false },\n });\n const serviceClient = createSupabase(options.supabaseUrl, options.supabaseServiceRoleKey, {\n auth: { persistSession: false, autoRefreshToken: false },\n });\n\n const mappingOpts = {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n };\n\n const integrationsOpts: IntegrationsOptions = {\n defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,\n sendEmailFunction: options.integrations?.sendEmailFunction,\n invokeLlmFunction: options.integrations?.invokeLlmFunction,\n generateImageFunction: options.integrations?.generateImageFunction,\n };\n\n return {\n supabase: userClient,\n entities: makeEntitiesProxy(userClient, mappingOpts),\n functions: makeFunctions(userClient),\n integrations: makeIntegrations(userClient, integrationsOpts),\n asServiceRole: {\n entities: makeEntitiesProxy(serviceClient, mappingOpts),\n functions: makeFunctions(serviceClient),\n integrations: makeIntegrations(serviceClient, integrationsOpts),\n },\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n ClientOptions,\n EntitiesProxy,\n EntityApi,\n EntityMapping,\n FilterObject,\n FilterValue,\n OrderBy,\n} from './types.js';\n\nconst DEFAULT_SHARED_ENTITIES = [\n // Auth/identity (option C: shared)\n 'User',\n 'Role',\n 'UserRole', // 'finance.user_roles' was 404 — UserRole belongs in shared\n 'Department',\n // Org (option C: shared)\n 'Company',\n // Cross-app entities exposed by core schema\n 'AuditLog',\n // Note: Customer is intentionally NOT shared — each app's Customer schema\n // differs significantly (CRM vs Facility vs Construction).\n];\n\n/** PascalCase → snake_case + naive pluralization (s, ies, es). */\nexport function defaultEntityToTable(entityName: string): string {\n const snake = entityName.replace(/([A-Z])/g, (m, c, i) =>\n i === 0 ? c.toLowerCase() : '_' + c.toLowerCase(),\n );\n if (snake.endsWith('y') && !/[aeiou]y$/.test(snake)) return snake.slice(0, -1) + 'ies';\n if (/(s|x|z|ch|sh)$/.test(snake)) return snake + 'es';\n return snake + 's';\n}\n\nexport function resolveEntityMapping(\n entityName: string,\n opts: Required<Pick<ClientOptions, 'schemaPrefix'>> &\n Pick<ClientOptions, 'sharedSchema' | 'sharedEntities' | 'entityMap'>,\n): EntityMapping {\n if (opts.entityMap?.[entityName]) return opts.entityMap[entityName];\n const sharedEntities = opts.sharedEntities ?? DEFAULT_SHARED_ENTITIES;\n const sharedSchema = opts.sharedSchema ?? 'core';\n const schema = sharedEntities.includes(entityName) ? sharedSchema : opts.schemaPrefix;\n return { schema, table: defaultEntityToTable(entityName) };\n}\n\n/**\n * Parse Base44-style orderBy:\n * - string '-created_date' → { field: 'created_date', ascending: false }\n * - string 'name' → { field: 'name', ascending: true }\n * - object passes through.\n */\nexport function parseOrderBy(input: string | OrderBy | undefined): OrderBy | undefined {\n if (!input) return undefined;\n if (typeof input === 'object') return input;\n if (input.startsWith('-')) return { field: input.slice(1), ascending: false };\n return { field: input, ascending: true };\n}\n\nconst MONGO_OPS = [\n '$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin', '$like', '$ilike',\n] as const;\n\nfunction isMongoFilter(v: unknown): v is Record<string, unknown> {\n if (!v || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.keys(v as object).some((k) =>\n (MONGO_OPS as readonly string[]).includes(k),\n );\n}\n\nfunction applyMongoOps(query: any, field: string, ops: Record<string, unknown>): any {\n for (const [op, value] of Object.entries(ops)) {\n switch (op) {\n case '$eq': query = query.eq(field, value); break;\n case '$ne': query = query.neq(field, value); break;\n case '$gt': query = query.gt(field, value); break;\n case '$gte': query = query.gte(field, value); break;\n case '$lt': query = query.lt(field, value); break;\n case '$lte': query = query.lte(field, value); break;\n case '$in': query = query.in(field, value as unknown[]); break;\n case '$nin': query = query.not('in', `(${(value as unknown[]).map(v => JSON.stringify(v)).join(',')})`); break;\n case '$like': query = query.like(field, value as string); break;\n case '$ilike': query = query.ilike(field, value as string); break;\n // Unknown ops are ignored rather than throwing — keeps shim forward-\n // compatible if Base44 ships new operators we haven't seen yet.\n }\n }\n return query;\n}\n\nfunction applyFilter(query: any, where: FilterObject): any {\n for (const [field, raw] of Object.entries(where)) {\n const v = raw as FilterValue;\n if (v === null) {\n query = query.is(field, null);\n } else if (isMongoFilter(v)) {\n query = applyMongoOps(query, field, v as Record<string, unknown>);\n } else if (typeof v === 'object' && !Array.isArray(v) && 'op' in v) {\n // legacy {op, value} form — translate to the Mongo path so behaviour stays in sync\n const { op, value } = v as { op: string; value: unknown };\n query = applyMongoOps(query, field, { [`$${op}`]: value });\n } else if (Array.isArray(v)) {\n query = query.in(field, v);\n } else {\n query = query.eq(field, v);\n }\n }\n return query;\n}\n\nfunction applyRange(query: any, limit: number | undefined, skip: number | undefined): any {\n if (typeof skip === 'number' && typeof limit === 'number') {\n return query.range(skip, skip + limit - 1);\n }\n if (typeof limit === 'number') return query.limit(limit);\n return query;\n}\n\nexport function makeEntityApi(client: SupabaseClient, mapping: EntityMapping): EntityApi {\n const from = () => client.schema(mapping.schema as never).from(mapping.table);\n\n // Treat \"table not in schema cache\" (PGRST205) and 404 as empty result, not error.\n // Apps reference many entities that may not exist in self-host schema yet —\n // surfacing as empty lets the UI render skeletons instead of crashing.\n const isMissingTableError = (e: unknown): boolean => {\n if (!e || typeof e !== 'object') return false;\n const code = (e as { code?: string }).code;\n const status = (e as { status?: number }).status;\n return code === 'PGRST205' || code === '42P01' || status === 404;\n };\n const warnedTables = new Set<string>();\n const warnMissing = () => {\n const key = `${mapping.schema}.${mapping.table}`;\n if (warnedTables.has(key)) return;\n warnedTables.add(key);\n if (typeof console !== 'undefined') console.warn(`[base44-shim] table ${key} not found — returning empty result`);\n };\n\n return {\n async list(orderBy, limit, skip) {\n let q = from().select('*');\n const ob = parseOrderBy(orderBy);\n if (ob) q = q.order(ob.field, { ascending: ob.ascending ?? true });\n q = applyRange(q, limit, skip);\n const { data, error } = await q;\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return []; }\n throw error;\n }\n return data ?? [];\n },\n async filter(where, orderBy, limit, skip) {\n let q = from().select('*');\n q = applyFilter(q, where);\n const ob = parseOrderBy(orderBy);\n if (ob) q = q.order(ob.field, { ascending: ob.ascending ?? true });\n q = applyRange(q, limit, skip);\n const { data, error } = await q;\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return []; }\n throw error;\n }\n return data ?? [];\n },\n async get(id) {\n const { data, error } = await from().select('*').eq('id', id).maybeSingle();\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return null; }\n throw error;\n }\n return data ?? null;\n },\n async read(id) {\n const { data, error } = await from().select('*').eq('id', id).maybeSingle();\n if (error) {\n if (isMissingTableError(error)) { warnMissing(); return null; }\n throw error;\n }\n return data ?? null;\n },\n async create(body) {\n const { data, error } = await from().insert(body).select().single();\n if (error) throw error;\n return data;\n },\n async bulkCreate(rows) {\n if (!rows.length) return [];\n const { data, error } = await from().insert(rows).select();\n if (error) throw error;\n return data ?? [];\n },\n async update(id, body) {\n const { data, error } = await from().update(body).eq('id', id).select().single();\n if (error) throw error;\n return data;\n },\n async bulkUpdate(rows) {\n if (!rows.length) return [];\n // PostgREST has no native multi-patch with per-row payloads; do one\n // round-trip per row. Fine for hundreds — re-evaluate if a caller\n // starts pushing thousands and we need a CTE-based RPC.\n const results = await Promise.all(\n rows.map(({ id, ...patch }) =>\n from().update(patch).eq('id', id).select().single(),\n ),\n );\n const errors = results.map((r) => r.error).filter(Boolean);\n if (errors.length) throw errors[0];\n return results.map((r) => r.data) as any[];\n },\n async updateMany(where, update) {\n // Base44 SDK / Mongo style: `{ $set: { field: value } }` wraps the patch.\n // Unwrap so the same call works whether the caller used $set or a flat object.\n const patch = (update as { $set?: unknown })?.$set ?? update;\n let q = from().update(patch as Record<string, unknown>);\n q = applyFilter(q, where);\n const { data, error } = await q.select();\n if (error) throw error;\n return data ?? [];\n },\n async delete(id) {\n const { error } = await from().delete().eq('id', id);\n if (error) throw error;\n },\n async deleteMany(where) {\n let q = from().delete();\n q = applyFilter(q, where);\n const { error } = await q;\n if (error) throw error;\n },\n subscribe(callback) {\n const channel = client\n .channel(`${mapping.schema}.${mapping.table}.${Math.random().toString(36).slice(2, 8)}`)\n .on(\n 'postgres_changes' as never,\n { event: '*', schema: mapping.schema, table: mapping.table },\n (payload: { eventType: string; new?: unknown; old?: unknown }) => {\n const type = payload.eventType.toLowerCase() as 'insert' | 'update' | 'delete';\n callback({ type, new: payload.new as never, old: payload.old as never });\n },\n )\n .subscribe();\n return () => {\n void client.removeChannel(channel);\n };\n },\n };\n}\n\nexport function makeEntitiesProxy(\n client: SupabaseClient,\n opts: Required<Pick<ClientOptions, 'schemaPrefix'>> &\n Pick<ClientOptions, 'sharedSchema' | 'sharedEntities' | 'entityMap'>,\n): EntitiesProxy {\n const cache: Record<string, EntityApi> = {};\n return new Proxy({} as EntitiesProxy, {\n get(_target, prop: string) {\n if (typeof prop !== 'string') return undefined;\n if (!cache[prop]) {\n const mapping = resolveEntityMapping(prop, opts);\n cache[prop] = makeEntityApi(client, mapping);\n }\n return cache[prop];\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\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":"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","names":["createSupabase"]}
|
package/dist/server.d.cts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
-
import { a as EntitiesProxy,
|
|
3
|
-
export { b as EntityApi, E as EntityMapping, F as FilterObject, c as FilterValue, J as Json, M as MongoFilter, O as OrderBy } from './types-
|
|
2
|
+
import { C as ClientOptions, a as EntitiesProxy, m as makeFunctions } from './types-CnrxaSFp.cjs';
|
|
3
|
+
export { b as EntityApi, E as EntityMapping, F as FilterObject, c as FilterValue, J as Json, M as MongoFilter, O as OrderBy } from './types-CnrxaSFp.cjs';
|
|
4
|
+
import { IntegrationsOptions, makeIntegrations } from './integrations.cjs';
|
|
4
5
|
|
|
5
6
|
interface ServerClient {
|
|
6
7
|
supabase: SupabaseClient;
|
|
7
8
|
entities: EntitiesProxy;
|
|
9
|
+
functions: ReturnType<typeof makeFunctions>;
|
|
10
|
+
integrations: ReturnType<typeof makeIntegrations>;
|
|
8
11
|
asServiceRole: {
|
|
9
12
|
entities: EntitiesProxy;
|
|
13
|
+
functions: ReturnType<typeof makeFunctions>;
|
|
14
|
+
integrations: ReturnType<typeof makeIntegrations>;
|
|
10
15
|
};
|
|
11
16
|
}
|
|
17
|
+
interface CreateServerClientOptions extends Omit<ClientOptions, 'client'> {
|
|
18
|
+
supabaseServiceRoleKey: string;
|
|
19
|
+
/** Integration stub config (edge function names for SendEmail / InvokeLLM / GenerateImage). */
|
|
20
|
+
integrations?: Partial<IntegrationsOptions>;
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Create a Base44-style client from an incoming HTTP Request, intended for
|
|
14
24
|
* Supabase Edge Functions (Deno) or any server runtime that has fetch Request.
|
|
@@ -16,9 +26,11 @@ interface ServerClient {
|
|
|
16
26
|
* Honors the caller's Authorization header so RLS applies as the end user.
|
|
17
27
|
* `asServiceRole` uses the configured service_role key (bypasses RLS) for
|
|
18
28
|
* privileged operations — analogous to base44.asServiceRole.
|
|
29
|
+
*
|
|
30
|
+
* Both the user and service-role sides expose `entities`, `functions`, and
|
|
31
|
+
* `integrations.Core` so ported edge functions can call whichever surface they
|
|
32
|
+
* used against Base44's managed backend.
|
|
19
33
|
*/
|
|
20
|
-
declare function createClientFromRequest(req: Request, options:
|
|
21
|
-
supabaseServiceRoleKey: string;
|
|
22
|
-
}): ServerClient;
|
|
34
|
+
declare function createClientFromRequest(req: Request, options: CreateServerClientOptions): ServerClient;
|
|
23
35
|
|
|
24
|
-
export { ClientOptions, EntitiesProxy, type ServerClient, createClientFromRequest };
|
|
36
|
+
export { ClientOptions, type CreateServerClientOptions, EntitiesProxy, type ServerClient, createClientFromRequest };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
-
import { a as EntitiesProxy,
|
|
3
|
-
export { b as EntityApi, E as EntityMapping, F as FilterObject, c as FilterValue, J as Json, M as MongoFilter, O as OrderBy } from './types-
|
|
2
|
+
import { C as ClientOptions, a as EntitiesProxy, m as makeFunctions } from './types-CnrxaSFp.js';
|
|
3
|
+
export { b as EntityApi, E as EntityMapping, F as FilterObject, c as FilterValue, J as Json, M as MongoFilter, O as OrderBy } from './types-CnrxaSFp.js';
|
|
4
|
+
import { IntegrationsOptions, makeIntegrations } from './integrations.js';
|
|
4
5
|
|
|
5
6
|
interface ServerClient {
|
|
6
7
|
supabase: SupabaseClient;
|
|
7
8
|
entities: EntitiesProxy;
|
|
9
|
+
functions: ReturnType<typeof makeFunctions>;
|
|
10
|
+
integrations: ReturnType<typeof makeIntegrations>;
|
|
8
11
|
asServiceRole: {
|
|
9
12
|
entities: EntitiesProxy;
|
|
13
|
+
functions: ReturnType<typeof makeFunctions>;
|
|
14
|
+
integrations: ReturnType<typeof makeIntegrations>;
|
|
10
15
|
};
|
|
11
16
|
}
|
|
17
|
+
interface CreateServerClientOptions extends Omit<ClientOptions, 'client'> {
|
|
18
|
+
supabaseServiceRoleKey: string;
|
|
19
|
+
/** Integration stub config (edge function names for SendEmail / InvokeLLM / GenerateImage). */
|
|
20
|
+
integrations?: Partial<IntegrationsOptions>;
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Create a Base44-style client from an incoming HTTP Request, intended for
|
|
14
24
|
* Supabase Edge Functions (Deno) or any server runtime that has fetch Request.
|
|
@@ -16,9 +26,11 @@ interface ServerClient {
|
|
|
16
26
|
* Honors the caller's Authorization header so RLS applies as the end user.
|
|
17
27
|
* `asServiceRole` uses the configured service_role key (bypasses RLS) for
|
|
18
28
|
* privileged operations — analogous to base44.asServiceRole.
|
|
29
|
+
*
|
|
30
|
+
* Both the user and service-role sides expose `entities`, `functions`, and
|
|
31
|
+
* `integrations.Core` so ported edge functions can call whichever surface they
|
|
32
|
+
* used against Base44's managed backend.
|
|
19
33
|
*/
|
|
20
|
-
declare function createClientFromRequest(req: Request, options:
|
|
21
|
-
supabaseServiceRoleKey: string;
|
|
22
|
-
}): ServerClient;
|
|
34
|
+
declare function createClientFromRequest(req: Request, options: CreateServerClientOptions): ServerClient;
|
|
23
35
|
|
|
24
|
-
export { ClientOptions, EntitiesProxy, type ServerClient, createClientFromRequest };
|
|
36
|
+
export { ClientOptions, type CreateServerClientOptions, EntitiesProxy, type ServerClient, createClientFromRequest };
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
makeEntitiesProxy
|
|
3
|
-
|
|
2
|
+
makeEntitiesProxy,
|
|
3
|
+
makeFunctions
|
|
4
|
+
} from "./chunk-YQ3BDCIS.js";
|
|
5
|
+
import {
|
|
6
|
+
makeIntegrations
|
|
7
|
+
} from "./chunk-E2KG6ZL4.js";
|
|
4
8
|
|
|
5
9
|
// src/server.ts
|
|
6
10
|
import { createClient as createSupabase } from "@supabase/supabase-js";
|
|
@@ -24,11 +28,21 @@ function createClientFromRequest(req, options) {
|
|
|
24
28
|
sharedEntities: options.sharedEntities,
|
|
25
29
|
entityMap: options.entityMap
|
|
26
30
|
};
|
|
31
|
+
const integrationsOpts = {
|
|
32
|
+
defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,
|
|
33
|
+
sendEmailFunction: options.integrations?.sendEmailFunction,
|
|
34
|
+
invokeLlmFunction: options.integrations?.invokeLlmFunction,
|
|
35
|
+
generateImageFunction: options.integrations?.generateImageFunction
|
|
36
|
+
};
|
|
27
37
|
return {
|
|
28
38
|
supabase: userClient,
|
|
29
39
|
entities: makeEntitiesProxy(userClient, mappingOpts),
|
|
40
|
+
functions: makeFunctions(userClient),
|
|
41
|
+
integrations: makeIntegrations(userClient, integrationsOpts),
|
|
30
42
|
asServiceRole: {
|
|
31
|
-
entities: makeEntitiesProxy(serviceClient, mappingOpts)
|
|
43
|
+
entities: makeEntitiesProxy(serviceClient, mappingOpts),
|
|
44
|
+
functions: makeFunctions(serviceClient),
|
|
45
|
+
integrations: makeIntegrations(serviceClient, integrationsOpts)
|
|
32
46
|
}
|
|
33
47
|
};
|
|
34
48
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeEntitiesProxy } from './entities.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\n\nexport interface ServerClient {\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n asServiceRole: {
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';\nimport { makeEntitiesProxy } from './entities.js';\nimport { makeFunctions } from './functions.js';\nimport { makeIntegrations, type IntegrationsOptions } from './integrations.js';\nimport type { ClientOptions, EntitiesProxy } from './types.js';\n\nexport type * from './types.js';\n\nexport interface ServerClient {\n supabase: SupabaseClient;\n entities: EntitiesProxy;\n functions: ReturnType<typeof makeFunctions>;\n integrations: ReturnType<typeof makeIntegrations>;\n asServiceRole: {\n entities: EntitiesProxy;\n functions: ReturnType<typeof makeFunctions>;\n integrations: ReturnType<typeof makeIntegrations>;\n };\n}\n\nexport interface CreateServerClientOptions\n extends Omit<ClientOptions, 'client'> {\n supabaseServiceRoleKey: string;\n /** Integration stub config (edge function names for SendEmail / InvokeLLM / GenerateImage). */\n integrations?: Partial<IntegrationsOptions>;\n}\n\n/**\n * Create a Base44-style client from an incoming HTTP Request, intended for\n * Supabase Edge Functions (Deno) or any server runtime that has fetch Request.\n *\n * Honors the caller's Authorization header so RLS applies as the end user.\n * `asServiceRole` uses the configured service_role key (bypasses RLS) for\n * privileged operations — analogous to base44.asServiceRole.\n *\n * Both the user and service-role sides expose `entities`, `functions`, and\n * `integrations.Core` so ported edge functions can call whichever surface they\n * used against Base44's managed backend.\n */\nexport function createClientFromRequest(\n req: Request,\n options: CreateServerClientOptions,\n): ServerClient {\n if (!options.supabaseUrl) throw new Error('createClientFromRequest: supabaseUrl is required');\n if (!options.supabaseAnonKey)\n throw new Error('createClientFromRequest: supabaseAnonKey is required');\n if (!options.supabaseServiceRoleKey)\n throw new Error('createClientFromRequest: supabaseServiceRoleKey is required for server use');\n\n const authHeader = req.headers.get('Authorization') ?? '';\n const userClient = createSupabase(options.supabaseUrl, options.supabaseAnonKey, {\n global: { headers: { Authorization: authHeader } },\n auth: { persistSession: false, autoRefreshToken: false },\n });\n const serviceClient = createSupabase(options.supabaseUrl, options.supabaseServiceRoleKey, {\n auth: { persistSession: false, autoRefreshToken: false },\n });\n\n const mappingOpts = {\n schemaPrefix: options.schemaPrefix,\n sharedSchema: options.sharedSchema,\n sharedEntities: options.sharedEntities,\n entityMap: options.entityMap,\n };\n\n const integrationsOpts: IntegrationsOptions = {\n defaultBucket: options.integrations?.defaultBucket ?? options.schemaPrefix,\n sendEmailFunction: options.integrations?.sendEmailFunction,\n invokeLlmFunction: options.integrations?.invokeLlmFunction,\n generateImageFunction: options.integrations?.generateImageFunction,\n };\n\n return {\n supabase: userClient,\n entities: makeEntitiesProxy(userClient, mappingOpts),\n functions: makeFunctions(userClient),\n integrations: makeIntegrations(userClient, integrationsOpts),\n asServiceRole: {\n entities: makeEntitiesProxy(serviceClient, mappingOpts),\n functions: makeFunctions(serviceClient),\n integrations: makeIntegrations(serviceClient, integrationsOpts),\n },\n };\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,gBAAgB,sBAA2C;AAuC7D,SAAS,wBACd,KACA,SACc;AACd,MAAI,CAAC,QAAQ,YAAa,OAAM,IAAI,MAAM,kDAAkD;AAC5F,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,sDAAsD;AACxE,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4EAA4E;AAE9F,QAAM,aAAa,IAAI,QAAQ,IAAI,eAAe,KAAK;AACvD,QAAM,aAAa,eAAe,QAAQ,aAAa,QAAQ,iBAAiB;AAAA,IAC9E,QAAQ,EAAE,SAAS,EAAE,eAAe,WAAW,EAAE;AAAA,IACjD,MAAM,EAAE,gBAAgB,OAAO,kBAAkB,MAAM;AAAA,EACzD,CAAC;AACD,QAAM,gBAAgB,eAAe,QAAQ,aAAa,QAAQ,wBAAwB;AAAA,IACxF,MAAM,EAAE,gBAAgB,OAAO,kBAAkB,MAAM;AAAA,EACzD,CAAC;AAED,QAAM,cAAc;AAAA,IAClB,cAAc,QAAQ;AAAA,IACtB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,EACrB;AAEA,QAAM,mBAAwC;AAAA,IAC5C,eAAe,QAAQ,cAAc,iBAAiB,QAAQ;AAAA,IAC9D,mBAAmB,QAAQ,cAAc;AAAA,IACzC,mBAAmB,QAAQ,cAAc;AAAA,IACzC,uBAAuB,QAAQ,cAAc;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,UAAU,kBAAkB,YAAY,WAAW;AAAA,IACnD,WAAW,cAAc,UAAU;AAAA,IACnC,cAAc,iBAAiB,YAAY,gBAAgB;AAAA,IAC3D,eAAe;AAAA,MACb,UAAU,kBAAkB,eAAe,WAAW;AAAA,MACtD,WAAW,cAAc,aAAa;AAAA,MACtC,cAAc,iBAAiB,eAAe,gBAAgB;AAAA,IAChE;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
2
|
|
|
3
|
+
/** Mirror of base44.functions — Supabase Edge Functions invoke wrapper.
|
|
4
|
+
*
|
|
5
|
+
* Returns the raw body. On HTTP error, throws an Error with the response body attached.
|
|
6
|
+
*/
|
|
7
|
+
declare function makeFunctions(client: SupabaseClient): {
|
|
8
|
+
/** Invoke an edge function by name, passing JSON body. Returns parsed JSON. */
|
|
9
|
+
invoke<T = unknown>(name: string, payload?: Record<string, unknown>): Promise<T>;
|
|
10
|
+
/** Lower-level: invoke and return Response so caller can handle non-JSON. */
|
|
11
|
+
fetch(name: string, init?: RequestInit): Promise<Response>;
|
|
12
|
+
};
|
|
13
|
+
|
|
3
14
|
type Json = string | number | boolean | null | Json[] | {
|
|
4
15
|
[key: string]: Json;
|
|
5
16
|
};
|
|
@@ -112,4 +123,4 @@ type EntitiesProxy = {
|
|
|
112
123
|
[entityName: string]: EntityApi;
|
|
113
124
|
};
|
|
114
125
|
|
|
115
|
-
export type
|
|
126
|
+
export { type ClientOptions as C, type EntityMapping as E, type FilterObject as F, type Json as J, type MongoFilter as M, type OrderBy as O, type EntitiesProxy as a, type EntityApi as b, type FilterValue as c, makeFunctions as m };
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
2
|
|
|
3
|
+
/** Mirror of base44.functions — Supabase Edge Functions invoke wrapper.
|
|
4
|
+
*
|
|
5
|
+
* Returns the raw body. On HTTP error, throws an Error with the response body attached.
|
|
6
|
+
*/
|
|
7
|
+
declare function makeFunctions(client: SupabaseClient): {
|
|
8
|
+
/** Invoke an edge function by name, passing JSON body. Returns parsed JSON. */
|
|
9
|
+
invoke<T = unknown>(name: string, payload?: Record<string, unknown>): Promise<T>;
|
|
10
|
+
/** Lower-level: invoke and return Response so caller can handle non-JSON. */
|
|
11
|
+
fetch(name: string, init?: RequestInit): Promise<Response>;
|
|
12
|
+
};
|
|
13
|
+
|
|
3
14
|
type Json = string | number | boolean | null | Json[] | {
|
|
4
15
|
[key: string]: Json;
|
|
5
16
|
};
|
|
@@ -112,4 +123,4 @@ type EntitiesProxy = {
|
|
|
112
123
|
[entityName: string]: EntityApi;
|
|
113
124
|
};
|
|
114
125
|
|
|
115
|
-
export type
|
|
126
|
+
export { type ClientOptions as C, type EntityMapping as E, type FilterObject as F, type Json as J, type MongoFilter as M, type OrderBy as O, type EntitiesProxy as a, type EntityApi as b, type FilterValue as c, makeFunctions as m };
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staticbot/base44-supabase-shim",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Drop-in shim mimicking @base44/sdk API but routing to a Supabase backend.
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Drop-in shim mimicking @base44/sdk API but routing to a Supabase backend. Vendored into migrated apps by Staticbot's Base44 native migration so the customer's build doesn't need a live npm connection.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
7
10
|
"repository": {
|
|
8
11
|
"type": "git",
|
|
9
12
|
"url": "https://github.com/staticbot/staticbot-base44-supabase-shim.git"
|
|
@@ -35,7 +38,8 @@
|
|
|
35
38
|
"dev": "tsup --watch",
|
|
36
39
|
"typecheck": "tsc --noEmit",
|
|
37
40
|
"test": "vitest run",
|
|
38
|
-
"test:watch": "vitest"
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"prepack": "npm run typecheck && npm run test && npm run build"
|
|
39
43
|
},
|
|
40
44
|
"peerDependencies": {
|
|
41
45
|
"@supabase/supabase-js": "^2.45.0"
|
package/src/agents.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stub of `base44.agents.*`. Base44 hosts an "agents" concept with WhatsApp/
|
|
3
|
+
* Telegram bridges that don't exist in self-host by default — this module
|
|
4
|
+
* exists so migrated apps referencing `base44.agents.getWhatsAppConnectURL(...)`
|
|
5
|
+
* don't `TypeError` at runtime. Default behavior returns null so <a href={...}>
|
|
6
|
+
* usages render as an unclickable button (feature visibly disabled).
|
|
7
|
+
*
|
|
8
|
+
* If a customer wires their own WhatsApp gateway, pass per-agent URLs via
|
|
9
|
+
* createClient({ agents: { whatsappUrls: { SubdomainReviewer: 'https://…' } } }).
|
|
10
|
+
*/
|
|
11
|
+
export interface AgentsOptions {
|
|
12
|
+
/** Per-agent WhatsApp connect URLs. Absent entries return null. */
|
|
13
|
+
whatsappUrls?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function makeAgents(opts: AgentsOptions = {}) {
|
|
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: string): string | null {
|
|
25
|
+
return opts.whatsappUrls?.[agentName] ?? null;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
package/src/auth.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
1
|
+
import type { Provider, SupabaseClient } from '@supabase/supabase-js';
|
|
2
2
|
|
|
3
3
|
export interface SignInArgs {
|
|
4
4
|
email: string;
|
|
@@ -11,14 +11,42 @@ export interface SignUpArgs {
|
|
|
11
11
|
metadata?: Record<string, unknown>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export interface VerifyOtpArgs {
|
|
15
|
+
email: string;
|
|
16
|
+
otpCode: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ResetPasswordArgs {
|
|
20
|
+
/**
|
|
21
|
+
* Reset token from the email link. Ignored by this shim — Supabase already
|
|
22
|
+
* exchanged the link fragment for a session before the app got here, so
|
|
23
|
+
* `updateUser({password})` operates on that session. Kept in the signature
|
|
24
|
+
* for source-compat with @base44/sdk callers.
|
|
25
|
+
*/
|
|
26
|
+
resetToken?: string;
|
|
27
|
+
newPassword: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ResetPasswordRequestOptions {
|
|
31
|
+
/** URL Supabase redirects to after the user clicks the reset link. */
|
|
32
|
+
redirectTo?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
export interface AuthOptions {
|
|
15
36
|
/**
|
|
16
37
|
* Browser path the redirectToLogin() shim should send users to.
|
|
17
38
|
* Default: '/login'.
|
|
18
39
|
*/
|
|
19
40
|
loginPath?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Default redirect URL for password-reset emails. Callers can still override
|
|
43
|
+
* per-call via resetPasswordRequest(email, { redirectTo }).
|
|
44
|
+
*/
|
|
45
|
+
resetPasswordRedirect?: string;
|
|
20
46
|
}
|
|
21
47
|
|
|
48
|
+
let setTokenWarned = false;
|
|
49
|
+
|
|
22
50
|
export function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {
|
|
23
51
|
const loginPath = opts.loginPath ?? '/login';
|
|
24
52
|
|
|
@@ -28,6 +56,12 @@ export function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {
|
|
|
28
56
|
if (error) throw error;
|
|
29
57
|
return data;
|
|
30
58
|
},
|
|
59
|
+
/** Base44 alias for signIn. */
|
|
60
|
+
async loginViaEmailPassword(email: string, password: string) {
|
|
61
|
+
const { data, error } = await client.auth.signInWithPassword({ email, password });
|
|
62
|
+
if (error) throw error;
|
|
63
|
+
return data;
|
|
64
|
+
},
|
|
31
65
|
async signUp({ email, password, metadata }: SignUpArgs) {
|
|
32
66
|
const { data, error } = await client.auth.signUp({
|
|
33
67
|
email,
|
|
@@ -37,14 +71,105 @@ export function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {
|
|
|
37
71
|
if (error) throw error;
|
|
38
72
|
return data;
|
|
39
73
|
},
|
|
74
|
+
/** Base44 alias for signUp. */
|
|
75
|
+
async register({ email, password, metadata }: SignUpArgs) {
|
|
76
|
+
const { data, error } = await client.auth.signUp({
|
|
77
|
+
email,
|
|
78
|
+
password,
|
|
79
|
+
options: { data: metadata ?? {} },
|
|
80
|
+
});
|
|
81
|
+
if (error) throw error;
|
|
82
|
+
return data;
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* Base44 OAuth flow: redirects the browser to the provider's consent screen
|
|
86
|
+
* and back to `returnPath` (relative to window.location.origin) on success.
|
|
87
|
+
* Supabase equivalent: signInWithOAuth with an absolute redirectTo.
|
|
88
|
+
*/
|
|
89
|
+
async loginWithProvider(provider: Provider, returnPath?: string) {
|
|
90
|
+
const redirectTo =
|
|
91
|
+
typeof window !== 'undefined'
|
|
92
|
+
? window.location.origin + (returnPath ?? '/')
|
|
93
|
+
: returnPath;
|
|
94
|
+
const { data, error } = await client.auth.signInWithOAuth({
|
|
95
|
+
provider,
|
|
96
|
+
options: redirectTo ? { redirectTo } : undefined,
|
|
97
|
+
});
|
|
98
|
+
if (error) throw error;
|
|
99
|
+
return data;
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Base44 email OTP verification after register(). Supabase's verifyOtp
|
|
103
|
+
* already sets the session on success, so setToken() is redundant afterward
|
|
104
|
+
* (kept as a soft no-op for source-compat).
|
|
105
|
+
*/
|
|
106
|
+
async verifyOtp({ email, otpCode }: VerifyOtpArgs) {
|
|
107
|
+
const { data, error } = await client.auth.verifyOtp({
|
|
108
|
+
email,
|
|
109
|
+
token: otpCode,
|
|
110
|
+
type: 'signup',
|
|
111
|
+
});
|
|
112
|
+
if (error) throw error;
|
|
113
|
+
// Base44's return shape included `access_token` at the top level; expose
|
|
114
|
+
// both that and the session/user so callers can pick either style.
|
|
115
|
+
return {
|
|
116
|
+
access_token: data.session?.access_token,
|
|
117
|
+
session: data.session,
|
|
118
|
+
user: data.user,
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
async resendOtp(email: string) {
|
|
122
|
+
const { error } = await client.auth.resend({ email, type: 'signup' });
|
|
123
|
+
if (error) throw error;
|
|
124
|
+
},
|
|
125
|
+
/**
|
|
126
|
+
* No-op alias kept so migrated code doesn't TypeError. Supabase's
|
|
127
|
+
* verifyOtp() already installed the session — pushing the access_token in
|
|
128
|
+
* again would do nothing productive (Supabase requires access + refresh to
|
|
129
|
+
* setSession, and Base44 returns only access). Warns once per process.
|
|
130
|
+
*/
|
|
131
|
+
setToken(_accessToken: string) {
|
|
132
|
+
if (!setTokenWarned) {
|
|
133
|
+
setTokenWarned = true;
|
|
134
|
+
if (typeof console !== 'undefined') {
|
|
135
|
+
console.warn(
|
|
136
|
+
'[base44-shim] auth.setToken() is a no-op — verifyOtp()/signInWithPassword() ' +
|
|
137
|
+
'already installed the Supabase session. Safe to remove the call.',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
async resetPasswordRequest(email: string, options?: ResetPasswordRequestOptions) {
|
|
143
|
+
const redirectTo = options?.redirectTo ?? opts.resetPasswordRedirect;
|
|
144
|
+
const { error } = await client.auth.resetPasswordForEmail(
|
|
145
|
+
email,
|
|
146
|
+
redirectTo ? { redirectTo } : undefined,
|
|
147
|
+
);
|
|
148
|
+
if (error) throw error;
|
|
149
|
+
},
|
|
150
|
+
async resetPassword({ newPassword }: ResetPasswordArgs) {
|
|
151
|
+
const { data, error } = await client.auth.updateUser({ password: newPassword });
|
|
152
|
+
if (error) throw error;
|
|
153
|
+
return data;
|
|
154
|
+
},
|
|
40
155
|
async signOut() {
|
|
41
156
|
const { error } = await client.auth.signOut();
|
|
42
157
|
if (error) throw error;
|
|
43
158
|
},
|
|
44
|
-
/**
|
|
45
|
-
|
|
159
|
+
/**
|
|
160
|
+
* Base44 alias for signOut. If `returnUrl` is provided, navigates there
|
|
161
|
+
* after signOut resolves so SPAs can drop users on a public route.
|
|
162
|
+
*/
|
|
163
|
+
async logout(returnUrl?: string) {
|
|
46
164
|
const { error } = await client.auth.signOut();
|
|
47
165
|
if (error) throw error;
|
|
166
|
+
if (returnUrl && typeof window !== 'undefined') {
|
|
167
|
+
window.location.assign(returnUrl);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
async isAuthenticated(): Promise<boolean> {
|
|
171
|
+
const { data } = await client.auth.getSession();
|
|
172
|
+
return !!data.session;
|
|
48
173
|
},
|
|
49
174
|
async getUser() {
|
|
50
175
|
const { data, error } = await client.auth.getUser();
|
|
@@ -99,3 +224,8 @@ export function makeAuth(client: SupabaseClient, opts: AuthOptions = {}) {
|
|
|
99
224
|
},
|
|
100
225
|
};
|
|
101
226
|
}
|
|
227
|
+
|
|
228
|
+
/** Test-only: reset the process-global warn-once state so multiple tests can assert it. */
|
|
229
|
+
export function __resetSetTokenWarnedForTests() {
|
|
230
|
+
setTokenWarned = false;
|
|
231
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createClient as createSupabase, type SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
import { makeAgents, type AgentsOptions } from './agents.js';
|
|
2
3
|
import { makeAuth, type AuthOptions } from './auth.js';
|
|
3
4
|
import { makeEntitiesProxy } from './entities.js';
|
|
4
5
|
import { makeFunctions } from './functions.js';
|
|
@@ -8,6 +9,7 @@ import { makeStorage } from './storage.js';
|
|
|
8
9
|
import type { ClientOptions, EntitiesProxy } from './types.js';
|
|
9
10
|
|
|
10
11
|
export type * from './types.js';
|
|
12
|
+
export type { AgentsOptions } from './agents.js';
|
|
11
13
|
export { defaultEntityToTable, resolveEntityMapping, parseOrderBy } from './entities.js';
|
|
12
14
|
|
|
13
15
|
export interface ExtendedClientOptions extends ClientOptions {
|
|
@@ -15,6 +17,8 @@ export interface ExtendedClientOptions extends ClientOptions {
|
|
|
15
17
|
authOptions?: AuthOptions;
|
|
16
18
|
/** Integration stub configuration (storage default bucket, edge function names). */
|
|
17
19
|
integrations?: Partial<IntegrationsOptions>;
|
|
20
|
+
/** Agents stub configuration (per-agent WhatsApp connect URLs, etc.). */
|
|
21
|
+
agents?: AgentsOptions;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
export interface Base44Client {
|
|
@@ -31,6 +35,8 @@ export interface Base44Client {
|
|
|
31
35
|
users: ReturnType<typeof makeUsers>;
|
|
32
36
|
/** Empty placeholder for base44.app property access. */
|
|
33
37
|
app: Record<string, unknown>;
|
|
38
|
+
/** Base44 agents stub — WhatsApp/Telegram bridges disabled by default. */
|
|
39
|
+
agents: ReturnType<typeof makeAgents>;
|
|
34
40
|
/** Service-role-scoped namespace for trusted server contexts. Throws if no service key supplied. */
|
|
35
41
|
asServiceRole: { entities: EntitiesProxy };
|
|
36
42
|
}
|
|
@@ -92,6 +98,7 @@ export function createClient(options: ExtendedClientOptions): Base44Client {
|
|
|
92
98
|
appLogs: makeAppLogs(supabase, options.schemaPrefix),
|
|
93
99
|
users: makeUsers(),
|
|
94
100
|
app,
|
|
101
|
+
agents: makeAgents(options.agents),
|
|
95
102
|
asServiceRole,
|
|
96
103
|
};
|
|
97
104
|
}
|
package/src/integrations.ts
CHANGED
|
@@ -13,18 +13,26 @@ export 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
24
|
/**
|
|
19
|
-
* Stub of `base44.integrations.Core.*`.
|
|
25
|
+
* Stub of `base44.integrations.Core.*`. Four methods are implemented:
|
|
20
26
|
*
|
|
21
|
-
* UploadFile
|
|
22
|
-
* SendEmail
|
|
23
|
-
* InvokeLLM
|
|
27
|
+
* UploadFile → delegates to Supabase Storage upload + returns {url, path}.
|
|
28
|
+
* SendEmail → invokes a configured edge function (or throws if none).
|
|
29
|
+
* InvokeLLM → invokes a configured edge function (or throws if none).
|
|
30
|
+
* GenerateImage → invokes a configured edge function (or throws if none).
|
|
24
31
|
*
|
|
25
|
-
* Air-gapped LAN cannot call OpenAI directly; wire your own LLM endpoint
|
|
32
|
+
* Air-gapped LAN cannot call OpenAI directly; wire your own LLM/image endpoint
|
|
26
33
|
* (Ollama, internal API gateway, etc.) inside an edge function and pass the
|
|
27
|
-
* function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay'
|
|
34
|
+
* function name via createClient({ integrations: { invokeLlmFunction: 'llm-relay',
|
|
35
|
+
* generateImageFunction: 'image-relay' } }).
|
|
28
36
|
*/
|
|
29
37
|
export function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptions) {
|
|
30
38
|
const Core = {
|
|
@@ -88,6 +96,24 @@ export function makeIntegrations(client: SupabaseClient, opts: IntegrationsOptio
|
|
|
88
96
|
if (error) throw error;
|
|
89
97
|
return data;
|
|
90
98
|
},
|
|
99
|
+
|
|
100
|
+
async GenerateImage(payload: {
|
|
101
|
+
prompt: string;
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
}): Promise<unknown> {
|
|
104
|
+
if (!opts.generateImageFunction) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
'GenerateImage not configured. Image-gen features are disabled in this self-host ' +
|
|
107
|
+
'build. Set integrations.generateImageFunction in createClient() and deploy an ' +
|
|
108
|
+
'edge function that proxies to your image endpoint (SDXL / DALL·E gateway).',
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const { data, error } = await client.functions.invoke(opts.generateImageFunction, {
|
|
112
|
+
body: payload,
|
|
113
|
+
});
|
|
114
|
+
if (error) throw error;
|
|
115
|
+
return data;
|
|
116
|
+
},
|
|
91
117
|
};
|
|
92
118
|
|
|
93
119
|
return { Core };
|